Rewrite the wrap checks to deal with gcc 4.x optimisations.
[Samba.git] / source / smbd / trans2.c
blob709eb39dd8dcc3467d43bfd31cdf156eddf6d424
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
28 extern int max_send;
29 extern enum protocol_types Protocol;
30 extern uint32 global_client_caps;
31 extern struct current_user current_user;
33 #define get_file_size(sbuf) ((sbuf).st_size)
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
36 static char *store_file_unix_basic(connection_struct *conn,
37 char *pdata,
38 files_struct *fsp,
39 const SMB_STRUCT_STAT *psbuf);
41 static char *store_file_unix_basic_info2(connection_struct *conn,
42 char *pdata,
43 files_struct *fsp,
44 const SMB_STRUCT_STAT *psbuf);
46 /********************************************************************
47 Roundup a value to the nearest allocation roundup size boundary.
48 Only do this for Windows clients.
49 ********************************************************************/
51 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
53 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
55 /* Only roundup for Windows clients. */
56 enum remote_arch_types ra_type = get_remote_arch();
57 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
58 val = SMB_ROUNDUP(val,rval);
60 return val;
63 /********************************************************************
64 Given a stat buffer return the allocated size on disk, taking into
65 account sparse files.
66 ********************************************************************/
68 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
70 SMB_BIG_UINT ret;
72 if(S_ISDIR(sbuf->st_mode)) {
73 return 0;
76 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
77 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
78 #else
79 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
80 #endif
82 if (fsp && fsp->initial_allocation_size)
83 ret = MAX(ret,fsp->initial_allocation_size);
85 return smb_roundup(conn, ret);
88 /****************************************************************************
89 Utility functions for dealing with extended attributes.
90 ****************************************************************************/
92 /****************************************************************************
93 Refuse to allow clients to overwrite our private xattrs.
94 ****************************************************************************/
96 static bool samba_private_attr_name(const char *unix_ea_name)
98 static const char *prohibited_ea_names[] = {
99 SAMBA_POSIX_INHERITANCE_EA_NAME,
100 SAMBA_XATTR_DOS_ATTRIB,
101 NULL
104 int i;
106 for (i = 0; prohibited_ea_names[i]; i++) {
107 if (strequal( prohibited_ea_names[i], unix_ea_name))
108 return true;
110 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
111 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
112 return true;
114 return false;
117 /****************************************************************************
118 Get one EA value. Fill in a struct ea_struct.
119 ****************************************************************************/
121 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
122 files_struct *fsp, const char *fname,
123 const char *ea_name, struct ea_struct *pea)
125 /* Get the value of this xattr. Max size is 64k. */
126 size_t attr_size = 256;
127 char *val = NULL;
128 ssize_t sizeret;
130 again:
132 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
133 if (!val) {
134 return NT_STATUS_NO_MEMORY;
137 if (fsp && fsp->fh->fd != -1) {
138 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
139 } else {
140 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
143 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
144 attr_size = 65536;
145 goto again;
148 if (sizeret == -1) {
149 return map_nt_error_from_unix(errno);
152 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
153 dump_data(10, (uint8 *)val, sizeret);
155 pea->flags = 0;
156 if (strnequal(ea_name, "user.", 5)) {
157 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
158 } else {
159 pea->name = talloc_strdup(mem_ctx, ea_name);
161 if (pea->name == NULL) {
162 TALLOC_FREE(val);
163 return NT_STATUS_NO_MEMORY;
165 pea->value.data = (unsigned char *)val;
166 pea->value.length = (size_t)sizeret;
167 return NT_STATUS_OK;
170 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
171 files_struct *fsp, const char *fname,
172 char ***pnames, size_t *pnum_names)
174 /* Get a list of all xattrs. Max namesize is 64k. */
175 size_t ea_namelist_size = 1024;
176 char *ea_namelist = NULL;
178 char *p;
179 char **names, **tmp;
180 size_t num_names;
181 ssize_t sizeret;
183 if (!lp_ea_support(SNUM(conn))) {
184 *pnames = NULL;
185 *pnum_names = 0;
186 return NT_STATUS_OK;
190 * TALLOC the result early to get the talloc hierarchy right.
193 names = TALLOC_ARRAY(mem_ctx, char *, 1);
194 if (names == NULL) {
195 DEBUG(0, ("talloc failed\n"));
196 return NT_STATUS_NO_MEMORY;
199 while (ea_namelist_size <= 65536) {
201 ea_namelist = TALLOC_REALLOC_ARRAY(
202 names, ea_namelist, char, ea_namelist_size);
203 if (ea_namelist == NULL) {
204 DEBUG(0, ("talloc failed\n"));
205 TALLOC_FREE(names);
206 return NT_STATUS_NO_MEMORY;
209 if (fsp && fsp->fh->fd != -1) {
210 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
211 ea_namelist_size);
212 } else {
213 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
214 ea_namelist_size);
217 if ((sizeret == -1) && (errno == ERANGE)) {
218 ea_namelist_size *= 2;
220 else {
221 break;
225 if (sizeret == -1) {
226 TALLOC_FREE(names);
227 return map_nt_error_from_unix(errno);
230 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
231 (unsigned int)sizeret));
233 if (sizeret == 0) {
234 TALLOC_FREE(names);
235 *pnames = NULL;
236 *pnum_names = 0;
237 return NT_STATUS_OK;
241 * Ensure the result is 0-terminated
244 if (ea_namelist[sizeret-1] != '\0') {
245 TALLOC_FREE(names);
246 return NT_STATUS_INTERNAL_ERROR;
250 * count the names
252 num_names = 0;
254 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
255 num_names += 1;
258 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
259 if (tmp == NULL) {
260 DEBUG(0, ("talloc failed\n"));
261 TALLOC_FREE(names);
262 return NT_STATUS_NO_MEMORY;
265 names = tmp;
266 num_names = 0;
268 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
269 names[num_names++] = p;
272 *pnames = names;
273 *pnum_names = num_names;
274 return NT_STATUS_OK;
277 /****************************************************************************
278 Return a linked list of the total EA's. Plus the total size
279 ****************************************************************************/
281 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
282 const char *fname, size_t *pea_total_len)
284 /* Get a list of all xattrs. Max namesize is 64k. */
285 size_t i, num_names;
286 char **names;
287 struct ea_list *ea_list_head = NULL;
288 NTSTATUS status;
290 *pea_total_len = 0;
292 if (!lp_ea_support(SNUM(conn))) {
293 return NULL;
296 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
297 &names, &num_names);
299 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
300 return NULL;
303 for (i=0; i<num_names; i++) {
304 struct ea_list *listp;
305 fstring dos_ea_name;
307 if (strnequal(names[i], "system.", 7)
308 || samba_private_attr_name(names[i]))
309 continue;
311 listp = TALLOC_P(mem_ctx, struct ea_list);
312 if (listp == NULL) {
313 return NULL;
316 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
317 fname, names[i],
318 &listp->ea))) {
319 return NULL;
322 push_ascii_fstring(dos_ea_name, listp->ea.name);
324 *pea_total_len +=
325 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
327 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
328 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
329 (unsigned int)listp->ea.value.length));
331 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
335 /* Add on 4 for total length. */
336 if (*pea_total_len) {
337 *pea_total_len += 4;
340 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
341 (unsigned int)*pea_total_len));
343 return ea_list_head;
346 /****************************************************************************
347 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
348 that was filled.
349 ****************************************************************************/
351 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
352 connection_struct *conn, struct ea_list *ea_list)
354 unsigned int ret_data_size = 4;
355 char *p = pdata;
357 SMB_ASSERT(total_data_size >= 4);
359 if (!lp_ea_support(SNUM(conn))) {
360 SIVAL(pdata,4,0);
361 return 4;
364 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
365 size_t dos_namelen;
366 fstring dos_ea_name;
367 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
368 dos_namelen = strlen(dos_ea_name);
369 if (dos_namelen > 255 || dos_namelen == 0) {
370 break;
372 if (ea_list->ea.value.length > 65535) {
373 break;
375 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
376 break;
379 /* We know we have room. */
380 SCVAL(p,0,ea_list->ea.flags);
381 SCVAL(p,1,dos_namelen);
382 SSVAL(p,2,ea_list->ea.value.length);
383 fstrcpy(p+4, dos_ea_name);
384 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
386 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
387 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
390 ret_data_size = PTR_DIFF(p, pdata);
391 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
392 SIVAL(pdata,0,ret_data_size);
393 return ret_data_size;
396 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
398 size_t total_ea_len = 0;
399 TALLOC_CTX *mem_ctx = NULL;
401 if (!lp_ea_support(SNUM(conn))) {
402 return 0;
404 mem_ctx = talloc_tos();
405 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
406 return total_ea_len;
409 /****************************************************************************
410 Ensure the EA name is case insensitive by matching any existing EA name.
411 ****************************************************************************/
413 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
415 size_t total_ea_len;
416 TALLOC_CTX *mem_ctx = talloc_tos();
417 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
419 for (; ea_list; ea_list = ea_list->next) {
420 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
421 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
422 &unix_ea_name[5], ea_list->ea.name));
423 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
424 break;
429 /****************************************************************************
430 Set or delete an extended attribute.
431 ****************************************************************************/
433 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
435 if (!lp_ea_support(SNUM(conn))) {
436 return NT_STATUS_EAS_NOT_SUPPORTED;
439 for (;ea_list; ea_list = ea_list->next) {
440 int ret;
441 fstring unix_ea_name;
443 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
444 fstrcat(unix_ea_name, ea_list->ea.name);
446 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
448 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
450 if (samba_private_attr_name(unix_ea_name)) {
451 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
452 return NT_STATUS_ACCESS_DENIED;
455 if (ea_list->ea.value.length == 0) {
456 /* Remove the attribute. */
457 if (fsp && (fsp->fh->fd != -1)) {
458 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
459 unix_ea_name, fsp->fsp_name));
460 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
461 } else {
462 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
463 unix_ea_name, fname));
464 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
466 #ifdef ENOATTR
467 /* Removing a non existent attribute always succeeds. */
468 if (ret == -1 && errno == ENOATTR) {
469 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
470 unix_ea_name));
471 ret = 0;
473 #endif
474 } else {
475 if (fsp && (fsp->fh->fd != -1)) {
476 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
477 unix_ea_name, fsp->fsp_name));
478 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
479 ea_list->ea.value.data, ea_list->ea.value.length, 0);
480 } else {
481 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
482 unix_ea_name, fname));
483 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
484 ea_list->ea.value.data, ea_list->ea.value.length, 0);
488 if (ret == -1) {
489 #ifdef ENOTSUP
490 if (errno == ENOTSUP) {
491 return NT_STATUS_EAS_NOT_SUPPORTED;
493 #endif
494 return map_nt_error_from_unix(errno);
498 return NT_STATUS_OK;
500 /****************************************************************************
501 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
502 ****************************************************************************/
504 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
506 struct ea_list *ea_list_head = NULL;
507 size_t offset = 0;
509 while (offset + 2 < data_size) {
510 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
511 unsigned int namelen = CVAL(pdata,offset);
513 offset++; /* Go past the namelen byte. */
515 /* integer wrap paranioa. */
516 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
517 (offset > data_size) || (namelen > data_size) ||
518 (offset + namelen >= data_size)) {
519 break;
521 /* Ensure the name is null terminated. */
522 if (pdata[offset + namelen] != '\0') {
523 return NULL;
525 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
526 if (!eal->ea.name) {
527 return NULL;
530 offset += (namelen + 1); /* Go past the name + terminating zero. */
531 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
532 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
535 return ea_list_head;
538 /****************************************************************************
539 Read one EA list entry from the buffer.
540 ****************************************************************************/
542 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
544 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
545 uint16 val_len;
546 unsigned int namelen;
548 if (!eal) {
549 return NULL;
552 if (data_size < 6) {
553 return NULL;
556 eal->ea.flags = CVAL(pdata,0);
557 namelen = CVAL(pdata,1);
558 val_len = SVAL(pdata,2);
560 if (4 + namelen + 1 + val_len > data_size) {
561 return NULL;
564 /* Ensure the name is null terminated. */
565 if (pdata[namelen + 4] != '\0') {
566 return NULL;
568 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
569 if (!eal->ea.name) {
570 return NULL;
573 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
574 if (!eal->ea.value.data) {
575 return NULL;
578 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
580 /* Ensure we're null terminated just in case we print the value. */
581 eal->ea.value.data[val_len] = '\0';
582 /* But don't count the null. */
583 eal->ea.value.length--;
585 if (pbytes_used) {
586 *pbytes_used = 4 + namelen + 1 + val_len;
589 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
590 dump_data(10, eal->ea.value.data, eal->ea.value.length);
592 return eal;
595 /****************************************************************************
596 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
597 ****************************************************************************/
599 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
601 struct ea_list *ea_list_head = NULL;
602 size_t offset = 0;
603 size_t bytes_used = 0;
605 while (offset < data_size) {
606 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
608 if (!eal) {
609 return NULL;
612 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
613 offset += bytes_used;
616 return ea_list_head;
619 /****************************************************************************
620 Count the total EA size needed.
621 ****************************************************************************/
623 static size_t ea_list_size(struct ea_list *ealist)
625 fstring dos_ea_name;
626 struct ea_list *listp;
627 size_t ret = 0;
629 for (listp = ealist; listp; listp = listp->next) {
630 push_ascii_fstring(dos_ea_name, listp->ea.name);
631 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
633 /* Add on 4 for total length. */
634 if (ret) {
635 ret += 4;
638 return ret;
641 /****************************************************************************
642 Return a union of EA's from a file list and a list of names.
643 The TALLOC context for the two lists *MUST* be identical as we steal
644 memory from one list to add to another. JRA.
645 ****************************************************************************/
647 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
649 struct ea_list *nlistp, *flistp;
651 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
652 for (flistp = file_list; flistp; flistp = flistp->next) {
653 if (strequal(nlistp->ea.name, flistp->ea.name)) {
654 break;
658 if (flistp) {
659 /* Copy the data from this entry. */
660 nlistp->ea.flags = flistp->ea.flags;
661 nlistp->ea.value = flistp->ea.value;
662 } else {
663 /* Null entry. */
664 nlistp->ea.flags = 0;
665 ZERO_STRUCT(nlistp->ea.value);
669 *total_ea_len = ea_list_size(name_list);
670 return name_list;
673 /****************************************************************************
674 Send the required number of replies back.
675 We assume all fields other than the data fields are
676 set correctly for the type of call.
677 HACK ! Always assumes smb_setup field is zero.
678 ****************************************************************************/
680 void send_trans2_replies(connection_struct *conn,
681 struct smb_request *req,
682 const char *params,
683 int paramsize,
684 const char *pdata,
685 int datasize,
686 int max_data_bytes)
688 /* As we are using a protocol > LANMAN1 then the max_send
689 variable must have been set in the sessetupX call.
690 This takes precedence over the max_xmit field in the
691 global struct. These different max_xmit variables should
692 be merged as this is now too confusing */
694 int data_to_send = datasize;
695 int params_to_send = paramsize;
696 int useable_space;
697 const char *pp = params;
698 const char *pd = pdata;
699 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
700 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
701 int data_alignment_offset = 0;
702 bool overflow = False;
704 /* Modify the data_to_send and datasize and set the error if
705 we're trying to send more than max_data_bytes. We still send
706 the part of the packet(s) that fit. Strange, but needed
707 for OS/2. */
709 if (max_data_bytes > 0 && datasize > max_data_bytes) {
710 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
711 max_data_bytes, datasize ));
712 datasize = data_to_send = max_data_bytes;
713 overflow = True;
716 /* If there genuinely are no parameters or data to send just send the empty packet */
718 if(params_to_send == 0 && data_to_send == 0) {
719 reply_outbuf(req, 10, 0);
720 show_msg((char *)req->outbuf);
721 return;
724 /* When sending params and data ensure that both are nicely aligned */
725 /* Only do this alignment when there is also data to send - else
726 can cause NT redirector problems. */
728 if (((params_to_send % 4) != 0) && (data_to_send != 0))
729 data_alignment_offset = 4 - (params_to_send % 4);
731 /* Space is bufsize minus Netbios over TCP header minus SMB header */
732 /* The alignment_offset is to align the param bytes on an even byte
733 boundary. NT 4.0 Beta needs this to work correctly. */
735 useable_space = max_send - (smb_size
736 + 2 * 10 /* wct */
737 + alignment_offset
738 + data_alignment_offset);
740 /* useable_space can never be more than max_send minus the alignment offset. */
742 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
744 while (params_to_send || data_to_send) {
745 /* Calculate whether we will totally or partially fill this packet */
747 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
749 /* We can never send more than useable_space */
751 * Note that 'useable_space' does not include the alignment offsets,
752 * but we must include the alignment offsets in the calculation of
753 * the length of the data we send over the wire, as the alignment offsets
754 * are sent here. Fix from Marc_Jacobsen@hp.com.
757 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
759 reply_outbuf(req, 10, total_sent_thistime);
761 /* Set total params and data to be sent */
762 SSVAL(req->outbuf,smb_tprcnt,paramsize);
763 SSVAL(req->outbuf,smb_tdrcnt,datasize);
765 /* Calculate how many parameters and data we can fit into
766 * this packet. Parameters get precedence
769 params_sent_thistime = MIN(params_to_send,useable_space);
770 data_sent_thistime = useable_space - params_sent_thistime;
771 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
773 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
775 /* smb_proff is the offset from the start of the SMB header to the
776 parameter bytes, however the first 4 bytes of outbuf are
777 the Netbios over TCP header. Thus use smb_base() to subtract
778 them from the calculation */
780 SSVAL(req->outbuf,smb_proff,
781 ((smb_buf(req->outbuf)+alignment_offset)
782 - smb_base(req->outbuf)));
784 if(params_sent_thistime == 0)
785 SSVAL(req->outbuf,smb_prdisp,0);
786 else
787 /* Absolute displacement of param bytes sent in this packet */
788 SSVAL(req->outbuf,smb_prdisp,pp - params);
790 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
791 if(data_sent_thistime == 0) {
792 SSVAL(req->outbuf,smb_droff,0);
793 SSVAL(req->outbuf,smb_drdisp, 0);
794 } else {
795 /* The offset of the data bytes is the offset of the
796 parameter bytes plus the number of parameters being sent this time */
797 SSVAL(req->outbuf, smb_droff,
798 ((smb_buf(req->outbuf)+alignment_offset)
799 - smb_base(req->outbuf))
800 + params_sent_thistime + data_alignment_offset);
801 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
804 /* Initialize the padding for alignment */
806 if (alignment_offset != 0) {
807 memset(smb_buf(req->outbuf), 0, alignment_offset);
810 /* Copy the param bytes into the packet */
812 if(params_sent_thistime) {
813 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
814 params_sent_thistime);
817 /* Copy in the data bytes */
818 if(data_sent_thistime) {
819 if (data_alignment_offset != 0) {
820 memset((smb_buf(req->outbuf)+alignment_offset+
821 params_sent_thistime), 0,
822 data_alignment_offset);
824 memcpy(smb_buf(req->outbuf)+alignment_offset
825 +params_sent_thistime+data_alignment_offset,
826 pd,data_sent_thistime);
829 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
830 params_sent_thistime, data_sent_thistime, useable_space));
831 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
832 params_to_send, data_to_send, paramsize, datasize));
834 if (overflow) {
835 error_packet_set((char *)req->outbuf,
836 ERRDOS,ERRbufferoverflow,
837 STATUS_BUFFER_OVERFLOW,
838 __LINE__,__FILE__);
841 /* Send the packet */
842 show_msg((char *)req->outbuf);
843 if (!srv_send_smb(smbd_server_fd(),
844 (char *)req->outbuf,
845 IS_CONN_ENCRYPTED(conn)))
846 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
848 TALLOC_FREE(req->outbuf);
850 pp += params_sent_thistime;
851 pd += data_sent_thistime;
853 params_to_send -= params_sent_thistime;
854 data_to_send -= data_sent_thistime;
856 /* Sanity check */
857 if(params_to_send < 0 || data_to_send < 0) {
858 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
859 params_to_send, data_to_send));
860 return;
864 return;
867 /****************************************************************************
868 Reply to a TRANSACT2_OPEN.
869 ****************************************************************************/
871 static void call_trans2open(connection_struct *conn,
872 struct smb_request *req,
873 char **pparams, int total_params,
874 char **ppdata, int total_data,
875 unsigned int max_data_bytes)
877 char *params = *pparams;
878 char *pdata = *ppdata;
879 int deny_mode;
880 int32 open_attr;
881 bool oplock_request;
882 #if 0
883 bool return_additional_info;
884 int16 open_sattr;
885 time_t open_time;
886 #endif
887 int open_ofun;
888 uint32 open_size;
889 char *pname;
890 char *fname = NULL;
891 SMB_OFF_T size=0;
892 int fattr=0,mtime=0;
893 SMB_INO_T inode = 0;
894 SMB_STRUCT_STAT sbuf;
895 int smb_action = 0;
896 files_struct *fsp;
897 struct ea_list *ea_list = NULL;
898 uint16 flags = 0;
899 NTSTATUS status;
900 uint32 access_mask;
901 uint32 share_mode;
902 uint32 create_disposition;
903 uint32 create_options = 0;
904 TALLOC_CTX *ctx = talloc_tos();
907 * Ensure we have enough parameters to perform the operation.
910 if (total_params < 29) {
911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
912 return;
915 flags = SVAL(params, 0);
916 deny_mode = SVAL(params, 2);
917 open_attr = SVAL(params,6);
918 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
919 if (oplock_request) {
920 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
923 #if 0
924 return_additional_info = BITSETW(params,0);
925 open_sattr = SVAL(params, 4);
926 open_time = make_unix_date3(params+8);
927 #endif
928 open_ofun = SVAL(params,12);
929 open_size = IVAL(params,14);
930 pname = &params[28];
932 if (IS_IPC(conn)) {
933 reply_doserror(req, ERRSRV, ERRaccess);
934 return;
937 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
938 total_params - 28, STR_TERMINATE,
939 &status);
940 if (!NT_STATUS_IS_OK(status)) {
941 reply_nterror(req, status);
942 return;
945 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
946 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
947 (unsigned int)open_ofun, open_size));
949 if (open_ofun == 0) {
950 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
951 return;
954 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
955 &access_mask,
956 &share_mode,
957 &create_disposition,
958 &create_options)) {
959 reply_doserror(req, ERRDOS, ERRbadaccess);
960 return;
963 /* Any data in this call is an EA list. */
964 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
965 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
966 return;
969 if (total_data != 4) {
970 if (total_data < 10) {
971 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
972 return;
975 if (IVAL(pdata,0) > total_data) {
976 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
977 IVAL(pdata,0), (unsigned int)total_data));
978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
979 return;
982 ea_list = read_ea_list(talloc_tos(), pdata + 4,
983 total_data - 4);
984 if (!ea_list) {
985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
986 return;
988 } else if (IVAL(pdata,0) != 4) {
989 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
990 return;
993 status = create_file(conn, /* conn */
994 req, /* req */
995 0, /* root_dir_fid */
996 fname, /* fname */
997 access_mask, /* access_mask */
998 share_mode, /* share_access */
999 create_disposition, /* create_disposition*/
1000 create_options, /* create_options */
1001 open_attr, /* file_attributes */
1002 oplock_request, /* oplock_request */
1003 open_size, /* allocation_size */
1004 NULL, /* sd */
1005 ea_list, /* ea_list */
1006 &fsp, /* result */
1007 &smb_action, /* pinfo */
1008 &sbuf); /* psbuf */
1010 if (!NT_STATUS_IS_OK(status)) {
1011 if (open_was_deferred(req->mid)) {
1012 /* We have re-scheduled this call. */
1013 return;
1015 reply_openerror(req, status);
1016 return;
1019 size = get_file_size(sbuf);
1020 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1021 mtime = sbuf.st_mtime;
1022 inode = sbuf.st_ino;
1023 if (fattr & aDIR) {
1024 close_file(fsp,ERROR_CLOSE);
1025 reply_doserror(req, ERRDOS,ERRnoaccess);
1026 return;
1029 /* Realloc the size of parameters and data we will return */
1030 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1031 if(*pparams == NULL ) {
1032 reply_nterror(req, NT_STATUS_NO_MEMORY);
1033 return;
1035 params = *pparams;
1037 SSVAL(params,0,fsp->fnum);
1038 SSVAL(params,2,fattr);
1039 srv_put_dos_date2(params,4, mtime);
1040 SIVAL(params,8, (uint32)size);
1041 SSVAL(params,12,deny_mode);
1042 SSVAL(params,14,0); /* open_type - file or directory. */
1043 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1045 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1046 smb_action |= EXTENDED_OPLOCK_GRANTED;
1049 SSVAL(params,18,smb_action);
1052 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1054 SIVAL(params,20,inode);
1055 SSVAL(params,24,0); /* Padding. */
1056 if (flags & 8) {
1057 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1058 SIVAL(params, 26, ea_size);
1059 } else {
1060 SIVAL(params, 26, 0);
1063 /* Send the required number of replies */
1064 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1067 /*********************************************************
1068 Routine to check if a given string matches exactly.
1069 as a special case a mask of "." does NOT match. That
1070 is required for correct wildcard semantics
1071 Case can be significant or not.
1072 **********************************************************/
1074 static bool exact_match(connection_struct *conn,
1075 const char *str,
1076 const char *mask)
1078 if (mask[0] == '.' && mask[1] == 0)
1079 return False;
1080 if (conn->case_sensitive)
1081 return strcmp(str,mask)==0;
1082 if (StrCaseCmp(str,mask) != 0) {
1083 return False;
1085 if (dptr_has_wild(conn->dirptr)) {
1086 return False;
1088 return True;
1091 /****************************************************************************
1092 Return the filetype for UNIX extensions.
1093 ****************************************************************************/
1095 static uint32 unix_filetype(mode_t mode)
1097 if(S_ISREG(mode))
1098 return UNIX_TYPE_FILE;
1099 else if(S_ISDIR(mode))
1100 return UNIX_TYPE_DIR;
1101 #ifdef S_ISLNK
1102 else if(S_ISLNK(mode))
1103 return UNIX_TYPE_SYMLINK;
1104 #endif
1105 #ifdef S_ISCHR
1106 else if(S_ISCHR(mode))
1107 return UNIX_TYPE_CHARDEV;
1108 #endif
1109 #ifdef S_ISBLK
1110 else if(S_ISBLK(mode))
1111 return UNIX_TYPE_BLKDEV;
1112 #endif
1113 #ifdef S_ISFIFO
1114 else if(S_ISFIFO(mode))
1115 return UNIX_TYPE_FIFO;
1116 #endif
1117 #ifdef S_ISSOCK
1118 else if(S_ISSOCK(mode))
1119 return UNIX_TYPE_SOCKET;
1120 #endif
1122 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1123 return UNIX_TYPE_UNKNOWN;
1126 /****************************************************************************
1127 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1128 ****************************************************************************/
1130 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1132 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1133 SMB_STRUCT_STAT *psbuf,
1134 uint32 perms,
1135 enum perm_type ptype,
1136 mode_t *ret_perms)
1138 mode_t ret = 0;
1140 if (perms == SMB_MODE_NO_CHANGE) {
1141 if (!VALID_STAT(*psbuf)) {
1142 return NT_STATUS_INVALID_PARAMETER;
1143 } else {
1144 *ret_perms = psbuf->st_mode;
1145 return NT_STATUS_OK;
1149 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1150 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1151 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1152 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1153 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1154 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1155 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1156 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1157 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1158 #ifdef S_ISVTX
1159 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1160 #endif
1161 #ifdef S_ISGID
1162 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1163 #endif
1164 #ifdef S_ISUID
1165 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1166 #endif
1168 switch (ptype) {
1169 case PERM_NEW_FILE:
1170 /* Apply mode mask */
1171 ret &= lp_create_mask(SNUM(conn));
1172 /* Add in force bits */
1173 ret |= lp_force_create_mode(SNUM(conn));
1174 break;
1175 case PERM_NEW_DIR:
1176 ret &= lp_dir_mask(SNUM(conn));
1177 /* Add in force bits */
1178 ret |= lp_force_dir_mode(SNUM(conn));
1179 break;
1180 case PERM_EXISTING_FILE:
1181 /* Apply mode mask */
1182 ret &= lp_security_mask(SNUM(conn));
1183 /* Add in force bits */
1184 ret |= lp_force_security_mode(SNUM(conn));
1185 break;
1186 case PERM_EXISTING_DIR:
1187 /* Apply mode mask */
1188 ret &= lp_dir_security_mask(SNUM(conn));
1189 /* Add in force bits */
1190 ret |= lp_force_dir_security_mode(SNUM(conn));
1191 break;
1194 *ret_perms = ret;
1195 return NT_STATUS_OK;
1198 /****************************************************************************
1199 Get a level dependent lanman2 dir entry.
1200 ****************************************************************************/
1202 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1203 connection_struct *conn,
1204 uint16 flags2,
1205 const char *path_mask,
1206 uint32 dirtype,
1207 int info_level,
1208 int requires_resume_key,
1209 bool dont_descend,
1210 bool ask_sharemode,
1211 char **ppdata,
1212 char *base_data,
1213 char *end_data,
1214 int space_remaining,
1215 bool *out_of_space,
1216 bool *got_exact_match,
1217 int *last_entry_off,
1218 struct ea_list *name_list)
1220 const char *dname;
1221 bool found = False;
1222 SMB_STRUCT_STAT sbuf;
1223 const char *mask = NULL;
1224 char *pathreal = NULL;
1225 const char *fname = NULL;
1226 char *p, *q, *pdata = *ppdata;
1227 uint32 reskey=0;
1228 long prev_dirpos=0;
1229 uint32 mode=0;
1230 SMB_OFF_T file_size = 0;
1231 SMB_BIG_UINT allocation_size = 0;
1232 uint32 len;
1233 struct timespec mdate_ts, adate_ts, create_date_ts;
1234 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1235 char *nameptr;
1236 char *last_entry_ptr;
1237 bool was_8_3;
1238 uint32 nt_extmode; /* Used for NT connections instead of mode */
1239 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1240 bool check_mangled_names = lp_manglednames(conn->params);
1241 char mangled_name[13]; /* mangled 8.3 name. */
1243 *out_of_space = False;
1244 *got_exact_match = False;
1246 ZERO_STRUCT(mdate_ts);
1247 ZERO_STRUCT(adate_ts);
1248 ZERO_STRUCT(create_date_ts);
1250 if (!conn->dirptr) {
1251 return(False);
1254 p = strrchr_m(path_mask,'/');
1255 if(p != NULL) {
1256 if(p[1] == '\0') {
1257 mask = talloc_strdup(ctx,"*.*");
1258 } else {
1259 mask = p+1;
1261 } else {
1262 mask = path_mask;
1265 while (!found) {
1266 bool got_match;
1267 bool ms_dfs_link = False;
1269 /* Needed if we run out of space */
1270 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1271 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1274 * Due to bugs in NT client redirectors we are not using
1275 * resume keys any more - set them to zero.
1276 * Check out the related comments in findfirst/findnext.
1277 * JRA.
1280 reskey = 0;
1282 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1283 (long)conn->dirptr,curr_dirpos));
1285 if (!dname) {
1286 return(False);
1290 * fname may get mangled, dname is never mangled.
1291 * Whenever we're accessing the filesystem we use
1292 * pathreal which is composed from dname.
1295 pathreal = NULL;
1296 fname = dname;
1298 /* Mangle fname if it's an illegal name. */
1299 if (mangle_must_mangle(dname,conn->params)) {
1300 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1301 continue; /* Error - couldn't mangle. */
1303 fname = mangled_name;
1306 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1307 got_match = mask_match(fname, mask, conn->case_sensitive);
1310 if(!got_match && check_mangled_names &&
1311 !mangle_is_8_3(fname, False, conn->params)) {
1313 * It turns out that NT matches wildcards against
1314 * both long *and* short names. This may explain some
1315 * of the wildcard wierdness from old DOS clients
1316 * that some people have been seeing.... JRA.
1318 /* Force the mangling into 8.3. */
1319 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1320 continue; /* Error - couldn't mangle. */
1323 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1324 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1328 if (got_match) {
1329 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1331 if (dont_descend && !isdots) {
1332 continue;
1335 if (needslash) {
1336 pathreal = NULL;
1337 pathreal = talloc_asprintf(ctx,
1338 "%s/%s",
1339 conn->dirpath,
1340 dname);
1341 } else {
1342 pathreal = talloc_asprintf(ctx,
1343 "%s%s",
1344 conn->dirpath,
1345 dname);
1348 if (!pathreal) {
1349 return False;
1352 if (INFO_LEVEL_IS_UNIX(info_level)) {
1353 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1354 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1355 pathreal,strerror(errno)));
1356 TALLOC_FREE(pathreal);
1357 continue;
1359 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1360 /* Needed to show the msdfs symlinks as
1361 * directories */
1363 if(lp_host_msdfs() &&
1364 lp_msdfs_root(SNUM(conn)) &&
1365 ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) {
1366 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1367 "as a directory\n",
1368 pathreal));
1369 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1371 } else {
1373 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1374 pathreal,strerror(errno)));
1375 TALLOC_FREE(pathreal);
1376 continue;
1380 if (ms_dfs_link) {
1381 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1382 } else {
1383 mode = dos_mode(conn,pathreal,&sbuf);
1386 if (!dir_check_ftype(conn,mode,dirtype)) {
1387 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1388 TALLOC_FREE(pathreal);
1389 continue;
1392 if (!(mode & aDIR)) {
1393 file_size = get_file_size(sbuf);
1395 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1397 mdate_ts = get_mtimespec(&sbuf);
1398 adate_ts = get_atimespec(&sbuf);
1399 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1401 if (ask_sharemode) {
1402 struct timespec write_time_ts;
1403 struct file_id fileid;
1405 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1406 get_file_infos(fileid, NULL, &write_time_ts);
1407 if (!null_timespec(write_time_ts)) {
1408 mdate_ts = write_time_ts;
1412 if (lp_dos_filetime_resolution(SNUM(conn))) {
1413 dos_filetime_timespec(&create_date_ts);
1414 dos_filetime_timespec(&mdate_ts);
1415 dos_filetime_timespec(&adate_ts);
1418 create_date = convert_timespec_to_time_t(create_date_ts);
1419 mdate = convert_timespec_to_time_t(mdate_ts);
1420 adate = convert_timespec_to_time_t(adate_ts);
1422 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1424 found = True;
1426 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1430 p = pdata;
1431 last_entry_ptr = p;
1433 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1435 switch (info_level) {
1436 case SMB_FIND_INFO_STANDARD:
1437 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1438 if(requires_resume_key) {
1439 SIVAL(p,0,reskey);
1440 p += 4;
1442 srv_put_dos_date2(p,0,create_date);
1443 srv_put_dos_date2(p,4,adate);
1444 srv_put_dos_date2(p,8,mdate);
1445 SIVAL(p,12,(uint32)file_size);
1446 SIVAL(p,16,(uint32)allocation_size);
1447 SSVAL(p,20,mode);
1448 p += 23;
1449 nameptr = p;
1450 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1451 p += ucs2_align(base_data, p, 0);
1453 len = srvstr_push(base_data, flags2, p,
1454 fname, PTR_DIFF(end_data, p),
1455 STR_TERMINATE);
1456 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1457 if (len > 2) {
1458 SCVAL(nameptr, -1, len - 2);
1459 } else {
1460 SCVAL(nameptr, -1, 0);
1462 } else {
1463 if (len > 1) {
1464 SCVAL(nameptr, -1, len - 1);
1465 } else {
1466 SCVAL(nameptr, -1, 0);
1469 p += len;
1470 break;
1472 case SMB_FIND_EA_SIZE:
1473 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1474 if(requires_resume_key) {
1475 SIVAL(p,0,reskey);
1476 p += 4;
1478 srv_put_dos_date2(p,0,create_date);
1479 srv_put_dos_date2(p,4,adate);
1480 srv_put_dos_date2(p,8,mdate);
1481 SIVAL(p,12,(uint32)file_size);
1482 SIVAL(p,16,(uint32)allocation_size);
1483 SSVAL(p,20,mode);
1485 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1486 SIVAL(p,22,ea_size); /* Extended attributes */
1488 p += 27;
1489 nameptr = p - 1;
1490 len = srvstr_push(base_data, flags2,
1491 p, fname, PTR_DIFF(end_data, p),
1492 STR_TERMINATE | STR_NOALIGN);
1493 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1494 if (len > 2) {
1495 len -= 2;
1496 } else {
1497 len = 0;
1499 } else {
1500 if (len > 1) {
1501 len -= 1;
1502 } else {
1503 len = 0;
1506 SCVAL(nameptr,0,len);
1507 p += len;
1508 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1509 break;
1511 case SMB_FIND_EA_LIST:
1513 struct ea_list *file_list = NULL;
1514 size_t ea_len = 0;
1516 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1517 if (!name_list) {
1518 return False;
1520 if(requires_resume_key) {
1521 SIVAL(p,0,reskey);
1522 p += 4;
1524 srv_put_dos_date2(p,0,create_date);
1525 srv_put_dos_date2(p,4,adate);
1526 srv_put_dos_date2(p,8,mdate);
1527 SIVAL(p,12,(uint32)file_size);
1528 SIVAL(p,16,(uint32)allocation_size);
1529 SSVAL(p,20,mode);
1530 p += 22; /* p now points to the EA area. */
1532 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1533 name_list = ea_list_union(name_list, file_list, &ea_len);
1535 /* We need to determine if this entry will fit in the space available. */
1536 /* Max string size is 255 bytes. */
1537 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1538 /* Move the dirptr back to prev_dirpos */
1539 dptr_SeekDir(conn->dirptr, prev_dirpos);
1540 *out_of_space = True;
1541 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1542 return False; /* Not finished - just out of space */
1545 /* Push the ea_data followed by the name. */
1546 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1547 nameptr = p;
1548 len = srvstr_push(base_data, flags2,
1549 p + 1, fname, PTR_DIFF(end_data, p+1),
1550 STR_TERMINATE | STR_NOALIGN);
1551 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1552 if (len > 2) {
1553 len -= 2;
1554 } else {
1555 len = 0;
1557 } else {
1558 if (len > 1) {
1559 len -= 1;
1560 } else {
1561 len = 0;
1564 SCVAL(nameptr,0,len);
1565 p += len + 1;
1566 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1567 break;
1570 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1571 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1572 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1573 p += 4;
1574 SIVAL(p,0,reskey); p += 4;
1575 put_long_date_timespec(p,create_date_ts); p += 8;
1576 put_long_date_timespec(p,adate_ts); p += 8;
1577 put_long_date_timespec(p,mdate_ts); p += 8;
1578 put_long_date_timespec(p,mdate_ts); p += 8;
1579 SOFF_T(p,0,file_size); p += 8;
1580 SOFF_T(p,0,allocation_size); p += 8;
1581 SIVAL(p,0,nt_extmode); p += 4;
1582 q = p; p += 4; /* q is placeholder for name length. */
1584 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1585 SIVAL(p,0,ea_size); /* Extended attributes */
1586 p += 4;
1588 /* Clear the short name buffer. This is
1589 * IMPORTANT as not doing so will trigger
1590 * a Win2k client bug. JRA.
1592 if (!was_8_3 && check_mangled_names) {
1593 if (!name_to_8_3(fname,mangled_name,True,
1594 conn->params)) {
1595 /* Error - mangle failed ! */
1596 memset(mangled_name,'\0',12);
1598 mangled_name[12] = 0;
1599 len = srvstr_push(base_data, flags2,
1600 p+2, mangled_name, 24,
1601 STR_UPPER|STR_UNICODE);
1602 if (len < 24) {
1603 memset(p + 2 + len,'\0',24 - len);
1605 SSVAL(p, 0, len);
1606 } else {
1607 memset(p,'\0',26);
1609 p += 2 + 24;
1610 len = srvstr_push(base_data, flags2, p,
1611 fname, PTR_DIFF(end_data, p),
1612 STR_TERMINATE_ASCII);
1613 SIVAL(q,0,len);
1614 p += len;
1615 SIVAL(p,0,0); /* Ensure any padding is null. */
1616 len = PTR_DIFF(p, pdata);
1617 len = (len + 3) & ~3;
1618 SIVAL(pdata,0,len);
1619 p = pdata + len;
1620 break;
1622 case SMB_FIND_FILE_DIRECTORY_INFO:
1623 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1624 p += 4;
1625 SIVAL(p,0,reskey); p += 4;
1626 put_long_date_timespec(p,create_date_ts); p += 8;
1627 put_long_date_timespec(p,adate_ts); p += 8;
1628 put_long_date_timespec(p,mdate_ts); p += 8;
1629 put_long_date_timespec(p,mdate_ts); p += 8;
1630 SOFF_T(p,0,file_size); p += 8;
1631 SOFF_T(p,0,allocation_size); p += 8;
1632 SIVAL(p,0,nt_extmode); p += 4;
1633 len = srvstr_push(base_data, flags2,
1634 p + 4, fname, PTR_DIFF(end_data, p+4),
1635 STR_TERMINATE_ASCII);
1636 SIVAL(p,0,len);
1637 p += 4 + len;
1638 SIVAL(p,0,0); /* Ensure any padding is null. */
1639 len = PTR_DIFF(p, pdata);
1640 len = (len + 3) & ~3;
1641 SIVAL(pdata,0,len);
1642 p = pdata + len;
1643 break;
1645 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1646 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1647 p += 4;
1648 SIVAL(p,0,reskey); p += 4;
1649 put_long_date_timespec(p,create_date_ts); p += 8;
1650 put_long_date_timespec(p,adate_ts); p += 8;
1651 put_long_date_timespec(p,mdate_ts); p += 8;
1652 put_long_date_timespec(p,mdate_ts); p += 8;
1653 SOFF_T(p,0,file_size); p += 8;
1654 SOFF_T(p,0,allocation_size); p += 8;
1655 SIVAL(p,0,nt_extmode); p += 4;
1656 q = p; p += 4; /* q is placeholder for name length. */
1658 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1659 SIVAL(p,0,ea_size); /* Extended attributes */
1660 p +=4;
1662 len = srvstr_push(base_data, flags2, p,
1663 fname, PTR_DIFF(end_data, p),
1664 STR_TERMINATE_ASCII);
1665 SIVAL(q, 0, len);
1666 p += len;
1668 SIVAL(p,0,0); /* Ensure any padding is null. */
1669 len = PTR_DIFF(p, pdata);
1670 len = (len + 3) & ~3;
1671 SIVAL(pdata,0,len);
1672 p = pdata + len;
1673 break;
1675 case SMB_FIND_FILE_NAMES_INFO:
1676 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1677 p += 4;
1678 SIVAL(p,0,reskey); p += 4;
1679 p += 4;
1680 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1681 acl on a dir (tridge) */
1682 len = srvstr_push(base_data, flags2, p,
1683 fname, PTR_DIFF(end_data, p),
1684 STR_TERMINATE_ASCII);
1685 SIVAL(p, -4, len);
1686 p += len;
1687 SIVAL(p,0,0); /* Ensure any padding is null. */
1688 len = PTR_DIFF(p, pdata);
1689 len = (len + 3) & ~3;
1690 SIVAL(pdata,0,len);
1691 p = pdata + len;
1692 break;
1694 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1695 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1696 p += 4;
1697 SIVAL(p,0,reskey); p += 4;
1698 put_long_date_timespec(p,create_date_ts); p += 8;
1699 put_long_date_timespec(p,adate_ts); p += 8;
1700 put_long_date_timespec(p,mdate_ts); p += 8;
1701 put_long_date_timespec(p,mdate_ts); p += 8;
1702 SOFF_T(p,0,file_size); p += 8;
1703 SOFF_T(p,0,allocation_size); p += 8;
1704 SIVAL(p,0,nt_extmode); p += 4;
1705 q = p; p += 4; /* q is placeholder for name length. */
1707 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1708 SIVAL(p,0,ea_size); /* Extended attributes */
1709 p +=4;
1711 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1712 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1713 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1714 len = srvstr_push(base_data, flags2, p,
1715 fname, PTR_DIFF(end_data, p),
1716 STR_TERMINATE_ASCII);
1717 SIVAL(q, 0, len);
1718 p += len;
1719 SIVAL(p,0,0); /* Ensure any padding is null. */
1720 len = PTR_DIFF(p, pdata);
1721 len = (len + 3) & ~3;
1722 SIVAL(pdata,0,len);
1723 p = pdata + len;
1724 break;
1726 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1727 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1728 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1729 p += 4;
1730 SIVAL(p,0,reskey); p += 4;
1731 put_long_date_timespec(p,create_date_ts); p += 8;
1732 put_long_date_timespec(p,adate_ts); p += 8;
1733 put_long_date_timespec(p,mdate_ts); p += 8;
1734 put_long_date_timespec(p,mdate_ts); p += 8;
1735 SOFF_T(p,0,file_size); p += 8;
1736 SOFF_T(p,0,allocation_size); p += 8;
1737 SIVAL(p,0,nt_extmode); p += 4;
1738 q = p; p += 4; /* q is placeholder for name length */
1740 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1741 SIVAL(p,0,ea_size); /* Extended attributes */
1742 p +=4;
1744 /* Clear the short name buffer. This is
1745 * IMPORTANT as not doing so will trigger
1746 * a Win2k client bug. JRA.
1748 if (!was_8_3 && check_mangled_names) {
1749 if (!name_to_8_3(fname,mangled_name,True,
1750 conn->params)) {
1751 /* Error - mangle failed ! */
1752 memset(mangled_name,'\0',12);
1754 mangled_name[12] = 0;
1755 len = srvstr_push(base_data, flags2,
1756 p+2, mangled_name, 24,
1757 STR_UPPER|STR_UNICODE);
1758 SSVAL(p, 0, len);
1759 if (len < 24) {
1760 memset(p + 2 + len,'\0',24 - len);
1762 SSVAL(p, 0, len);
1763 } else {
1764 memset(p,'\0',26);
1766 p += 26;
1767 SSVAL(p,0,0); p += 2; /* Reserved ? */
1768 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1769 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1770 len = srvstr_push(base_data, flags2, p,
1771 fname, PTR_DIFF(end_data, p),
1772 STR_TERMINATE_ASCII);
1773 SIVAL(q,0,len);
1774 p += len;
1775 SIVAL(p,0,0); /* Ensure any padding is null. */
1776 len = PTR_DIFF(p, pdata);
1777 len = (len + 3) & ~3;
1778 SIVAL(pdata,0,len);
1779 p = pdata + len;
1780 break;
1782 /* CIFS UNIX Extension. */
1784 case SMB_FIND_FILE_UNIX:
1785 case SMB_FIND_FILE_UNIX_INFO2:
1786 p+= 4;
1787 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1789 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1791 if (info_level == SMB_FIND_FILE_UNIX) {
1792 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1793 p = store_file_unix_basic(conn, p,
1794 NULL, &sbuf);
1795 len = srvstr_push(base_data, flags2, p,
1796 fname, PTR_DIFF(end_data, p),
1797 STR_TERMINATE);
1798 } else {
1799 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1800 p = store_file_unix_basic_info2(conn, p,
1801 NULL, &sbuf);
1802 nameptr = p;
1803 p += 4;
1804 len = srvstr_push(base_data, flags2, p, fname,
1805 PTR_DIFF(end_data, p), 0);
1806 SIVAL(nameptr, 0, len);
1809 p += len;
1810 SIVAL(p,0,0); /* Ensure any padding is null. */
1812 len = PTR_DIFF(p, pdata);
1813 len = (len + 3) & ~3;
1814 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1815 p = pdata + len;
1816 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1818 break;
1820 default:
1821 return(False);
1825 if (PTR_DIFF(p,pdata) > space_remaining) {
1826 /* Move the dirptr back to prev_dirpos */
1827 dptr_SeekDir(conn->dirptr, prev_dirpos);
1828 *out_of_space = True;
1829 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1830 return False; /* Not finished - just out of space */
1833 /* Setup the last entry pointer, as an offset from base_data */
1834 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1835 /* Advance the data pointer to the next slot */
1836 *ppdata = p;
1838 return(found);
1841 /****************************************************************************
1842 Reply to a TRANS2_FINDFIRST.
1843 ****************************************************************************/
1845 static void call_trans2findfirst(connection_struct *conn,
1846 struct smb_request *req,
1847 char **pparams, int total_params,
1848 char **ppdata, int total_data,
1849 unsigned int max_data_bytes)
1851 /* We must be careful here that we don't return more than the
1852 allowed number of data bytes. If this means returning fewer than
1853 maxentries then so be it. We assume that the redirector has
1854 enough room for the fixed number of parameter bytes it has
1855 requested. */
1856 char *params = *pparams;
1857 char *pdata = *ppdata;
1858 char *data_end;
1859 uint32 dirtype;
1860 int maxentries;
1861 uint16 findfirst_flags;
1862 bool close_after_first;
1863 bool close_if_end;
1864 bool requires_resume_key;
1865 int info_level;
1866 char *directory = NULL;
1867 const char *mask = NULL;
1868 char *p;
1869 int last_entry_off=0;
1870 int dptr_num = -1;
1871 int numentries = 0;
1872 int i;
1873 bool finished = False;
1874 bool dont_descend = False;
1875 bool out_of_space = False;
1876 int space_remaining;
1877 bool mask_contains_wcard = False;
1878 SMB_STRUCT_STAT sbuf;
1879 struct ea_list *ea_list = NULL;
1880 NTSTATUS ntstatus = NT_STATUS_OK;
1881 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1882 TALLOC_CTX *ctx = talloc_tos();
1884 if (total_params < 13) {
1885 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1886 return;
1889 dirtype = SVAL(params,0);
1890 maxentries = SVAL(params,2);
1891 findfirst_flags = SVAL(params,4);
1892 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1893 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1894 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1895 info_level = SVAL(params,6);
1897 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1898 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1899 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1900 info_level, max_data_bytes));
1902 if (!maxentries) {
1903 /* W2K3 seems to treat zero as 1. */
1904 maxentries = 1;
1907 switch (info_level) {
1908 case SMB_FIND_INFO_STANDARD:
1909 case SMB_FIND_EA_SIZE:
1910 case SMB_FIND_EA_LIST:
1911 case SMB_FIND_FILE_DIRECTORY_INFO:
1912 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1913 case SMB_FIND_FILE_NAMES_INFO:
1914 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1915 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1916 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1917 break;
1918 case SMB_FIND_FILE_UNIX:
1919 case SMB_FIND_FILE_UNIX_INFO2:
1920 if (!lp_unix_extensions()) {
1921 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1922 return;
1924 break;
1925 default:
1926 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1927 return;
1930 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1931 params+12, total_params - 12,
1932 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1933 if (!NT_STATUS_IS_OK(ntstatus)) {
1934 reply_nterror(req, ntstatus);
1935 return;
1938 ntstatus = resolve_dfspath_wcard(ctx, conn,
1939 req->flags2 & FLAGS2_DFS_PATHNAMES,
1940 directory,
1941 &directory,
1942 &mask_contains_wcard);
1943 if (!NT_STATUS_IS_OK(ntstatus)) {
1944 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1945 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1946 ERRSRV, ERRbadpath);
1947 return;
1949 reply_nterror(req, ntstatus);
1950 return;
1953 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1954 if (!NT_STATUS_IS_OK(ntstatus)) {
1955 reply_nterror(req, ntstatus);
1956 return;
1959 ntstatus = check_name(conn, directory);
1960 if (!NT_STATUS_IS_OK(ntstatus)) {
1961 reply_nterror(req, ntstatus);
1962 return;
1965 p = strrchr_m(directory,'/');
1966 if(p == NULL) {
1967 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1968 if((directory[0] == '.') && (directory[1] == '\0')) {
1969 mask = "*";
1970 mask_contains_wcard = True;
1971 } else {
1972 mask = directory;
1974 directory = talloc_strdup(talloc_tos(), "./");
1975 if (!directory) {
1976 reply_nterror(req, NT_STATUS_NO_MEMORY);
1977 return;
1979 } else {
1980 mask = p+1;
1981 *p = 0;
1984 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1986 if (info_level == SMB_FIND_EA_LIST) {
1987 uint32 ea_size;
1989 if (total_data < 4) {
1990 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1991 return;
1994 ea_size = IVAL(pdata,0);
1995 if (ea_size != total_data) {
1996 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1997 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1998 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1999 return;
2002 if (!lp_ea_support(SNUM(conn))) {
2003 reply_doserror(req, ERRDOS, ERReasnotsupported);
2004 return;
2007 /* Pull out the list of names. */
2008 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2009 if (!ea_list) {
2010 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2011 return;
2015 *ppdata = (char *)SMB_REALLOC(
2016 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2017 if(*ppdata == NULL ) {
2018 reply_nterror(req, NT_STATUS_NO_MEMORY);
2019 return;
2021 pdata = *ppdata;
2022 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2024 /* Realloc the params space */
2025 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2026 if (*pparams == NULL) {
2027 reply_nterror(req, NT_STATUS_NO_MEMORY);
2028 return;
2030 params = *pparams;
2032 /* Save the wildcard match and attribs we are using on this directory -
2033 needed as lanman2 assumes these are being saved between calls */
2035 ntstatus = dptr_create(conn,
2036 directory,
2037 False,
2038 True,
2039 req->smbpid,
2040 mask,
2041 mask_contains_wcard,
2042 dirtype,
2043 &conn->dirptr);
2045 if (!NT_STATUS_IS_OK(ntstatus)) {
2046 reply_nterror(req, ntstatus);
2047 return;
2050 dptr_num = dptr_dnum(conn->dirptr);
2051 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2053 /* We don't need to check for VOL here as this is returned by
2054 a different TRANS2 call. */
2056 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2057 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2058 dont_descend = True;
2060 p = pdata;
2061 space_remaining = max_data_bytes;
2062 out_of_space = False;
2064 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2065 bool got_exact_match = False;
2067 /* this is a heuristic to avoid seeking the dirptr except when
2068 absolutely necessary. It allows for a filename of about 40 chars */
2069 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2070 out_of_space = True;
2071 finished = False;
2072 } else {
2073 finished = !get_lanman2_dir_entry(ctx,
2074 conn,
2075 req->flags2,
2076 mask,dirtype,info_level,
2077 requires_resume_key,dont_descend,
2078 ask_sharemode,
2079 &p,pdata,data_end,
2080 space_remaining, &out_of_space,
2081 &got_exact_match,
2082 &last_entry_off, ea_list);
2085 if (finished && out_of_space)
2086 finished = False;
2088 if (!finished && !out_of_space)
2089 numentries++;
2092 * As an optimisation if we know we aren't looking
2093 * for a wildcard name (ie. the name matches the wildcard exactly)
2094 * then we can finish on any (first) match.
2095 * This speeds up large directory searches. JRA.
2098 if(got_exact_match)
2099 finished = True;
2101 /* Ensure space_remaining never goes -ve. */
2102 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2103 space_remaining = 0;
2104 out_of_space = true;
2105 } else {
2106 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2110 /* Check if we can close the dirptr */
2111 if(close_after_first || (finished && close_if_end)) {
2112 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2113 dptr_close(&dptr_num);
2117 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2118 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2119 * the protocol level is less than NT1. Tested with smbclient. JRA.
2120 * This should fix the OS/2 client bug #2335.
2123 if(numentries == 0) {
2124 dptr_close(&dptr_num);
2125 if (Protocol < PROTOCOL_NT1) {
2126 reply_doserror(req, ERRDOS, ERRnofiles);
2127 return;
2128 } else {
2129 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2130 ERRDOS, ERRbadfile);
2131 return;
2135 /* At this point pdata points to numentries directory entries. */
2137 /* Set up the return parameter block */
2138 SSVAL(params,0,dptr_num);
2139 SSVAL(params,2,numentries);
2140 SSVAL(params,4,finished);
2141 SSVAL(params,6,0); /* Never an EA error */
2142 SSVAL(params,8,last_entry_off);
2144 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2145 max_data_bytes);
2147 if ((! *directory) && dptr_path(dptr_num)) {
2148 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2149 if (!directory) {
2150 reply_nterror(req, NT_STATUS_NO_MEMORY);
2154 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2155 smb_fn_name(CVAL(req->inbuf,smb_com)),
2156 mask, directory, dirtype, numentries ) );
2159 * Force a name mangle here to ensure that the
2160 * mask as an 8.3 name is top of the mangled cache.
2161 * The reasons for this are subtle. Don't remove
2162 * this code unless you know what you are doing
2163 * (see PR#13758). JRA.
2166 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2167 char mangled_name[13];
2168 name_to_8_3(mask, mangled_name, True, conn->params);
2171 return;
2174 /****************************************************************************
2175 Reply to a TRANS2_FINDNEXT.
2176 ****************************************************************************/
2178 static void call_trans2findnext(connection_struct *conn,
2179 struct smb_request *req,
2180 char **pparams, int total_params,
2181 char **ppdata, int total_data,
2182 unsigned int max_data_bytes)
2184 /* We must be careful here that we don't return more than the
2185 allowed number of data bytes. If this means returning fewer than
2186 maxentries then so be it. We assume that the redirector has
2187 enough room for the fixed number of parameter bytes it has
2188 requested. */
2189 char *params = *pparams;
2190 char *pdata = *ppdata;
2191 char *data_end;
2192 int dptr_num;
2193 int maxentries;
2194 uint16 info_level;
2195 uint32 resume_key;
2196 uint16 findnext_flags;
2197 bool close_after_request;
2198 bool close_if_end;
2199 bool requires_resume_key;
2200 bool continue_bit;
2201 bool mask_contains_wcard = False;
2202 char *resume_name = NULL;
2203 const char *mask = NULL;
2204 const char *directory = NULL;
2205 char *p = NULL;
2206 uint16 dirtype;
2207 int numentries = 0;
2208 int i, last_entry_off=0;
2209 bool finished = False;
2210 bool dont_descend = False;
2211 bool out_of_space = False;
2212 int space_remaining;
2213 struct ea_list *ea_list = NULL;
2214 NTSTATUS ntstatus = NT_STATUS_OK;
2215 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2216 TALLOC_CTX *ctx = talloc_tos();
2218 if (total_params < 13) {
2219 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2220 return;
2223 dptr_num = SVAL(params,0);
2224 maxentries = SVAL(params,2);
2225 info_level = SVAL(params,4);
2226 resume_key = IVAL(params,6);
2227 findnext_flags = SVAL(params,10);
2228 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2229 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2230 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2231 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2233 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2234 params+12,
2235 total_params - 12, STR_TERMINATE, &ntstatus,
2236 &mask_contains_wcard);
2237 if (!NT_STATUS_IS_OK(ntstatus)) {
2238 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2239 complain (it thinks we're asking for the directory above the shared
2240 path or an invalid name). Catch this as the resume name is only compared, never used in
2241 a file access. JRA. */
2242 srvstr_pull_talloc(ctx, params, req->flags2,
2243 &resume_name, params+12,
2244 total_params - 12,
2245 STR_TERMINATE);
2247 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2248 reply_nterror(req, ntstatus);
2249 return;
2253 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2254 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2255 resume_key = %d resume name = %s continue=%d level = %d\n",
2256 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2257 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2259 if (!maxentries) {
2260 /* W2K3 seems to treat zero as 1. */
2261 maxentries = 1;
2264 switch (info_level) {
2265 case SMB_FIND_INFO_STANDARD:
2266 case SMB_FIND_EA_SIZE:
2267 case SMB_FIND_EA_LIST:
2268 case SMB_FIND_FILE_DIRECTORY_INFO:
2269 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2270 case SMB_FIND_FILE_NAMES_INFO:
2271 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2272 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2273 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2274 break;
2275 case SMB_FIND_FILE_UNIX:
2276 case SMB_FIND_FILE_UNIX_INFO2:
2277 if (!lp_unix_extensions()) {
2278 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2279 return;
2281 break;
2282 default:
2283 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2284 return;
2287 if (info_level == SMB_FIND_EA_LIST) {
2288 uint32 ea_size;
2290 if (total_data < 4) {
2291 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2292 return;
2295 ea_size = IVAL(pdata,0);
2296 if (ea_size != total_data) {
2297 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2298 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2299 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2300 return;
2303 if (!lp_ea_support(SNUM(conn))) {
2304 reply_doserror(req, ERRDOS, ERReasnotsupported);
2305 return;
2308 /* Pull out the list of names. */
2309 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2310 if (!ea_list) {
2311 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2312 return;
2316 *ppdata = (char *)SMB_REALLOC(
2317 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2318 if(*ppdata == NULL) {
2319 reply_nterror(req, NT_STATUS_NO_MEMORY);
2320 return;
2323 pdata = *ppdata;
2324 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2326 /* Realloc the params space */
2327 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2328 if(*pparams == NULL ) {
2329 reply_nterror(req, NT_STATUS_NO_MEMORY);
2330 return;
2333 params = *pparams;
2335 /* Check that the dptr is valid */
2336 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2337 reply_doserror(req, ERRDOS, ERRnofiles);
2338 return;
2341 string_set(&conn->dirpath,dptr_path(dptr_num));
2343 /* Get the wildcard mask from the dptr */
2344 if((p = dptr_wcard(dptr_num))== NULL) {
2345 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2346 reply_doserror(req, ERRDOS, ERRnofiles);
2347 return;
2350 mask = p;
2351 directory = conn->dirpath;
2353 /* Get the attr mask from the dptr */
2354 dirtype = dptr_attr(dptr_num);
2356 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2357 dptr_num, mask, dirtype,
2358 (long)conn->dirptr,
2359 dptr_TellDir(conn->dirptr)));
2361 /* We don't need to check for VOL here as this is returned by
2362 a different TRANS2 call. */
2364 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2365 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2366 dont_descend = True;
2368 p = pdata;
2369 space_remaining = max_data_bytes;
2370 out_of_space = False;
2373 * Seek to the correct position. We no longer use the resume key but
2374 * depend on the last file name instead.
2377 if(*resume_name && !continue_bit) {
2378 SMB_STRUCT_STAT st;
2380 long current_pos = 0;
2382 * Remember, name_to_8_3 is called by
2383 * get_lanman2_dir_entry(), so the resume name
2384 * could be mangled. Ensure we check the unmangled name.
2387 if (mangle_is_mangled(resume_name, conn->params)) {
2388 char *new_resume_name = NULL;
2389 mangle_lookup_name_from_8_3(ctx,
2390 resume_name,
2391 &new_resume_name,
2392 conn->params);
2393 if (new_resume_name) {
2394 resume_name = new_resume_name;
2399 * Fix for NT redirector problem triggered by resume key indexes
2400 * changing between directory scans. We now return a resume key of 0
2401 * and instead look for the filename to continue from (also given
2402 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2403 * findfirst/findnext (as is usual) then the directory pointer
2404 * should already be at the correct place.
2407 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2408 } /* end if resume_name && !continue_bit */
2410 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2411 bool got_exact_match = False;
2413 /* this is a heuristic to avoid seeking the dirptr except when
2414 absolutely necessary. It allows for a filename of about 40 chars */
2415 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2416 out_of_space = True;
2417 finished = False;
2418 } else {
2419 finished = !get_lanman2_dir_entry(ctx,
2420 conn,
2421 req->flags2,
2422 mask,dirtype,info_level,
2423 requires_resume_key,dont_descend,
2424 ask_sharemode,
2425 &p,pdata,data_end,
2426 space_remaining, &out_of_space,
2427 &got_exact_match,
2428 &last_entry_off, ea_list);
2431 if (finished && out_of_space)
2432 finished = False;
2434 if (!finished && !out_of_space)
2435 numentries++;
2438 * As an optimisation if we know we aren't looking
2439 * for a wildcard name (ie. the name matches the wildcard exactly)
2440 * then we can finish on any (first) match.
2441 * This speeds up large directory searches. JRA.
2444 if(got_exact_match)
2445 finished = True;
2447 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2450 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2451 smb_fn_name(CVAL(req->inbuf,smb_com)),
2452 mask, directory, dirtype, numentries ) );
2454 /* Check if we can close the dirptr */
2455 if(close_after_request || (finished && close_if_end)) {
2456 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2457 dptr_close(&dptr_num); /* This frees up the saved mask */
2460 /* Set up the return parameter block */
2461 SSVAL(params,0,numentries);
2462 SSVAL(params,2,finished);
2463 SSVAL(params,4,0); /* Never an EA error */
2464 SSVAL(params,6,last_entry_off);
2466 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2467 max_data_bytes);
2469 return;
2472 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2474 E_md4hash(lp_servicename(SNUM(conn)),objid);
2475 return objid;
2478 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2480 SMB_ASSERT(extended_info != NULL);
2482 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2483 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2484 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2485 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2486 #ifdef SAMBA_VERSION_REVISION
2487 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2488 #endif
2489 extended_info->samba_subversion = 0;
2490 #ifdef SAMBA_VERSION_RC_RELEASE
2491 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2492 #else
2493 #ifdef SAMBA_VERSION_PRE_RELEASE
2494 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2495 #endif
2496 #endif
2497 #ifdef SAMBA_VERSION_VENDOR_PATCH
2498 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2499 #endif
2500 extended_info->samba_gitcommitdate = 0;
2501 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2502 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2503 #endif
2505 memset(extended_info->samba_version_string, 0,
2506 sizeof(extended_info->samba_version_string));
2508 snprintf (extended_info->samba_version_string,
2509 sizeof(extended_info->samba_version_string),
2510 "%s", samba_version_string());
2513 /****************************************************************************
2514 Reply to a TRANS2_QFSINFO (query filesystem info).
2515 ****************************************************************************/
2517 static void call_trans2qfsinfo(connection_struct *conn,
2518 struct smb_request *req,
2519 char **pparams, int total_params,
2520 char **ppdata, int total_data,
2521 unsigned int max_data_bytes)
2523 char *pdata, *end_data;
2524 char *params = *pparams;
2525 uint16 info_level;
2526 int data_len, len;
2527 SMB_STRUCT_STAT st;
2528 const char *vname = volume_label(SNUM(conn));
2529 int snum = SNUM(conn);
2530 char *fstype = lp_fstype(SNUM(conn));
2531 uint32 additional_flags = 0;
2533 if (total_params < 2) {
2534 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2535 return;
2538 info_level = SVAL(params,0);
2540 if (IS_IPC(conn)) {
2541 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2542 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2543 "info level (0x%x) on IPC$.\n",
2544 (unsigned int)info_level));
2545 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2546 return;
2550 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2551 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2552 DEBUG(0,("call_trans2qfsinfo: encryption required "
2553 "and info level 0x%x sent.\n",
2554 (unsigned int)info_level));
2555 exit_server_cleanly("encryption required "
2556 "on connection");
2557 return;
2561 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2563 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2564 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2565 reply_doserror(req, ERRSRV, ERRinvdevice);
2566 return;
2569 *ppdata = (char *)SMB_REALLOC(
2570 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2571 if (*ppdata == NULL ) {
2572 reply_nterror(req, NT_STATUS_NO_MEMORY);
2573 return;
2576 pdata = *ppdata;
2577 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2578 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2580 switch (info_level) {
2581 case SMB_INFO_ALLOCATION:
2583 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2584 data_len = 18;
2585 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2586 reply_unixerror(req, ERRHRD, ERRgeneral);
2587 return;
2590 block_size = lp_block_size(snum);
2591 if (bsize < block_size) {
2592 SMB_BIG_UINT factor = block_size/bsize;
2593 bsize = block_size;
2594 dsize /= factor;
2595 dfree /= factor;
2597 if (bsize > block_size) {
2598 SMB_BIG_UINT factor = bsize/block_size;
2599 bsize = block_size;
2600 dsize *= factor;
2601 dfree *= factor;
2603 bytes_per_sector = 512;
2604 sectors_per_unit = bsize/bytes_per_sector;
2606 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2607 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2608 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2610 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2611 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2612 SIVAL(pdata,l1_cUnit,dsize);
2613 SIVAL(pdata,l1_cUnitAvail,dfree);
2614 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2615 break;
2618 case SMB_INFO_VOLUME:
2619 /* Return volume name */
2621 * Add volume serial number - hash of a combination of
2622 * the called hostname and the service name.
2624 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2626 * Win2k3 and previous mess this up by sending a name length
2627 * one byte short. I believe only older clients (OS/2 Win9x) use
2628 * this call so try fixing this by adding a terminating null to
2629 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2631 len = srvstr_push(
2632 pdata, req->flags2,
2633 pdata+l2_vol_szVolLabel, vname,
2634 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2635 STR_NOALIGN|STR_TERMINATE);
2636 SCVAL(pdata,l2_vol_cch,len);
2637 data_len = l2_vol_szVolLabel + len;
2638 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2639 (unsigned)st.st_ctime, len, vname));
2640 break;
2642 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2643 case SMB_FS_ATTRIBUTE_INFORMATION:
2645 additional_flags = 0;
2646 #if defined(HAVE_SYS_QUOTAS)
2647 additional_flags |= FILE_VOLUME_QUOTAS;
2648 #endif
2650 if(lp_nt_acl_support(SNUM(conn))) {
2651 additional_flags |= FILE_PERSISTENT_ACLS;
2654 /* Capabilities are filled in at connection time through STATVFS call */
2655 additional_flags |= conn->fs_capabilities;
2657 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2658 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2659 additional_flags); /* FS ATTRIBUTES */
2661 SIVAL(pdata,4,255); /* Max filename component length */
2662 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2663 and will think we can't do long filenames */
2664 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2665 PTR_DIFF(end_data, pdata+12),
2666 STR_UNICODE);
2667 SIVAL(pdata,8,len);
2668 data_len = 12 + len;
2669 break;
2671 case SMB_QUERY_FS_LABEL_INFO:
2672 case SMB_FS_LABEL_INFORMATION:
2673 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2674 PTR_DIFF(end_data, pdata+4), 0);
2675 data_len = 4 + len;
2676 SIVAL(pdata,0,len);
2677 break;
2679 case SMB_QUERY_FS_VOLUME_INFO:
2680 case SMB_FS_VOLUME_INFORMATION:
2683 * Add volume serial number - hash of a combination of
2684 * the called hostname and the service name.
2686 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2687 (str_checksum(get_local_machine_name())<<16));
2689 /* Max label len is 32 characters. */
2690 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2691 PTR_DIFF(end_data, pdata+18),
2692 STR_UNICODE);
2693 SIVAL(pdata,12,len);
2694 data_len = 18+len;
2696 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2697 (int)strlen(vname),vname, lp_servicename(snum)));
2698 break;
2700 case SMB_QUERY_FS_SIZE_INFO:
2701 case SMB_FS_SIZE_INFORMATION:
2703 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2704 data_len = 24;
2705 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2706 reply_unixerror(req, ERRHRD, ERRgeneral);
2707 return;
2709 block_size = lp_block_size(snum);
2710 if (bsize < block_size) {
2711 SMB_BIG_UINT factor = block_size/bsize;
2712 bsize = block_size;
2713 dsize /= factor;
2714 dfree /= factor;
2716 if (bsize > block_size) {
2717 SMB_BIG_UINT factor = bsize/block_size;
2718 bsize = block_size;
2719 dsize *= factor;
2720 dfree *= factor;
2722 bytes_per_sector = 512;
2723 sectors_per_unit = bsize/bytes_per_sector;
2724 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2725 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2726 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2727 SBIG_UINT(pdata,0,dsize);
2728 SBIG_UINT(pdata,8,dfree);
2729 SIVAL(pdata,16,sectors_per_unit);
2730 SIVAL(pdata,20,bytes_per_sector);
2731 break;
2734 case SMB_FS_FULL_SIZE_INFORMATION:
2736 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2737 data_len = 32;
2738 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2739 reply_unixerror(req, ERRHRD, ERRgeneral);
2740 return;
2742 block_size = lp_block_size(snum);
2743 if (bsize < block_size) {
2744 SMB_BIG_UINT factor = block_size/bsize;
2745 bsize = block_size;
2746 dsize /= factor;
2747 dfree /= factor;
2749 if (bsize > block_size) {
2750 SMB_BIG_UINT factor = bsize/block_size;
2751 bsize = block_size;
2752 dsize *= factor;
2753 dfree *= factor;
2755 bytes_per_sector = 512;
2756 sectors_per_unit = bsize/bytes_per_sector;
2757 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2758 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2759 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2760 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2761 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2762 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2763 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2764 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2765 break;
2768 case SMB_QUERY_FS_DEVICE_INFO:
2769 case SMB_FS_DEVICE_INFORMATION:
2770 data_len = 8;
2771 SIVAL(pdata,0,0); /* dev type */
2772 SIVAL(pdata,4,0); /* characteristics */
2773 break;
2775 #ifdef HAVE_SYS_QUOTAS
2776 case SMB_FS_QUOTA_INFORMATION:
2778 * what we have to send --metze:
2780 * Unknown1: 24 NULL bytes
2781 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2782 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2783 * Quota Flags: 2 byte :
2784 * Unknown3: 6 NULL bytes
2786 * 48 bytes total
2788 * details for Quota Flags:
2790 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2791 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2792 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2793 * 0x0001 Enable Quotas: enable quota for this fs
2797 /* we need to fake up a fsp here,
2798 * because its not send in this call
2800 files_struct fsp;
2801 SMB_NTQUOTA_STRUCT quotas;
2803 ZERO_STRUCT(fsp);
2804 ZERO_STRUCT(quotas);
2806 fsp.conn = conn;
2807 fsp.fnum = -1;
2809 /* access check */
2810 if (current_user.ut.uid != 0) {
2811 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2812 lp_servicename(SNUM(conn)),conn->user));
2813 reply_doserror(req, ERRDOS, ERRnoaccess);
2814 return;
2817 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2818 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2819 reply_doserror(req, ERRSRV, ERRerror);
2820 return;
2823 data_len = 48;
2825 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2827 /* Unknown1 24 NULL bytes*/
2828 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2829 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2830 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2832 /* Default Soft Quota 8 bytes */
2833 SBIG_UINT(pdata,24,quotas.softlim);
2835 /* Default Hard Quota 8 bytes */
2836 SBIG_UINT(pdata,32,quotas.hardlim);
2838 /* Quota flag 2 bytes */
2839 SSVAL(pdata,40,quotas.qflags);
2841 /* Unknown3 6 NULL bytes */
2842 SSVAL(pdata,42,0);
2843 SIVAL(pdata,44,0);
2845 break;
2847 #endif /* HAVE_SYS_QUOTAS */
2848 case SMB_FS_OBJECTID_INFORMATION:
2850 unsigned char objid[16];
2851 struct smb_extended_info extended_info;
2852 memcpy(pdata,create_volume_objectid(conn, objid),16);
2853 samba_extended_info_version (&extended_info);
2854 SIVAL(pdata,16,extended_info.samba_magic);
2855 SIVAL(pdata,20,extended_info.samba_version);
2856 SIVAL(pdata,24,extended_info.samba_subversion);
2857 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2858 memcpy(pdata+36,extended_info.samba_version_string,28);
2859 data_len = 64;
2860 break;
2864 * Query the version and capabilities of the CIFS UNIX extensions
2865 * in use.
2868 case SMB_QUERY_CIFS_UNIX_INFO:
2870 bool large_write = lp_min_receive_file_size() &&
2871 !srv_is_signing_active();
2872 bool large_read = !srv_is_signing_active();
2873 int encrypt_caps = 0;
2875 if (!lp_unix_extensions()) {
2876 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2877 return;
2880 switch (conn->encrypt_level) {
2881 case 0:
2882 encrypt_caps = 0;
2883 break;
2884 case 1:
2885 case Auto:
2886 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2887 break;
2888 case Required:
2889 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2890 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2891 large_write = false;
2892 large_read = false;
2893 break;
2896 data_len = 12;
2897 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2898 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2900 /* We have POSIX ACLs, pathname, encryption,
2901 * large read/write, and locking capability. */
2903 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2904 CIFS_UNIX_POSIX_ACLS_CAP|
2905 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2906 CIFS_UNIX_FCNTL_LOCKS_CAP|
2907 CIFS_UNIX_EXTATTR_CAP|
2908 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2909 encrypt_caps|
2910 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2911 (large_write ?
2912 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2913 break;
2916 case SMB_QUERY_POSIX_FS_INFO:
2918 int rc;
2919 vfs_statvfs_struct svfs;
2921 if (!lp_unix_extensions()) {
2922 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2923 return;
2926 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2928 if (!rc) {
2929 data_len = 56;
2930 SIVAL(pdata,0,svfs.OptimalTransferSize);
2931 SIVAL(pdata,4,svfs.BlockSize);
2932 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2933 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2934 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2935 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2936 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2937 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2938 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2939 #ifdef EOPNOTSUPP
2940 } else if (rc == EOPNOTSUPP) {
2941 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2942 return;
2943 #endif /* EOPNOTSUPP */
2944 } else {
2945 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2946 reply_doserror(req, ERRSRV, ERRerror);
2947 return;
2949 break;
2952 case SMB_QUERY_POSIX_WHOAMI:
2954 uint32_t flags = 0;
2955 uint32_t sid_bytes;
2956 int i;
2958 if (!lp_unix_extensions()) {
2959 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2960 return;
2963 if (max_data_bytes < 40) {
2964 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2965 return;
2968 /* We ARE guest if global_sid_Builtin_Guests is
2969 * in our list of SIDs.
2971 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2972 current_user.nt_user_token)) {
2973 flags |= SMB_WHOAMI_GUEST;
2976 /* We are NOT guest if global_sid_Authenticated_Users
2977 * is in our list of SIDs.
2979 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2980 current_user.nt_user_token)) {
2981 flags &= ~SMB_WHOAMI_GUEST;
2984 /* NOTE: 8 bytes for UID/GID, irrespective of native
2985 * platform size. This matches
2986 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2988 data_len = 4 /* flags */
2989 + 4 /* flag mask */
2990 + 8 /* uid */
2991 + 8 /* gid */
2992 + 4 /* ngroups */
2993 + 4 /* num_sids */
2994 + 4 /* SID bytes */
2995 + 4 /* pad/reserved */
2996 + (current_user.ut.ngroups * 8)
2997 /* groups list */
2998 + (current_user.nt_user_token->num_sids *
2999 SID_MAX_SIZE)
3000 /* SID list */;
3002 SIVAL(pdata, 0, flags);
3003 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3004 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
3005 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
3008 if (data_len >= max_data_bytes) {
3009 /* Potential overflow, skip the GIDs and SIDs. */
3011 SIVAL(pdata, 24, 0); /* num_groups */
3012 SIVAL(pdata, 28, 0); /* num_sids */
3013 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3014 SIVAL(pdata, 36, 0); /* reserved */
3016 data_len = 40;
3017 break;
3020 SIVAL(pdata, 24, current_user.ut.ngroups);
3021 SIVAL(pdata, 28,
3022 current_user.nt_user_token->num_sids);
3024 /* We walk the SID list twice, but this call is fairly
3025 * infrequent, and I don't expect that it's performance
3026 * sensitive -- jpeach
3028 for (i = 0, sid_bytes = 0;
3029 i < current_user.nt_user_token->num_sids; ++i) {
3030 sid_bytes += ndr_size_dom_sid(
3031 &current_user.nt_user_token->user_sids[i], 0);
3034 /* SID list byte count */
3035 SIVAL(pdata, 32, sid_bytes);
3037 /* 4 bytes pad/reserved - must be zero */
3038 SIVAL(pdata, 36, 0);
3039 data_len = 40;
3041 /* GID list */
3042 for (i = 0; i < current_user.ut.ngroups; ++i) {
3043 SBIG_UINT(pdata, data_len,
3044 (SMB_BIG_UINT)current_user.ut.groups[i]);
3045 data_len += 8;
3048 /* SID list */
3049 for (i = 0;
3050 i < current_user.nt_user_token->num_sids; ++i) {
3051 int sid_len = ndr_size_dom_sid(
3052 &current_user.nt_user_token->user_sids[i], 0);
3054 sid_linearize(pdata + data_len, sid_len,
3055 &current_user.nt_user_token->user_sids[i]);
3056 data_len += sid_len;
3059 break;
3062 case SMB_MAC_QUERY_FS_INFO:
3064 * Thursby MAC extension... ONLY on NTFS filesystems
3065 * once we do streams then we don't need this
3067 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3068 data_len = 88;
3069 SIVAL(pdata,84,0x100); /* Don't support mac... */
3070 break;
3072 /* drop through */
3073 default:
3074 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3075 return;
3079 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3080 max_data_bytes);
3082 DEBUG( 4, ( "%s info_level = %d\n",
3083 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
3085 return;
3088 /****************************************************************************
3089 Reply to a TRANS2_SETFSINFO (set filesystem info).
3090 ****************************************************************************/
3092 static void call_trans2setfsinfo(connection_struct *conn,
3093 struct smb_request *req,
3094 char **pparams, int total_params,
3095 char **ppdata, int total_data,
3096 unsigned int max_data_bytes)
3098 char *pdata = *ppdata;
3099 char *params = *pparams;
3100 uint16 info_level;
3102 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3104 /* */
3105 if (total_params < 4) {
3106 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3107 total_params));
3108 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3109 return;
3112 info_level = SVAL(params,2);
3114 if (IS_IPC(conn)) {
3115 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3116 info_level != SMB_SET_CIFS_UNIX_INFO) {
3117 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3118 "info level (0x%x) on IPC$.\n",
3119 (unsigned int)info_level));
3120 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3121 return;
3125 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3126 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3127 DEBUG(0,("call_trans2setfsinfo: encryption required "
3128 "and info level 0x%x sent.\n",
3129 (unsigned int)info_level));
3130 exit_server_cleanly("encryption required "
3131 "on connection");
3132 return;
3136 switch(info_level) {
3137 case SMB_SET_CIFS_UNIX_INFO:
3139 uint16 client_unix_major;
3140 uint16 client_unix_minor;
3141 uint32 client_unix_cap_low;
3142 uint32 client_unix_cap_high;
3144 if (!lp_unix_extensions()) {
3145 reply_nterror(req,
3146 NT_STATUS_INVALID_LEVEL);
3147 return;
3150 /* There should be 12 bytes of capabilities set. */
3151 if (total_data < 8) {
3152 reply_nterror(
3153 req,
3154 NT_STATUS_INVALID_PARAMETER);
3155 return;
3157 client_unix_major = SVAL(pdata,0);
3158 client_unix_minor = SVAL(pdata,2);
3159 client_unix_cap_low = IVAL(pdata,4);
3160 client_unix_cap_high = IVAL(pdata,8);
3161 /* Just print these values for now. */
3162 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3163 cap_low = 0x%x, cap_high = 0x%x\n",
3164 (unsigned int)client_unix_major,
3165 (unsigned int)client_unix_minor,
3166 (unsigned int)client_unix_cap_low,
3167 (unsigned int)client_unix_cap_high ));
3169 /* Here is where we must switch to posix pathname processing... */
3170 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3171 lp_set_posix_pathnames();
3172 mangle_change_to_posix();
3175 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3176 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3177 /* Client that knows how to do posix locks,
3178 * but not posix open/mkdir operations. Set a
3179 * default type for read/write checks. */
3181 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3184 break;
3187 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3189 NTSTATUS status;
3190 size_t param_len = 0;
3191 size_t data_len = total_data;
3193 if (!lp_unix_extensions()) {
3194 reply_nterror(
3195 req,
3196 NT_STATUS_INVALID_LEVEL);
3197 return;
3200 if (lp_smb_encrypt(SNUM(conn)) == false) {
3201 reply_nterror(
3202 req,
3203 NT_STATUS_NOT_SUPPORTED);
3204 return;
3207 DEBUG( 4,("call_trans2setfsinfo: "
3208 "request transport encryption.\n"));
3210 status = srv_request_encryption_setup(conn,
3211 (unsigned char **)ppdata,
3212 &data_len,
3213 (unsigned char **)pparams,
3214 &param_len);
3216 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3217 !NT_STATUS_IS_OK(status)) {
3218 reply_nterror(req, status);
3219 return;
3222 send_trans2_replies(conn, req,
3223 *pparams,
3224 param_len,
3225 *ppdata,
3226 data_len,
3227 max_data_bytes);
3229 if (NT_STATUS_IS_OK(status)) {
3230 /* Server-side transport
3231 * encryption is now *on*. */
3232 status = srv_encryption_start(conn);
3233 if (!NT_STATUS_IS_OK(status)) {
3234 exit_server_cleanly(
3235 "Failure in setting "
3236 "up encrypted transport");
3239 return;
3242 case SMB_FS_QUOTA_INFORMATION:
3244 files_struct *fsp = NULL;
3245 SMB_NTQUOTA_STRUCT quotas;
3247 ZERO_STRUCT(quotas);
3249 /* access check */
3250 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3251 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3252 lp_servicename(SNUM(conn)),conn->user));
3253 reply_doserror(req, ERRSRV, ERRaccess);
3254 return;
3257 /* note: normaly there're 48 bytes,
3258 * but we didn't use the last 6 bytes for now
3259 * --metze
3261 fsp = file_fsp(SVAL(params,0));
3262 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3263 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3264 reply_nterror(
3265 req, NT_STATUS_INVALID_HANDLE);
3266 return;
3269 if (total_data < 42) {
3270 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3271 total_data));
3272 reply_nterror(
3273 req,
3274 NT_STATUS_INVALID_PARAMETER);
3275 return;
3278 /* unknown_1 24 NULL bytes in pdata*/
3280 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3281 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3282 #ifdef LARGE_SMB_OFF_T
3283 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3284 #else /* LARGE_SMB_OFF_T */
3285 if ((IVAL(pdata,28) != 0)&&
3286 ((quotas.softlim != 0xFFFFFFFF)||
3287 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3288 /* more than 32 bits? */
3289 reply_nterror(
3290 req,
3291 NT_STATUS_INVALID_PARAMETER);
3292 return;
3294 #endif /* LARGE_SMB_OFF_T */
3296 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3297 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3298 #ifdef LARGE_SMB_OFF_T
3299 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3300 #else /* LARGE_SMB_OFF_T */
3301 if ((IVAL(pdata,36) != 0)&&
3302 ((quotas.hardlim != 0xFFFFFFFF)||
3303 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3304 /* more than 32 bits? */
3305 reply_nterror(
3306 req,
3307 NT_STATUS_INVALID_PARAMETER);
3308 return;
3310 #endif /* LARGE_SMB_OFF_T */
3312 /* quota_flags 2 bytes **/
3313 quotas.qflags = SVAL(pdata,40);
3315 /* unknown_2 6 NULL bytes follow*/
3317 /* now set the quotas */
3318 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3319 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3320 reply_doserror(req, ERRSRV, ERRerror);
3321 return;
3324 break;
3326 default:
3327 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3328 info_level));
3329 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3330 return;
3331 break;
3335 * sending this reply works fine,
3336 * but I'm not sure it's the same
3337 * like windows do...
3338 * --metze
3340 reply_outbuf(req, 10, 0);
3343 #if defined(HAVE_POSIX_ACLS)
3344 /****************************************************************************
3345 Utility function to count the number of entries in a POSIX acl.
3346 ****************************************************************************/
3348 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3350 unsigned int ace_count = 0;
3351 int entry_id = SMB_ACL_FIRST_ENTRY;
3352 SMB_ACL_ENTRY_T entry;
3354 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3355 /* get_next... */
3356 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3357 entry_id = SMB_ACL_NEXT_ENTRY;
3359 ace_count++;
3361 return ace_count;
3364 /****************************************************************************
3365 Utility function to marshall a POSIX acl into wire format.
3366 ****************************************************************************/
3368 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3370 int entry_id = SMB_ACL_FIRST_ENTRY;
3371 SMB_ACL_ENTRY_T entry;
3373 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3374 SMB_ACL_TAG_T tagtype;
3375 SMB_ACL_PERMSET_T permset;
3376 unsigned char perms = 0;
3377 unsigned int own_grp;
3379 /* get_next... */
3380 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3381 entry_id = SMB_ACL_NEXT_ENTRY;
3384 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3385 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3386 return False;
3389 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3390 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3391 return False;
3394 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3395 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3396 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3398 SCVAL(pdata,1,perms);
3400 switch (tagtype) {
3401 case SMB_ACL_USER_OBJ:
3402 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3403 own_grp = (unsigned int)pst->st_uid;
3404 SIVAL(pdata,2,own_grp);
3405 SIVAL(pdata,6,0);
3406 break;
3407 case SMB_ACL_USER:
3409 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3410 if (!puid) {
3411 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3412 return False;
3414 own_grp = (unsigned int)*puid;
3415 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3416 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3417 SIVAL(pdata,2,own_grp);
3418 SIVAL(pdata,6,0);
3419 break;
3421 case SMB_ACL_GROUP_OBJ:
3422 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3423 own_grp = (unsigned int)pst->st_gid;
3424 SIVAL(pdata,2,own_grp);
3425 SIVAL(pdata,6,0);
3426 break;
3427 case SMB_ACL_GROUP:
3429 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3430 if (!pgid) {
3431 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3432 return False;
3434 own_grp = (unsigned int)*pgid;
3435 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3436 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3437 SIVAL(pdata,2,own_grp);
3438 SIVAL(pdata,6,0);
3439 break;
3441 case SMB_ACL_MASK:
3442 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3443 SIVAL(pdata,2,0xFFFFFFFF);
3444 SIVAL(pdata,6,0xFFFFFFFF);
3445 break;
3446 case SMB_ACL_OTHER:
3447 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3448 SIVAL(pdata,2,0xFFFFFFFF);
3449 SIVAL(pdata,6,0xFFFFFFFF);
3450 break;
3451 default:
3452 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3453 return False;
3455 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3458 return True;
3460 #endif
3462 /****************************************************************************
3463 Store the FILE_UNIX_BASIC info.
3464 ****************************************************************************/
3466 static char *store_file_unix_basic(connection_struct *conn,
3467 char *pdata,
3468 files_struct *fsp,
3469 const SMB_STRUCT_STAT *psbuf)
3471 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3472 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3474 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3475 pdata += 8;
3477 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3478 pdata += 8;
3480 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3481 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3482 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3483 pdata += 24;
3485 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3486 SIVAL(pdata,4,0);
3487 pdata += 8;
3489 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3490 SIVAL(pdata,4,0);
3491 pdata += 8;
3493 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3494 pdata += 4;
3496 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3497 SIVAL(pdata,4,0);
3498 pdata += 8;
3500 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3501 SIVAL(pdata,4,0);
3502 pdata += 8;
3504 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3505 pdata += 8;
3507 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3508 SIVAL(pdata,4,0);
3509 pdata += 8;
3511 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3512 SIVAL(pdata,4,0);
3513 pdata += 8;
3515 return pdata;
3518 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3519 * the chflags(2) (or equivalent) flags.
3521 * XXX: this really should be behind the VFS interface. To do this, we would
3522 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3523 * Each VFS module could then implement its own mapping as appropriate for the
3524 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3526 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3527 info2_flags_map[] =
3529 #ifdef UF_NODUMP
3530 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3531 #endif
3533 #ifdef UF_IMMUTABLE
3534 { UF_IMMUTABLE, EXT_IMMUTABLE },
3535 #endif
3537 #ifdef UF_APPEND
3538 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3539 #endif
3541 #ifdef UF_HIDDEN
3542 { UF_HIDDEN, EXT_HIDDEN },
3543 #endif
3545 /* Do not remove. We need to guarantee that this array has at least one
3546 * entry to build on HP-UX.
3548 { 0, 0 }
3552 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3553 uint32 *smb_fflags, uint32 *smb_fmask)
3555 #ifdef HAVE_STAT_ST_FLAGS
3556 int i;
3558 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3559 *smb_fmask |= info2_flags_map[i].smb_fflag;
3560 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3561 *smb_fflags |= info2_flags_map[i].smb_fflag;
3564 #endif /* HAVE_STAT_ST_FLAGS */
3567 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3568 const uint32 smb_fflags,
3569 const uint32 smb_fmask,
3570 int *stat_fflags)
3572 #ifdef HAVE_STAT_ST_FLAGS
3573 uint32 max_fmask = 0;
3574 int i;
3576 *stat_fflags = psbuf->st_flags;
3578 /* For each flags requested in smb_fmask, check the state of the
3579 * corresponding flag in smb_fflags and set or clear the matching
3580 * stat flag.
3583 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3584 max_fmask |= info2_flags_map[i].smb_fflag;
3585 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3586 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3587 *stat_fflags |= info2_flags_map[i].stat_fflag;
3588 } else {
3589 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3594 /* If smb_fmask is asking to set any bits that are not supported by
3595 * our flag mappings, we should fail.
3597 if ((smb_fmask & max_fmask) != smb_fmask) {
3598 return False;
3601 return True;
3602 #else
3603 return False;
3604 #endif /* HAVE_STAT_ST_FLAGS */
3608 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3609 * of file flags and birth (create) time.
3611 static char *store_file_unix_basic_info2(connection_struct *conn,
3612 char *pdata,
3613 files_struct *fsp,
3614 const SMB_STRUCT_STAT *psbuf)
3616 uint32 file_flags = 0;
3617 uint32 flags_mask = 0;
3619 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3621 /* Create (birth) time 64 bit */
3622 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3623 pdata += 8;
3625 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3626 SIVAL(pdata, 0, file_flags); /* flags */
3627 SIVAL(pdata, 4, flags_mask); /* mask */
3628 pdata += 8;
3630 return pdata;
3633 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3634 const struct stream_struct *streams,
3635 char *data,
3636 unsigned int max_data_bytes,
3637 unsigned int *data_size)
3639 unsigned int i;
3640 unsigned int ofs = 0;
3642 for (i=0; i<num_streams; i++) {
3643 unsigned int next_offset;
3644 size_t namelen;
3645 smb_ucs2_t *namebuf;
3647 namelen = push_ucs2_talloc(talloc_tos(), &namebuf,
3648 streams[i].name);
3650 if ((namelen == (size_t)-1) || (namelen <= 2)) {
3651 return NT_STATUS_INVALID_PARAMETER;
3655 * name_buf is now null-terminated, we need to marshall as not
3656 * terminated
3659 namelen -= 2;
3661 if (ofs + 24 + namelen > max_data_bytes) {
3662 TALLOC_FREE(namebuf);
3663 return NT_STATUS_BUFFER_TOO_SMALL;
3666 SIVAL(data, ofs+4, namelen);
3667 SOFF_T(data, ofs+8, streams[i].size);
3668 SOFF_T(data, ofs+16, streams[i].alloc_size);
3669 memcpy(data+ofs+24, namebuf, namelen);
3670 TALLOC_FREE(namebuf);
3672 next_offset = ofs + 24 + namelen;
3674 if (i == num_streams-1) {
3675 SIVAL(data, ofs, 0);
3677 else {
3678 unsigned int align = ndr_align_size(next_offset, 8);
3680 if (next_offset + align > max_data_bytes) {
3681 return NT_STATUS_BUFFER_TOO_SMALL;
3684 memset(data+next_offset, 0, align);
3685 next_offset += align;
3687 SIVAL(data, ofs, next_offset - ofs);
3688 ofs = next_offset;
3691 ofs = next_offset;
3694 *data_size = ofs;
3696 return NT_STATUS_OK;
3699 /****************************************************************************
3700 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3701 ****************************************************************************/
3703 static void call_trans2qpipeinfo(connection_struct *conn,
3704 struct smb_request *req,
3705 unsigned int tran_call,
3706 char **pparams, int total_params,
3707 char **ppdata, int total_data,
3708 unsigned int max_data_bytes)
3710 char *params = *pparams;
3711 char *pdata = *ppdata;
3712 unsigned int data_size = 0;
3713 unsigned int param_size = 2;
3714 uint16 info_level;
3715 smb_np_struct *p_pipe = NULL;
3717 if (!params) {
3718 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3719 return;
3722 if (total_params < 4) {
3723 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3724 return;
3727 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3728 if (p_pipe == NULL) {
3729 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3730 return;
3733 info_level = SVAL(params,2);
3735 *pparams = (char *)SMB_REALLOC(*pparams,2);
3736 if (*pparams == NULL) {
3737 reply_nterror(req, NT_STATUS_NO_MEMORY);
3738 return;
3740 params = *pparams;
3741 SSVAL(params,0,0);
3742 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3743 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3744 if (*ppdata == NULL ) {
3745 reply_nterror(req, NT_STATUS_NO_MEMORY);
3746 return;
3748 pdata = *ppdata;
3750 switch (info_level) {
3751 case SMB_FILE_STANDARD_INFORMATION:
3752 memset(pdata,0,24);
3753 SOFF_T(pdata,0,4096LL);
3754 SIVAL(pdata,16,1);
3755 SIVAL(pdata,20,1);
3756 data_size = 24;
3757 break;
3759 default:
3760 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3761 return;
3764 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3765 max_data_bytes);
3767 return;
3770 /****************************************************************************
3771 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3772 file name or file id).
3773 ****************************************************************************/
3775 static void call_trans2qfilepathinfo(connection_struct *conn,
3776 struct smb_request *req,
3777 unsigned int tran_call,
3778 char **pparams, int total_params,
3779 char **ppdata, int total_data,
3780 unsigned int max_data_bytes)
3782 char *params = *pparams;
3783 char *pdata = *ppdata;
3784 char *dstart, *dend;
3785 uint16 info_level;
3786 int mode=0;
3787 int nlink;
3788 SMB_OFF_T file_size=0;
3789 SMB_BIG_UINT allocation_size=0;
3790 unsigned int data_size = 0;
3791 unsigned int param_size = 2;
3792 SMB_STRUCT_STAT sbuf;
3793 char *dos_fname = NULL;
3794 char *fname = NULL;
3795 char *fullpathname;
3796 char *base_name;
3797 char *p;
3798 SMB_OFF_T pos = 0;
3799 bool delete_pending = False;
3800 int len;
3801 time_t create_time, mtime, atime;
3802 struct timespec create_time_ts, mtime_ts, atime_ts;
3803 struct timespec write_time_ts;
3804 files_struct *fsp = NULL;
3805 struct file_id fileid;
3806 struct ea_list *ea_list = NULL;
3807 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3808 char *lock_data = NULL;
3809 TALLOC_CTX *ctx = talloc_tos();
3811 if (!params) {
3812 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3813 return;
3816 ZERO_STRUCT(sbuf);
3817 ZERO_STRUCT(write_time_ts);
3819 if (tran_call == TRANSACT2_QFILEINFO) {
3820 if (total_params < 4) {
3821 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3822 return;
3825 if (IS_IPC(conn)) {
3826 call_trans2qpipeinfo(conn, req, tran_call,
3827 pparams, total_params,
3828 ppdata, total_data,
3829 max_data_bytes);
3830 return;
3833 fsp = file_fsp(SVAL(params,0));
3834 info_level = SVAL(params,2);
3836 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3838 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3839 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3840 return;
3843 /* Initial check for valid fsp ptr. */
3844 if (!check_fsp_open(conn, req, fsp, &current_user)) {
3845 return;
3848 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3849 if (!fname) {
3850 reply_nterror(req, NT_STATUS_NO_MEMORY);
3851 return;
3854 if(fsp->fake_file_handle) {
3856 * This is actually for the QUOTA_FAKE_FILE --metze
3859 /* We know this name is ok, it's already passed the checks. */
3861 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3863 * This is actually a QFILEINFO on a directory
3864 * handle (returned from an NT SMB). NT5.0 seems
3865 * to do this call. JRA.
3868 if (INFO_LEVEL_IS_UNIX(info_level)) {
3869 /* Always do lstat for UNIX calls. */
3870 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3871 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3872 reply_unixerror(req,ERRDOS,ERRbadpath);
3873 return;
3875 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3876 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3877 reply_unixerror(req, ERRDOS, ERRbadpath);
3878 return;
3881 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3882 get_file_infos(fileid, &delete_pending, &write_time_ts);
3883 } else {
3885 * Original code - this is an open file.
3887 if (!check_fsp(conn, req, fsp, &current_user)) {
3888 return;
3891 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3892 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3893 reply_unixerror(req, ERRDOS, ERRbadfid);
3894 return;
3896 pos = fsp->fh->position_information;
3897 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3898 get_file_infos(fileid, &delete_pending, &write_time_ts);
3899 access_mask = fsp->access_mask;
3902 } else {
3903 NTSTATUS status = NT_STATUS_OK;
3905 /* qpathinfo */
3906 if (total_params < 7) {
3907 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3908 return;
3911 info_level = SVAL(params,0);
3913 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3915 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3916 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3917 return;
3920 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3921 total_params - 6,
3922 STR_TERMINATE, &status);
3923 if (!NT_STATUS_IS_OK(status)) {
3924 reply_nterror(req, status);
3925 return;
3928 status = resolve_dfspath(ctx,
3929 conn,
3930 req->flags2 & FLAGS2_DFS_PATHNAMES,
3931 fname,
3932 &fname);
3933 if (!NT_STATUS_IS_OK(status)) {
3934 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3935 reply_botherror(req,
3936 NT_STATUS_PATH_NOT_COVERED,
3937 ERRSRV, ERRbadpath);
3939 reply_nterror(req, status);
3940 return;
3943 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3944 if (!NT_STATUS_IS_OK(status)) {
3945 reply_nterror(req, status);
3946 return;
3948 status = check_name(conn, fname);
3949 if (!NT_STATUS_IS_OK(status)) {
3950 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3951 reply_nterror(req, status);
3952 return;
3955 if (INFO_LEVEL_IS_UNIX(info_level)) {
3956 /* Always do lstat for UNIX calls. */
3957 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3958 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3959 reply_unixerror(req, ERRDOS, ERRbadpath);
3960 return;
3962 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3963 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3964 reply_unixerror(req, ERRDOS, ERRbadpath);
3965 return;
3968 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3969 get_file_infos(fileid, &delete_pending, &write_time_ts);
3970 if (delete_pending) {
3971 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3972 return;
3976 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3977 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3978 return;
3981 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3982 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3984 p = strrchr_m(fname,'/');
3985 if (!p)
3986 base_name = fname;
3987 else
3988 base_name = p+1;
3990 mode = dos_mode(conn,fname,&sbuf);
3991 if (!mode)
3992 mode = FILE_ATTRIBUTE_NORMAL;
3994 nlink = sbuf.st_nlink;
3996 if (nlink && (mode&aDIR)) {
3997 nlink = 1;
4000 if ((nlink > 0) && delete_pending) {
4001 nlink -= 1;
4004 fullpathname = fname;
4005 if (!(mode & aDIR))
4006 file_size = get_file_size(sbuf);
4008 /* Pull out any data sent here before we realloc. */
4009 switch (info_level) {
4010 case SMB_INFO_QUERY_EAS_FROM_LIST:
4012 /* Pull any EA list from the data portion. */
4013 uint32 ea_size;
4015 if (total_data < 4) {
4016 reply_nterror(
4017 req, NT_STATUS_INVALID_PARAMETER);
4018 return;
4020 ea_size = IVAL(pdata,0);
4022 if (total_data > 0 && ea_size != total_data) {
4023 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4024 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4025 reply_nterror(
4026 req, NT_STATUS_INVALID_PARAMETER);
4027 return;
4030 if (!lp_ea_support(SNUM(conn))) {
4031 reply_doserror(req, ERRDOS,
4032 ERReasnotsupported);
4033 return;
4036 /* Pull out the list of names. */
4037 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4038 if (!ea_list) {
4039 reply_nterror(
4040 req, NT_STATUS_INVALID_PARAMETER);
4041 return;
4043 break;
4046 case SMB_QUERY_POSIX_LOCK:
4048 if (fsp == NULL || fsp->fh->fd == -1) {
4049 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4050 return;
4053 if (total_data != POSIX_LOCK_DATA_SIZE) {
4054 reply_nterror(
4055 req, NT_STATUS_INVALID_PARAMETER);
4056 return;
4059 /* Copy the lock range data. */
4060 lock_data = (char *)TALLOC_MEMDUP(
4061 ctx, pdata, total_data);
4062 if (!lock_data) {
4063 reply_nterror(req, NT_STATUS_NO_MEMORY);
4064 return;
4067 default:
4068 break;
4071 *pparams = (char *)SMB_REALLOC(*pparams,2);
4072 if (*pparams == NULL) {
4073 reply_nterror(req, NT_STATUS_NO_MEMORY);
4074 return;
4076 params = *pparams;
4077 SSVAL(params,0,0);
4078 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4079 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4080 if (*ppdata == NULL ) {
4081 reply_nterror(req, NT_STATUS_NO_MEMORY);
4082 return;
4084 pdata = *ppdata;
4085 dstart = pdata;
4086 dend = dstart + data_size - 1;
4088 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4089 mtime_ts = get_mtimespec(&sbuf);
4090 atime_ts = get_atimespec(&sbuf);
4092 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4094 if (!fsp) {
4095 /* Do we have this path open ? */
4096 files_struct *fsp1;
4097 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4098 fsp1 = file_find_di_first(fileid);
4099 if (fsp1 && fsp1->initial_allocation_size) {
4100 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4104 if (!null_timespec(write_time_ts)) {
4105 mtime_ts = write_time_ts;
4108 if (lp_dos_filetime_resolution(SNUM(conn))) {
4109 dos_filetime_timespec(&create_time_ts);
4110 dos_filetime_timespec(&mtime_ts);
4111 dos_filetime_timespec(&atime_ts);
4114 create_time = convert_timespec_to_time_t(create_time_ts);
4115 mtime = convert_timespec_to_time_t(mtime_ts);
4116 atime = convert_timespec_to_time_t(atime_ts);
4118 /* NT expects the name to be in an exact form of the *full*
4119 filename. See the trans2 torture test */
4120 if (ISDOT(base_name)) {
4121 dos_fname = talloc_strdup(ctx, "\\");
4122 if (!dos_fname) {
4123 reply_nterror(req, NT_STATUS_NO_MEMORY);
4124 return;
4126 } else {
4127 dos_fname = talloc_asprintf(ctx,
4128 "\\%s",
4129 fname);
4130 if (!dos_fname) {
4131 reply_nterror(req, NT_STATUS_NO_MEMORY);
4132 return;
4134 string_replace(dos_fname, '/', '\\');
4137 switch (info_level) {
4138 case SMB_INFO_STANDARD:
4139 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4140 data_size = 22;
4141 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4142 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4143 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4144 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4145 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4146 SSVAL(pdata,l1_attrFile,mode);
4147 break;
4149 case SMB_INFO_QUERY_EA_SIZE:
4151 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4152 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4153 data_size = 26;
4154 srv_put_dos_date2(pdata,0,create_time);
4155 srv_put_dos_date2(pdata,4,atime);
4156 srv_put_dos_date2(pdata,8,mtime); /* write time */
4157 SIVAL(pdata,12,(uint32)file_size);
4158 SIVAL(pdata,16,(uint32)allocation_size);
4159 SSVAL(pdata,20,mode);
4160 SIVAL(pdata,22,ea_size);
4161 break;
4164 case SMB_INFO_IS_NAME_VALID:
4165 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4166 if (tran_call == TRANSACT2_QFILEINFO) {
4167 /* os/2 needs this ? really ?*/
4168 reply_doserror(req, ERRDOS, ERRbadfunc);
4169 return;
4171 data_size = 0;
4172 param_size = 0;
4173 break;
4175 case SMB_INFO_QUERY_EAS_FROM_LIST:
4177 size_t total_ea_len = 0;
4178 struct ea_list *ea_file_list = NULL;
4180 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4182 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4183 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4185 if (!ea_list || (total_ea_len > data_size)) {
4186 data_size = 4;
4187 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4188 break;
4191 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4192 break;
4195 case SMB_INFO_QUERY_ALL_EAS:
4197 /* We have data_size bytes to put EA's into. */
4198 size_t total_ea_len = 0;
4200 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4202 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4203 if (!ea_list || (total_ea_len > data_size)) {
4204 data_size = 4;
4205 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4206 break;
4209 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4210 break;
4213 case SMB_FILE_BASIC_INFORMATION:
4214 case SMB_QUERY_FILE_BASIC_INFO:
4216 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4217 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4218 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4219 } else {
4220 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4221 data_size = 40;
4222 SIVAL(pdata,36,0);
4224 put_long_date_timespec(pdata,create_time_ts);
4225 put_long_date_timespec(pdata+8,atime_ts);
4226 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4227 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4228 SIVAL(pdata,32,mode);
4230 DEBUG(5,("SMB_QFBI - "));
4231 DEBUG(5,("create: %s ", ctime(&create_time)));
4232 DEBUG(5,("access: %s ", ctime(&atime)));
4233 DEBUG(5,("write: %s ", ctime(&mtime)));
4234 DEBUG(5,("change: %s ", ctime(&mtime)));
4235 DEBUG(5,("mode: %x\n", mode));
4236 break;
4238 case SMB_FILE_STANDARD_INFORMATION:
4239 case SMB_QUERY_FILE_STANDARD_INFO:
4241 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4242 data_size = 24;
4243 SOFF_T(pdata,0,allocation_size);
4244 SOFF_T(pdata,8,file_size);
4245 SIVAL(pdata,16,nlink);
4246 SCVAL(pdata,20,delete_pending?1:0);
4247 SCVAL(pdata,21,(mode&aDIR)?1:0);
4248 SSVAL(pdata,22,0); /* Padding. */
4249 break;
4251 case SMB_FILE_EA_INFORMATION:
4252 case SMB_QUERY_FILE_EA_INFO:
4254 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4255 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4256 data_size = 4;
4257 SIVAL(pdata,0,ea_size);
4258 break;
4261 /* Get the 8.3 name - used if NT SMB was negotiated. */
4262 case SMB_QUERY_FILE_ALT_NAME_INFO:
4263 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4265 char mangled_name[13];
4266 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4267 if (!name_to_8_3(base_name,mangled_name,
4268 True,conn->params)) {
4269 reply_nterror(
4270 req,
4271 NT_STATUS_NO_MEMORY);
4273 len = srvstr_push(dstart, req->flags2,
4274 pdata+4, mangled_name,
4275 PTR_DIFF(dend, pdata+4),
4276 STR_UNICODE);
4277 data_size = 4 + len;
4278 SIVAL(pdata,0,len);
4279 break;
4282 case SMB_QUERY_FILE_NAME_INFO:
4284 this must be *exactly* right for ACLs on mapped drives to work
4286 len = srvstr_push(dstart, req->flags2,
4287 pdata+4, dos_fname,
4288 PTR_DIFF(dend, pdata+4),
4289 STR_UNICODE);
4290 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4291 data_size = 4 + len;
4292 SIVAL(pdata,0,len);
4293 break;
4295 case SMB_FILE_ALLOCATION_INFORMATION:
4296 case SMB_QUERY_FILE_ALLOCATION_INFO:
4297 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4298 data_size = 8;
4299 SOFF_T(pdata,0,allocation_size);
4300 break;
4302 case SMB_FILE_END_OF_FILE_INFORMATION:
4303 case SMB_QUERY_FILE_END_OF_FILEINFO:
4304 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4305 data_size = 8;
4306 SOFF_T(pdata,0,file_size);
4307 break;
4309 case SMB_QUERY_FILE_ALL_INFO:
4310 case SMB_FILE_ALL_INFORMATION:
4312 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4313 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4314 put_long_date_timespec(pdata,create_time_ts);
4315 put_long_date_timespec(pdata+8,atime_ts);
4316 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4317 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4318 SIVAL(pdata,32,mode);
4319 SIVAL(pdata,36,0); /* padding. */
4320 pdata += 40;
4321 SOFF_T(pdata,0,allocation_size);
4322 SOFF_T(pdata,8,file_size);
4323 SIVAL(pdata,16,nlink);
4324 SCVAL(pdata,20,delete_pending);
4325 SCVAL(pdata,21,(mode&aDIR)?1:0);
4326 SSVAL(pdata,22,0);
4327 pdata += 24;
4328 SIVAL(pdata,0,ea_size);
4329 pdata += 4; /* EA info */
4330 len = srvstr_push(dstart, req->flags2,
4331 pdata+4, dos_fname,
4332 PTR_DIFF(dend, pdata+4),
4333 STR_UNICODE);
4334 SIVAL(pdata,0,len);
4335 pdata += 4 + len;
4336 data_size = PTR_DIFF(pdata,(*ppdata));
4337 break;
4339 case SMB_FILE_INTERNAL_INFORMATION:
4340 /* This should be an index number - looks like
4341 dev/ino to me :-)
4343 I think this causes us to fail the IFSKIT
4344 BasicFileInformationTest. -tpot */
4346 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4347 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4348 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4349 data_size = 8;
4350 break;
4352 case SMB_FILE_ACCESS_INFORMATION:
4353 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4354 SIVAL(pdata,0,access_mask);
4355 data_size = 4;
4356 break;
4358 case SMB_FILE_NAME_INFORMATION:
4359 /* Pathname with leading '\'. */
4361 size_t byte_len;
4362 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4363 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4364 SIVAL(pdata,0,byte_len);
4365 data_size = 4 + byte_len;
4366 break;
4369 case SMB_FILE_DISPOSITION_INFORMATION:
4370 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4371 data_size = 1;
4372 SCVAL(pdata,0,delete_pending);
4373 break;
4375 case SMB_FILE_POSITION_INFORMATION:
4376 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4377 data_size = 8;
4378 SOFF_T(pdata,0,pos);
4379 break;
4381 case SMB_FILE_MODE_INFORMATION:
4382 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4383 SIVAL(pdata,0,mode);
4384 data_size = 4;
4385 break;
4387 case SMB_FILE_ALIGNMENT_INFORMATION:
4388 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4389 SIVAL(pdata,0,0); /* No alignment needed. */
4390 data_size = 4;
4391 break;
4394 * NT4 server just returns "invalid query" to this - if we try
4395 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4396 * want this. JRA.
4398 /* The first statement above is false - verified using Thursby
4399 * client against NT4 -- gcolley.
4401 case SMB_QUERY_FILE_STREAM_INFO:
4402 case SMB_FILE_STREAM_INFORMATION: {
4403 unsigned int num_streams;
4404 struct stream_struct *streams;
4405 NTSTATUS status;
4407 DEBUG(10,("call_trans2qfilepathinfo: "
4408 "SMB_FILE_STREAM_INFORMATION\n"));
4410 status = SMB_VFS_STREAMINFO(
4411 conn, fsp, fname, talloc_tos(),
4412 &num_streams, &streams);
4414 if (!NT_STATUS_IS_OK(status)) {
4415 DEBUG(10, ("could not get stream info: %s\n",
4416 nt_errstr(status)));
4417 reply_nterror(req, status);
4418 return;
4421 status = marshall_stream_info(num_streams, streams,
4422 pdata, max_data_bytes,
4423 &data_size);
4425 if (!NT_STATUS_IS_OK(status)) {
4426 DEBUG(10, ("marshall_stream_info failed: %s\n",
4427 nt_errstr(status)));
4428 reply_nterror(req, status);
4429 return;
4432 TALLOC_FREE(streams);
4434 break;
4436 case SMB_QUERY_COMPRESSION_INFO:
4437 case SMB_FILE_COMPRESSION_INFORMATION:
4438 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4439 SOFF_T(pdata,0,file_size);
4440 SIVAL(pdata,8,0); /* ??? */
4441 SIVAL(pdata,12,0); /* ??? */
4442 data_size = 16;
4443 break;
4445 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4446 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4447 put_long_date_timespec(pdata,create_time_ts);
4448 put_long_date_timespec(pdata+8,atime_ts);
4449 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4450 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4451 SOFF_T(pdata,32,allocation_size);
4452 SOFF_T(pdata,40,file_size);
4453 SIVAL(pdata,48,mode);
4454 SIVAL(pdata,52,0); /* ??? */
4455 data_size = 56;
4456 break;
4458 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4459 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4460 SIVAL(pdata,0,mode);
4461 SIVAL(pdata,4,0);
4462 data_size = 8;
4463 break;
4466 * CIFS UNIX Extensions.
4469 case SMB_QUERY_FILE_UNIX_BASIC:
4471 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4472 data_size = PTR_DIFF(pdata,(*ppdata));
4475 int i;
4476 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4478 for (i=0; i<100; i++)
4479 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4480 DEBUG(4,("\n"));
4483 break;
4485 case SMB_QUERY_FILE_UNIX_INFO2:
4487 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4488 data_size = PTR_DIFF(pdata,(*ppdata));
4491 int i;
4492 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4494 for (i=0; i<100; i++)
4495 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4496 DEBUG(4,("\n"));
4499 break;
4501 case SMB_QUERY_FILE_UNIX_LINK:
4503 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4505 if (!buffer) {
4506 reply_nterror(req, NT_STATUS_NO_MEMORY);
4507 return;
4510 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4511 #ifdef S_ISLNK
4512 if(!S_ISLNK(sbuf.st_mode)) {
4513 reply_unixerror(req, ERRSRV,
4514 ERRbadlink);
4515 return;
4517 #else
4518 reply_unixerror(req, ERRDOS, ERRbadlink);
4519 return;
4520 #endif
4521 len = SMB_VFS_READLINK(conn,fullpathname,
4522 buffer, PATH_MAX);
4523 if (len == -1) {
4524 reply_unixerror(req, ERRDOS,
4525 ERRnoaccess);
4526 return;
4528 buffer[len] = 0;
4529 len = srvstr_push(dstart, req->flags2,
4530 pdata, buffer,
4531 PTR_DIFF(dend, pdata),
4532 STR_TERMINATE);
4533 pdata += len;
4534 data_size = PTR_DIFF(pdata,(*ppdata));
4536 break;
4539 #if defined(HAVE_POSIX_ACLS)
4540 case SMB_QUERY_POSIX_ACL:
4542 SMB_ACL_T file_acl = NULL;
4543 SMB_ACL_T def_acl = NULL;
4544 uint16 num_file_acls = 0;
4545 uint16 num_def_acls = 0;
4547 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4548 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4549 } else {
4550 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4553 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4554 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4555 fname ));
4556 reply_nterror(
4557 req,
4558 NT_STATUS_NOT_IMPLEMENTED);
4559 return;
4562 if (S_ISDIR(sbuf.st_mode)) {
4563 if (fsp && fsp->is_directory) {
4564 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4565 } else {
4566 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4568 def_acl = free_empty_sys_acl(conn, def_acl);
4571 num_file_acls = count_acl_entries(conn, file_acl);
4572 num_def_acls = count_acl_entries(conn, def_acl);
4574 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4575 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4576 data_size,
4577 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4578 SMB_POSIX_ACL_HEADER_SIZE) ));
4579 if (file_acl) {
4580 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4582 if (def_acl) {
4583 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4585 reply_nterror(
4586 req,
4587 NT_STATUS_BUFFER_TOO_SMALL);
4588 return;
4591 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4592 SSVAL(pdata,2,num_file_acls);
4593 SSVAL(pdata,4,num_def_acls);
4594 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4595 if (file_acl) {
4596 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4598 if (def_acl) {
4599 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4601 reply_nterror(
4602 req, NT_STATUS_INTERNAL_ERROR);
4603 return;
4605 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4606 if (file_acl) {
4607 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4609 if (def_acl) {
4610 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4612 reply_nterror(
4613 req,
4614 NT_STATUS_INTERNAL_ERROR);
4615 return;
4618 if (file_acl) {
4619 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4621 if (def_acl) {
4622 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4624 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4625 break;
4627 #endif
4630 case SMB_QUERY_POSIX_LOCK:
4632 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4633 SMB_BIG_UINT count;
4634 SMB_BIG_UINT offset;
4635 uint32 lock_pid;
4636 enum brl_type lock_type;
4638 if (total_data != POSIX_LOCK_DATA_SIZE) {
4639 reply_nterror(
4640 req, NT_STATUS_INVALID_PARAMETER);
4641 return;
4644 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4645 case POSIX_LOCK_TYPE_READ:
4646 lock_type = READ_LOCK;
4647 break;
4648 case POSIX_LOCK_TYPE_WRITE:
4649 lock_type = WRITE_LOCK;
4650 break;
4651 case POSIX_LOCK_TYPE_UNLOCK:
4652 default:
4653 /* There's no point in asking for an unlock... */
4654 reply_nterror(
4655 req,
4656 NT_STATUS_INVALID_PARAMETER);
4657 return;
4660 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4661 #if defined(HAVE_LONGLONG)
4662 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4663 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4664 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4665 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4666 #else /* HAVE_LONGLONG */
4667 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4668 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4669 #endif /* HAVE_LONGLONG */
4671 status = query_lock(fsp,
4672 &lock_pid,
4673 &count,
4674 &offset,
4675 &lock_type,
4676 POSIX_LOCK);
4678 if (ERROR_WAS_LOCK_DENIED(status)) {
4679 /* Here we need to report who has it locked... */
4680 data_size = POSIX_LOCK_DATA_SIZE;
4682 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4683 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4684 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4685 #if defined(HAVE_LONGLONG)
4686 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4687 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4688 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4689 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4690 #else /* HAVE_LONGLONG */
4691 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4692 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4693 #endif /* HAVE_LONGLONG */
4695 } else if (NT_STATUS_IS_OK(status)) {
4696 /* For success we just return a copy of what we sent
4697 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4698 data_size = POSIX_LOCK_DATA_SIZE;
4699 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4700 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4701 } else {
4702 reply_nterror(req, status);
4703 return;
4705 break;
4708 default:
4709 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4710 return;
4713 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4714 max_data_bytes);
4716 return;
4719 /****************************************************************************
4720 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4721 code.
4722 ****************************************************************************/
4724 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4725 connection_struct *conn,
4726 const char *oldname_in,
4727 const char *newname_in)
4729 SMB_STRUCT_STAT sbuf1, sbuf2;
4730 char *last_component_oldname = NULL;
4731 char *last_component_newname = NULL;
4732 char *oldname = NULL;
4733 char *newname = NULL;
4734 NTSTATUS status = NT_STATUS_OK;
4736 ZERO_STRUCT(sbuf1);
4737 ZERO_STRUCT(sbuf2);
4739 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4740 &last_component_oldname, &sbuf1);
4741 if (!NT_STATUS_IS_OK(status)) {
4742 return status;
4745 status = check_name(conn, oldname);
4746 if (!NT_STATUS_IS_OK(status)) {
4747 return status;
4750 /* source must already exist. */
4751 if (!VALID_STAT(sbuf1)) {
4752 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4755 status = unix_convert(ctx, conn, newname_in, False, &newname,
4756 &last_component_newname, &sbuf2);
4757 if (!NT_STATUS_IS_OK(status)) {
4758 return status;
4761 status = check_name(conn, newname);
4762 if (!NT_STATUS_IS_OK(status)) {
4763 return status;
4766 /* Disallow if newname already exists. */
4767 if (VALID_STAT(sbuf2)) {
4768 return NT_STATUS_OBJECT_NAME_COLLISION;
4771 /* No links from a directory. */
4772 if (S_ISDIR(sbuf1.st_mode)) {
4773 return NT_STATUS_FILE_IS_A_DIRECTORY;
4776 /* Ensure this is within the share. */
4777 status = check_reduced_name(conn, oldname);
4778 if (!NT_STATUS_IS_OK(status)) {
4779 return status;
4782 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4784 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4785 status = map_nt_error_from_unix(errno);
4786 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4787 nt_errstr(status), newname, oldname));
4790 return status;
4793 /****************************************************************************
4794 Deal with setting the time from any of the setfilepathinfo functions.
4795 ****************************************************************************/
4797 NTSTATUS smb_set_file_time(connection_struct *conn,
4798 files_struct *fsp,
4799 const char *fname,
4800 const SMB_STRUCT_STAT *psbuf,
4801 struct timespec ts[2],
4802 bool setting_write_time)
4804 uint32 action =
4805 FILE_NOTIFY_CHANGE_LAST_ACCESS
4806 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4808 if (!VALID_STAT(*psbuf)) {
4809 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4812 /* get some defaults (no modifications) if any info is zero or -1. */
4813 if (null_timespec(ts[0])) {
4814 ts[0] = get_atimespec(psbuf);
4815 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4818 if (null_timespec(ts[1])) {
4819 ts[1] = get_mtimespec(psbuf);
4820 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4823 if (!setting_write_time) {
4824 /* ts[1] comes from change time, not write time. */
4825 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4828 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4829 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4832 * Try and set the times of this file if
4833 * they are different from the current values.
4837 struct timespec mts = get_mtimespec(psbuf);
4838 struct timespec ats = get_atimespec(psbuf);
4839 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4840 return NT_STATUS_OK;
4844 if (setting_write_time) {
4846 * This was a setfileinfo on an open file.
4847 * NT does this a lot. We also need to
4848 * set the time here, as it can be read by
4849 * FindFirst/FindNext and with the patch for bug #2045
4850 * in smbd/fileio.c it ensures that this timestamp is
4851 * kept sticky even after a write. We save the request
4852 * away and will set it on file close and after a write. JRA.
4855 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4856 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4858 if (fsp != NULL) {
4859 set_write_time_fsp(fsp, ts[1], true);
4860 } else {
4861 set_write_time_path(conn, fname,
4862 vfs_file_id_from_sbuf(conn, psbuf),
4863 ts[1], true);
4867 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4869 if(file_ntimes(conn, fname, ts)!=0) {
4870 return map_nt_error_from_unix(errno);
4872 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4874 return NT_STATUS_OK;
4877 /****************************************************************************
4878 Deal with setting the dosmode from any of the setfilepathinfo functions.
4879 ****************************************************************************/
4881 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4882 const char *fname,
4883 SMB_STRUCT_STAT *psbuf,
4884 uint32 dosmode)
4886 if (!VALID_STAT(*psbuf)) {
4887 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4890 if (dosmode) {
4891 if (S_ISDIR(psbuf->st_mode)) {
4892 dosmode |= aDIR;
4893 } else {
4894 dosmode &= ~aDIR;
4898 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4900 /* check the mode isn't different, before changing it */
4901 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4903 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4904 fname, (unsigned int)dosmode ));
4906 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4907 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4908 fname, strerror(errno)));
4909 return map_nt_error_from_unix(errno);
4912 return NT_STATUS_OK;
4915 /****************************************************************************
4916 Deal with setting the size from any of the setfilepathinfo functions.
4917 ****************************************************************************/
4919 static NTSTATUS smb_set_file_size(connection_struct *conn,
4920 struct smb_request *req,
4921 files_struct *fsp,
4922 const char *fname,
4923 SMB_STRUCT_STAT *psbuf,
4924 SMB_OFF_T size)
4926 NTSTATUS status = NT_STATUS_OK;
4927 files_struct *new_fsp = NULL;
4929 if (!VALID_STAT(*psbuf)) {
4930 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4933 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4935 if (size == get_file_size(*psbuf)) {
4936 return NT_STATUS_OK;
4939 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4940 fname, (double)size ));
4942 if (fsp && fsp->fh->fd != -1) {
4943 /* Handle based call. */
4944 if (vfs_set_filelen(fsp, size) == -1) {
4945 return map_nt_error_from_unix(errno);
4947 return NT_STATUS_OK;
4950 status = open_file_ntcreate(conn, req, fname, psbuf,
4951 FILE_WRITE_ATTRIBUTES,
4952 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4953 FILE_OPEN,
4955 FILE_ATTRIBUTE_NORMAL,
4956 FORCE_OPLOCK_BREAK_TO_NONE,
4957 NULL, &new_fsp);
4959 if (!NT_STATUS_IS_OK(status)) {
4960 /* NB. We check for open_was_deferred in the caller. */
4961 return status;
4964 if (vfs_set_filelen(new_fsp, size) == -1) {
4965 status = map_nt_error_from_unix(errno);
4966 close_file(new_fsp,NORMAL_CLOSE);
4967 return status;
4970 close_file(new_fsp,NORMAL_CLOSE);
4971 return NT_STATUS_OK;
4974 /****************************************************************************
4975 Deal with SMB_INFO_SET_EA.
4976 ****************************************************************************/
4978 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4979 const char *pdata,
4980 int total_data,
4981 files_struct *fsp,
4982 const char *fname)
4984 struct ea_list *ea_list = NULL;
4985 TALLOC_CTX *ctx = NULL;
4986 NTSTATUS status = NT_STATUS_OK;
4988 if (total_data < 10) {
4990 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4991 length. They seem to have no effect. Bug #3212. JRA */
4993 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4994 /* We're done. We only get EA info in this call. */
4995 return NT_STATUS_OK;
4998 return NT_STATUS_INVALID_PARAMETER;
5001 if (IVAL(pdata,0) > total_data) {
5002 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5003 IVAL(pdata,0), (unsigned int)total_data));
5004 return NT_STATUS_INVALID_PARAMETER;
5007 ctx = talloc_tos();
5008 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5009 if (!ea_list) {
5010 return NT_STATUS_INVALID_PARAMETER;
5012 status = set_ea(conn, fsp, fname, ea_list);
5014 return status;
5017 /****************************************************************************
5018 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5019 ****************************************************************************/
5021 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5022 const char *pdata,
5023 int total_data,
5024 files_struct *fsp,
5025 const char *fname,
5026 SMB_STRUCT_STAT *psbuf)
5028 NTSTATUS status = NT_STATUS_OK;
5029 bool delete_on_close;
5030 uint32 dosmode = 0;
5032 if (total_data < 1) {
5033 return NT_STATUS_INVALID_PARAMETER;
5036 if (fsp == NULL) {
5037 return NT_STATUS_INVALID_HANDLE;
5040 delete_on_close = (CVAL(pdata,0) ? True : False);
5041 dosmode = dos_mode(conn, fname, psbuf);
5043 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5044 "delete_on_close = %u\n",
5045 fsp->fsp_name,
5046 (unsigned int)dosmode,
5047 (unsigned int)delete_on_close ));
5049 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5051 if (!NT_STATUS_IS_OK(status)) {
5052 return status;
5055 /* The set is across all open files on this dev/inode pair. */
5056 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
5057 return NT_STATUS_ACCESS_DENIED;
5059 return NT_STATUS_OK;
5062 /****************************************************************************
5063 Deal with SMB_FILE_POSITION_INFORMATION.
5064 ****************************************************************************/
5066 static NTSTATUS smb_file_position_information(connection_struct *conn,
5067 const char *pdata,
5068 int total_data,
5069 files_struct *fsp)
5071 SMB_BIG_UINT position_information;
5073 if (total_data < 8) {
5074 return NT_STATUS_INVALID_PARAMETER;
5077 if (fsp == NULL) {
5078 /* Ignore on pathname based set. */
5079 return NT_STATUS_OK;
5082 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5083 #ifdef LARGE_SMB_OFF_T
5084 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5085 #else /* LARGE_SMB_OFF_T */
5086 if (IVAL(pdata,4) != 0) {
5087 /* more than 32 bits? */
5088 return NT_STATUS_INVALID_PARAMETER;
5090 #endif /* LARGE_SMB_OFF_T */
5092 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5093 fsp->fsp_name, (double)position_information ));
5094 fsp->fh->position_information = position_information;
5095 return NT_STATUS_OK;
5098 /****************************************************************************
5099 Deal with SMB_FILE_MODE_INFORMATION.
5100 ****************************************************************************/
5102 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5103 const char *pdata,
5104 int total_data)
5106 uint32 mode;
5108 if (total_data < 4) {
5109 return NT_STATUS_INVALID_PARAMETER;
5111 mode = IVAL(pdata,0);
5112 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5113 return NT_STATUS_INVALID_PARAMETER;
5115 return NT_STATUS_OK;
5118 /****************************************************************************
5119 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5120 ****************************************************************************/
5122 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5123 struct smb_request *req,
5124 const char *pdata,
5125 int total_data,
5126 const char *fname)
5128 char *link_target = NULL;
5129 const char *newname = fname;
5130 NTSTATUS status = NT_STATUS_OK;
5131 TALLOC_CTX *ctx = talloc_tos();
5133 /* Set a symbolic link. */
5134 /* Don't allow this if follow links is false. */
5136 if (total_data == 0) {
5137 return NT_STATUS_INVALID_PARAMETER;
5140 if (!lp_symlinks(SNUM(conn))) {
5141 return NT_STATUS_ACCESS_DENIED;
5144 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5145 total_data, STR_TERMINATE);
5147 if (!link_target) {
5148 return NT_STATUS_INVALID_PARAMETER;
5151 /* !widelinks forces the target path to be within the share. */
5152 /* This means we can interpret the target as a pathname. */
5153 if (!lp_widelinks(SNUM(conn))) {
5154 char *rel_name = NULL;
5155 char *last_dirp = NULL;
5157 if (*link_target == '/') {
5158 /* No absolute paths allowed. */
5159 return NT_STATUS_ACCESS_DENIED;
5161 rel_name = talloc_strdup(ctx,newname);
5162 if (!rel_name) {
5163 return NT_STATUS_NO_MEMORY;
5165 last_dirp = strrchr_m(rel_name, '/');
5166 if (last_dirp) {
5167 last_dirp[1] = '\0';
5168 } else {
5169 rel_name = talloc_strdup(ctx,"./");
5170 if (!rel_name) {
5171 return NT_STATUS_NO_MEMORY;
5174 rel_name = talloc_asprintf_append(rel_name,
5175 "%s",
5176 link_target);
5177 if (!rel_name) {
5178 return NT_STATUS_NO_MEMORY;
5181 status = check_name(conn, rel_name);
5182 if (!NT_STATUS_IS_OK(status)) {
5183 return status;
5187 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5188 newname, link_target ));
5190 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5191 return map_nt_error_from_unix(errno);
5194 return NT_STATUS_OK;
5197 /****************************************************************************
5198 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5199 ****************************************************************************/
5201 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5202 struct smb_request *req,
5203 const char *pdata, int total_data,
5204 const char *fname)
5206 char *oldname = NULL;
5207 TALLOC_CTX *ctx = talloc_tos();
5208 NTSTATUS status = NT_STATUS_OK;
5210 /* Set a hard link. */
5211 if (total_data == 0) {
5212 return NT_STATUS_INVALID_PARAMETER;
5215 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5216 total_data, STR_TERMINATE, &status);
5217 if (!NT_STATUS_IS_OK(status)) {
5218 return status;
5221 status = resolve_dfspath(ctx, conn,
5222 req->flags2 & FLAGS2_DFS_PATHNAMES,
5223 oldname,
5224 &oldname);
5225 if (!NT_STATUS_IS_OK(status)) {
5226 return status;
5229 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5230 fname, oldname));
5232 return hardlink_internals(ctx, conn, oldname, fname);
5235 /****************************************************************************
5236 Deal with SMB_FILE_RENAME_INFORMATION.
5237 ****************************************************************************/
5239 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5240 struct smb_request *req,
5241 const char *pdata,
5242 int total_data,
5243 files_struct *fsp,
5244 const char *fname)
5246 bool overwrite;
5247 uint32 root_fid;
5248 uint32 len;
5249 char *newname = NULL;
5250 char *base_name = NULL;
5251 bool dest_has_wcard = False;
5252 NTSTATUS status = NT_STATUS_OK;
5253 char *p;
5254 TALLOC_CTX *ctx = talloc_tos();
5256 if (total_data < 13) {
5257 return NT_STATUS_INVALID_PARAMETER;
5260 overwrite = (CVAL(pdata,0) ? True : False);
5261 root_fid = IVAL(pdata,4);
5262 len = IVAL(pdata,8);
5264 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5265 return NT_STATUS_INVALID_PARAMETER;
5268 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5269 len, 0, &status,
5270 &dest_has_wcard);
5271 if (!NT_STATUS_IS_OK(status)) {
5272 return status;
5275 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5276 newname));
5278 status = resolve_dfspath_wcard(ctx, conn,
5279 req->flags2 & FLAGS2_DFS_PATHNAMES,
5280 newname,
5281 &newname,
5282 &dest_has_wcard);
5283 if (!NT_STATUS_IS_OK(status)) {
5284 return status;
5287 /* Check the new name has no '/' characters. */
5288 if (strchr_m(newname, '/')) {
5289 return NT_STATUS_NOT_SUPPORTED;
5292 /* Create the base directory. */
5293 base_name = talloc_strdup(ctx, fname);
5294 if (!base_name) {
5295 return NT_STATUS_NO_MEMORY;
5297 p = strrchr_m(base_name, '/');
5298 if (p) {
5299 p[1] = '\0';
5300 } else {
5301 base_name = talloc_strdup(ctx, "./");
5302 if (!base_name) {
5303 return NT_STATUS_NO_MEMORY;
5306 /* Append the new name. */
5307 base_name = talloc_asprintf_append(base_name,
5308 "%s",
5309 newname);
5310 if (!base_name) {
5311 return NT_STATUS_NO_MEMORY;
5314 if (fsp) {
5315 SMB_STRUCT_STAT sbuf;
5316 char *newname_last_component = NULL;
5318 ZERO_STRUCT(sbuf);
5320 status = unix_convert(ctx, conn, newname, False,
5321 &newname,
5322 &newname_last_component,
5323 &sbuf);
5325 /* If an error we expect this to be
5326 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5328 if (!NT_STATUS_IS_OK(status)
5329 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5330 status)) {
5331 return status;
5334 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5335 fsp->fnum, fsp->fsp_name, base_name ));
5336 status = rename_internals_fsp(conn, fsp, base_name,
5337 newname_last_component, 0,
5338 overwrite);
5339 } else {
5340 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5341 fname, base_name ));
5342 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5343 overwrite, False, dest_has_wcard,
5344 FILE_WRITE_ATTRIBUTES);
5347 return status;
5350 /****************************************************************************
5351 Deal with SMB_SET_POSIX_ACL.
5352 ****************************************************************************/
5354 #if defined(HAVE_POSIX_ACLS)
5355 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5356 const char *pdata,
5357 int total_data,
5358 files_struct *fsp,
5359 const char *fname,
5360 SMB_STRUCT_STAT *psbuf)
5362 uint16 posix_acl_version;
5363 uint16 num_file_acls;
5364 uint16 num_def_acls;
5365 bool valid_file_acls = True;
5366 bool valid_def_acls = True;
5368 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5369 return NT_STATUS_INVALID_PARAMETER;
5371 posix_acl_version = SVAL(pdata,0);
5372 num_file_acls = SVAL(pdata,2);
5373 num_def_acls = SVAL(pdata,4);
5375 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5376 valid_file_acls = False;
5377 num_file_acls = 0;
5380 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5381 valid_def_acls = False;
5382 num_def_acls = 0;
5385 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5386 return NT_STATUS_INVALID_PARAMETER;
5389 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5390 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5391 return NT_STATUS_INVALID_PARAMETER;
5394 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5395 fname ? fname : fsp->fsp_name,
5396 (unsigned int)num_file_acls,
5397 (unsigned int)num_def_acls));
5399 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5400 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5401 return map_nt_error_from_unix(errno);
5404 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5405 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5406 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5407 return map_nt_error_from_unix(errno);
5409 return NT_STATUS_OK;
5411 #endif
5413 /****************************************************************************
5414 Deal with SMB_SET_POSIX_LOCK.
5415 ****************************************************************************/
5417 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5418 const struct smb_request *req,
5419 const char *pdata,
5420 int total_data,
5421 files_struct *fsp)
5423 SMB_BIG_UINT count;
5424 SMB_BIG_UINT offset;
5425 uint32 lock_pid;
5426 bool blocking_lock = False;
5427 enum brl_type lock_type;
5429 NTSTATUS status = NT_STATUS_OK;
5431 if (fsp == NULL || fsp->fh->fd == -1) {
5432 return NT_STATUS_INVALID_HANDLE;
5435 if (total_data != POSIX_LOCK_DATA_SIZE) {
5436 return NT_STATUS_INVALID_PARAMETER;
5439 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5440 case POSIX_LOCK_TYPE_READ:
5441 lock_type = READ_LOCK;
5442 break;
5443 case POSIX_LOCK_TYPE_WRITE:
5444 /* Return the right POSIX-mappable error code for files opened read-only. */
5445 if (!fsp->can_write) {
5446 return NT_STATUS_INVALID_HANDLE;
5448 lock_type = WRITE_LOCK;
5449 break;
5450 case POSIX_LOCK_TYPE_UNLOCK:
5451 lock_type = UNLOCK_LOCK;
5452 break;
5453 default:
5454 return NT_STATUS_INVALID_PARAMETER;
5457 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5458 blocking_lock = False;
5459 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5460 blocking_lock = True;
5461 } else {
5462 return NT_STATUS_INVALID_PARAMETER;
5465 if (!lp_blocking_locks(SNUM(conn))) {
5466 blocking_lock = False;
5469 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5470 #if defined(HAVE_LONGLONG)
5471 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5472 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5473 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5474 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5475 #else /* HAVE_LONGLONG */
5476 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5477 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5478 #endif /* HAVE_LONGLONG */
5480 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5481 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5482 fsp->fsp_name,
5483 (unsigned int)lock_type,
5484 (unsigned int)lock_pid,
5485 (double)count,
5486 (double)offset ));
5488 if (lock_type == UNLOCK_LOCK) {
5489 status = do_unlock(smbd_messaging_context(),
5490 fsp,
5491 lock_pid,
5492 count,
5493 offset,
5494 POSIX_LOCK);
5495 } else {
5496 uint32 block_smbpid;
5498 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5499 fsp,
5500 lock_pid,
5501 count,
5502 offset,
5503 lock_type,
5504 POSIX_LOCK,
5505 blocking_lock,
5506 &status,
5507 &block_smbpid);
5509 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5511 * A blocking lock was requested. Package up
5512 * this smb into a queued request and push it
5513 * onto the blocking lock queue.
5515 if(push_blocking_lock_request(br_lck,
5516 req,
5517 fsp,
5518 -1, /* infinite timeout. */
5520 lock_pid,
5521 lock_type,
5522 POSIX_LOCK,
5523 offset,
5524 count,
5525 block_smbpid)) {
5526 TALLOC_FREE(br_lck);
5527 return status;
5530 TALLOC_FREE(br_lck);
5533 return status;
5536 /****************************************************************************
5537 Deal with SMB_INFO_STANDARD.
5538 ****************************************************************************/
5540 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5541 const char *pdata,
5542 int total_data,
5543 files_struct *fsp,
5544 const char *fname,
5545 const SMB_STRUCT_STAT *psbuf)
5547 struct timespec ts[2];
5549 if (total_data < 12) {
5550 return NT_STATUS_INVALID_PARAMETER;
5553 /* access time */
5554 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5555 /* write time */
5556 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5558 DEBUG(10,("smb_set_info_standard: file %s\n",
5559 fname ? fname : fsp->fsp_name ));
5561 return smb_set_file_time(conn,
5562 fsp,
5563 fname,
5564 psbuf,
5566 true);
5569 /****************************************************************************
5570 Deal with SMB_SET_FILE_BASIC_INFO.
5571 ****************************************************************************/
5573 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5574 const char *pdata,
5575 int total_data,
5576 files_struct *fsp,
5577 const char *fname,
5578 SMB_STRUCT_STAT *psbuf)
5580 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5581 struct timespec write_time;
5582 struct timespec changed_time;
5583 uint32 dosmode = 0;
5584 struct timespec ts[2];
5585 NTSTATUS status = NT_STATUS_OK;
5586 bool setting_write_time = true;
5588 if (total_data < 36) {
5589 return NT_STATUS_INVALID_PARAMETER;
5592 /* Set the attributes */
5593 dosmode = IVAL(pdata,32);
5594 status = smb_set_file_dosmode(conn,
5595 fname,
5596 psbuf,
5597 dosmode);
5598 if (!NT_STATUS_IS_OK(status)) {
5599 return status;
5602 /* Ignore create time at offset pdata. */
5604 /* access time */
5605 ts[0] = interpret_long_date(pdata+8);
5607 write_time = interpret_long_date(pdata+16);
5608 changed_time = interpret_long_date(pdata+24);
5610 /* mtime */
5611 ts[1] = timespec_min(&write_time, &changed_time);
5613 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5614 ts[1] = write_time;
5617 /* Prefer a defined time to an undefined one. */
5618 if (null_timespec(ts[1])) {
5619 if (null_timespec(write_time)) {
5620 ts[1] = changed_time;
5621 setting_write_time = false;
5622 } else {
5623 ts[1] = write_time;
5627 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5628 fname ? fname : fsp->fsp_name ));
5630 return smb_set_file_time(conn,
5631 fsp,
5632 fname,
5633 psbuf,
5635 setting_write_time);
5638 /****************************************************************************
5639 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5640 ****************************************************************************/
5642 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5643 struct smb_request *req,
5644 const char *pdata,
5645 int total_data,
5646 files_struct *fsp,
5647 const char *fname,
5648 SMB_STRUCT_STAT *psbuf)
5650 SMB_BIG_UINT allocation_size = 0;
5651 NTSTATUS status = NT_STATUS_OK;
5652 files_struct *new_fsp = NULL;
5654 if (!VALID_STAT(*psbuf)) {
5655 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5658 if (total_data < 8) {
5659 return NT_STATUS_INVALID_PARAMETER;
5662 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5663 #ifdef LARGE_SMB_OFF_T
5664 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5665 #else /* LARGE_SMB_OFF_T */
5666 if (IVAL(pdata,4) != 0) {
5667 /* more than 32 bits? */
5668 return NT_STATUS_INVALID_PARAMETER;
5670 #endif /* LARGE_SMB_OFF_T */
5672 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5673 fname, (double)allocation_size ));
5675 if (allocation_size) {
5676 allocation_size = smb_roundup(conn, allocation_size);
5679 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5680 fname, (double)allocation_size ));
5682 if (fsp && fsp->fh->fd != -1) {
5683 /* Open file handle. */
5684 /* Only change if needed. */
5685 if (allocation_size != get_file_size(*psbuf)) {
5686 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5687 return map_nt_error_from_unix(errno);
5690 /* But always update the time. */
5692 * This is equivalent to a write. Ensure it's seen immediately
5693 * if there are no pending writes.
5695 trigger_write_time_update(fsp);
5696 return NT_STATUS_OK;
5699 /* Pathname or stat or directory file. */
5701 status = open_file_ntcreate(conn, req, fname, psbuf,
5702 FILE_WRITE_DATA,
5703 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5704 FILE_OPEN,
5706 FILE_ATTRIBUTE_NORMAL,
5707 FORCE_OPLOCK_BREAK_TO_NONE,
5708 NULL, &new_fsp);
5710 if (!NT_STATUS_IS_OK(status)) {
5711 /* NB. We check for open_was_deferred in the caller. */
5712 return status;
5715 /* Only change if needed. */
5716 if (allocation_size != get_file_size(*psbuf)) {
5717 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5718 status = map_nt_error_from_unix(errno);
5719 close_file(new_fsp,NORMAL_CLOSE);
5720 return status;
5724 /* Changing the allocation size should set the last mod time. */
5726 * This is equivalent to a write. Ensure it's seen immediately
5727 * if there are no pending writes.
5729 trigger_write_time_update(new_fsp);
5731 close_file(new_fsp,NORMAL_CLOSE);
5732 return NT_STATUS_OK;
5735 /****************************************************************************
5736 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5737 ****************************************************************************/
5739 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5740 struct smb_request *req,
5741 const char *pdata,
5742 int total_data,
5743 files_struct *fsp,
5744 const char *fname,
5745 SMB_STRUCT_STAT *psbuf)
5747 SMB_OFF_T size;
5749 if (total_data < 8) {
5750 return NT_STATUS_INVALID_PARAMETER;
5753 size = IVAL(pdata,0);
5754 #ifdef LARGE_SMB_OFF_T
5755 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5756 #else /* LARGE_SMB_OFF_T */
5757 if (IVAL(pdata,4) != 0) {
5758 /* more than 32 bits? */
5759 return NT_STATUS_INVALID_PARAMETER;
5761 #endif /* LARGE_SMB_OFF_T */
5762 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5763 "file %s to %.0f\n", fname, (double)size ));
5765 return smb_set_file_size(conn, req,
5766 fsp,
5767 fname,
5768 psbuf,
5769 size);
5772 /****************************************************************************
5773 Allow a UNIX info mknod.
5774 ****************************************************************************/
5776 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5777 const char *pdata,
5778 int total_data,
5779 const char *fname,
5780 SMB_STRUCT_STAT *psbuf)
5782 uint32 file_type = IVAL(pdata,56);
5783 #if defined(HAVE_MAKEDEV)
5784 uint32 dev_major = IVAL(pdata,60);
5785 uint32 dev_minor = IVAL(pdata,68);
5786 #endif
5787 SMB_DEV_T dev = (SMB_DEV_T)0;
5788 uint32 raw_unixmode = IVAL(pdata,84);
5789 NTSTATUS status;
5790 mode_t unixmode;
5792 if (total_data < 100) {
5793 return NT_STATUS_INVALID_PARAMETER;
5796 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5797 if (!NT_STATUS_IS_OK(status)) {
5798 return status;
5801 #if defined(HAVE_MAKEDEV)
5802 dev = makedev(dev_major, dev_minor);
5803 #endif
5805 switch (file_type) {
5806 #if defined(S_IFIFO)
5807 case UNIX_TYPE_FIFO:
5808 unixmode |= S_IFIFO;
5809 break;
5810 #endif
5811 #if defined(S_IFSOCK)
5812 case UNIX_TYPE_SOCKET:
5813 unixmode |= S_IFSOCK;
5814 break;
5815 #endif
5816 #if defined(S_IFCHR)
5817 case UNIX_TYPE_CHARDEV:
5818 unixmode |= S_IFCHR;
5819 break;
5820 #endif
5821 #if defined(S_IFBLK)
5822 case UNIX_TYPE_BLKDEV:
5823 unixmode |= S_IFBLK;
5824 break;
5825 #endif
5826 default:
5827 return NT_STATUS_INVALID_PARAMETER;
5830 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5831 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5833 /* Ok - do the mknod. */
5834 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5835 return map_nt_error_from_unix(errno);
5838 /* If any of the other "set" calls fail we
5839 * don't want to end up with a half-constructed mknod.
5842 if (lp_inherit_perms(SNUM(conn))) {
5843 inherit_access_acl(
5844 conn, parent_dirname(fname),
5845 fname, unixmode);
5848 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5849 status = map_nt_error_from_unix(errno);
5850 SMB_VFS_UNLINK(conn,fname);
5851 return status;
5853 return NT_STATUS_OK;
5856 /****************************************************************************
5857 Deal with SMB_SET_FILE_UNIX_BASIC.
5858 ****************************************************************************/
5860 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5861 struct smb_request *req,
5862 const char *pdata,
5863 int total_data,
5864 files_struct *fsp,
5865 const char *fname,
5866 SMB_STRUCT_STAT *psbuf)
5868 struct timespec ts[2];
5869 uint32 raw_unixmode;
5870 mode_t unixmode;
5871 SMB_OFF_T size = 0;
5872 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5873 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5874 NTSTATUS status = NT_STATUS_OK;
5875 bool delete_on_fail = False;
5876 enum perm_type ptype;
5878 if (total_data < 100) {
5879 return NT_STATUS_INVALID_PARAMETER;
5882 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5883 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5884 size=IVAL(pdata,0); /* first 8 Bytes are size */
5885 #ifdef LARGE_SMB_OFF_T
5886 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5887 #else /* LARGE_SMB_OFF_T */
5888 if (IVAL(pdata,4) != 0) {
5889 /* more than 32 bits? */
5890 return NT_STATUS_INVALID_PARAMETER;
5892 #endif /* LARGE_SMB_OFF_T */
5895 ts[0] = interpret_long_date(pdata+24); /* access_time */
5896 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5897 set_owner = (uid_t)IVAL(pdata,40);
5898 set_grp = (gid_t)IVAL(pdata,48);
5899 raw_unixmode = IVAL(pdata,84);
5901 if (VALID_STAT(*psbuf)) {
5902 if (S_ISDIR(psbuf->st_mode)) {
5903 ptype = PERM_EXISTING_DIR;
5904 } else {
5905 ptype = PERM_EXISTING_FILE;
5907 } else {
5908 ptype = PERM_NEW_FILE;
5911 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5912 if (!NT_STATUS_IS_OK(status)) {
5913 return status;
5916 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5917 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5918 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5920 if (!VALID_STAT(*psbuf)) {
5922 * The only valid use of this is to create character and block
5923 * devices, and named pipes. This is deprecated (IMHO) and
5924 * a new info level should be used for mknod. JRA.
5927 status = smb_unix_mknod(conn,
5928 pdata,
5929 total_data,
5930 fname,
5931 psbuf);
5932 if (!NT_STATUS_IS_OK(status)) {
5933 return status;
5936 /* Ensure we don't try and change anything else. */
5937 raw_unixmode = SMB_MODE_NO_CHANGE;
5938 size = get_file_size(*psbuf);
5939 ts[0] = get_atimespec(psbuf);
5940 ts[1] = get_mtimespec(psbuf);
5942 * We continue here as we might want to change the
5943 * owner uid/gid.
5945 delete_on_fail = True;
5948 #if 1
5949 /* Horrible backwards compatibility hack as an old server bug
5950 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5951 * */
5953 if (!size) {
5954 size = get_file_size(*psbuf);
5956 #endif
5959 * Deal with the UNIX specific mode set.
5962 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5963 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5964 (unsigned int)unixmode, fname ));
5965 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5966 return map_nt_error_from_unix(errno);
5971 * Deal with the UNIX specific uid set.
5974 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5975 int ret;
5977 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5978 (unsigned int)set_owner, fname ));
5980 if (S_ISLNK(psbuf->st_mode)) {
5981 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5982 } else {
5983 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5986 if (ret != 0) {
5987 status = map_nt_error_from_unix(errno);
5988 if (delete_on_fail) {
5989 SMB_VFS_UNLINK(conn,fname);
5991 return status;
5996 * Deal with the UNIX specific gid set.
5999 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6000 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6001 (unsigned int)set_owner, fname ));
6002 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6003 status = map_nt_error_from_unix(errno);
6004 if (delete_on_fail) {
6005 SMB_VFS_UNLINK(conn,fname);
6007 return status;
6011 /* Deal with any size changes. */
6013 status = smb_set_file_size(conn, req,
6014 fsp,
6015 fname,
6016 psbuf,
6017 size);
6018 if (!NT_STATUS_IS_OK(status)) {
6019 return status;
6022 /* Deal with any time changes. */
6024 return smb_set_file_time(conn,
6025 fsp,
6026 fname,
6027 psbuf,
6029 true);
6032 /****************************************************************************
6033 Deal with SMB_SET_FILE_UNIX_INFO2.
6034 ****************************************************************************/
6036 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6037 struct smb_request *req,
6038 const char *pdata,
6039 int total_data,
6040 files_struct *fsp,
6041 const char *fname,
6042 SMB_STRUCT_STAT *psbuf)
6044 NTSTATUS status;
6045 uint32 smb_fflags;
6046 uint32 smb_fmask;
6048 if (total_data < 116) {
6049 return NT_STATUS_INVALID_PARAMETER;
6052 /* Start by setting all the fields that are common between UNIX_BASIC
6053 * and UNIX_INFO2.
6055 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6056 fsp, fname, psbuf);
6057 if (!NT_STATUS_IS_OK(status)) {
6058 return status;
6061 smb_fflags = IVAL(pdata, 108);
6062 smb_fmask = IVAL(pdata, 112);
6064 /* NB: We should only attempt to alter the file flags if the client
6065 * sends a non-zero mask.
6067 if (smb_fmask != 0) {
6068 int stat_fflags = 0;
6070 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6071 &stat_fflags)) {
6072 /* Client asked to alter a flag we don't understand. */
6073 return NT_STATUS_INVALID_PARAMETER;
6076 if (fsp && fsp->fh->fd != -1) {
6077 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6078 return NT_STATUS_NOT_SUPPORTED;
6079 } else {
6080 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6081 return map_nt_error_from_unix(errno);
6086 /* XXX: need to add support for changing the create_time here. You
6087 * can do this for paths on Darwin with setattrlist(2). The right way
6088 * to hook this up is probably by extending the VFS utimes interface.
6091 return NT_STATUS_OK;
6094 /****************************************************************************
6095 Create a directory with POSIX semantics.
6096 ****************************************************************************/
6098 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6099 struct smb_request *req,
6100 char **ppdata,
6101 int total_data,
6102 const char *fname,
6103 SMB_STRUCT_STAT *psbuf,
6104 int *pdata_return_size)
6106 NTSTATUS status = NT_STATUS_OK;
6107 uint32 raw_unixmode = 0;
6108 uint32 mod_unixmode = 0;
6109 mode_t unixmode = (mode_t)0;
6110 files_struct *fsp = NULL;
6111 uint16 info_level_return = 0;
6112 int info;
6113 char *pdata = *ppdata;
6115 if (total_data < 18) {
6116 return NT_STATUS_INVALID_PARAMETER;
6119 raw_unixmode = IVAL(pdata,8);
6120 /* Next 4 bytes are not yet defined. */
6122 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6123 if (!NT_STATUS_IS_OK(status)) {
6124 return status;
6127 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6129 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6130 fname, (unsigned int)unixmode ));
6132 status = open_directory(conn, req,
6133 fname,
6134 psbuf,
6135 FILE_READ_ATTRIBUTES, /* Just a stat open */
6136 FILE_SHARE_NONE, /* Ignored for stat opens */
6137 FILE_CREATE,
6139 mod_unixmode,
6140 &info,
6141 &fsp);
6143 if (NT_STATUS_IS_OK(status)) {
6144 close_file(fsp, NORMAL_CLOSE);
6147 info_level_return = SVAL(pdata,16);
6149 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6150 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6151 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6152 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6153 } else {
6154 *pdata_return_size = 12;
6157 /* Realloc the data size */
6158 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6159 if (*ppdata == NULL) {
6160 *pdata_return_size = 0;
6161 return NT_STATUS_NO_MEMORY;
6163 pdata = *ppdata;
6165 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6166 SSVAL(pdata,2,0); /* No fnum. */
6167 SIVAL(pdata,4,info); /* Was directory created. */
6169 switch (info_level_return) {
6170 case SMB_QUERY_FILE_UNIX_BASIC:
6171 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6172 SSVAL(pdata,10,0); /* Padding. */
6173 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6174 break;
6175 case SMB_QUERY_FILE_UNIX_INFO2:
6176 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6177 SSVAL(pdata,10,0); /* Padding. */
6178 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6179 break;
6180 default:
6181 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6182 SSVAL(pdata,10,0); /* Padding. */
6183 break;
6186 return status;
6189 /****************************************************************************
6190 Open/Create a file with POSIX semantics.
6191 ****************************************************************************/
6193 static NTSTATUS smb_posix_open(connection_struct *conn,
6194 struct smb_request *req,
6195 char **ppdata,
6196 int total_data,
6197 const char *fname,
6198 SMB_STRUCT_STAT *psbuf,
6199 int *pdata_return_size)
6201 bool extended_oplock_granted = False;
6202 char *pdata = *ppdata;
6203 uint32 flags = 0;
6204 uint32 wire_open_mode = 0;
6205 uint32 raw_unixmode = 0;
6206 uint32 mod_unixmode = 0;
6207 uint32 create_disp = 0;
6208 uint32 access_mask = 0;
6209 uint32 create_options = 0;
6210 NTSTATUS status = NT_STATUS_OK;
6211 mode_t unixmode = (mode_t)0;
6212 files_struct *fsp = NULL;
6213 int oplock_request = 0;
6214 int info = 0;
6215 uint16 info_level_return = 0;
6217 if (total_data < 18) {
6218 return NT_STATUS_INVALID_PARAMETER;
6221 flags = IVAL(pdata,0);
6222 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6223 if (oplock_request) {
6224 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6227 wire_open_mode = IVAL(pdata,4);
6229 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6230 return smb_posix_mkdir(conn, req,
6231 ppdata,
6232 total_data,
6233 fname,
6234 psbuf,
6235 pdata_return_size);
6238 switch (wire_open_mode & SMB_ACCMODE) {
6239 case SMB_O_RDONLY:
6240 access_mask = FILE_READ_DATA;
6241 break;
6242 case SMB_O_WRONLY:
6243 access_mask = FILE_WRITE_DATA;
6244 break;
6245 case SMB_O_RDWR:
6246 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6247 break;
6248 default:
6249 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6250 (unsigned int)wire_open_mode ));
6251 return NT_STATUS_INVALID_PARAMETER;
6254 wire_open_mode &= ~SMB_ACCMODE;
6256 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6257 create_disp = FILE_CREATE;
6258 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6259 create_disp = FILE_OVERWRITE_IF;
6260 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6261 create_disp = FILE_OPEN_IF;
6262 } else {
6263 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6264 (unsigned int)wire_open_mode ));
6265 return NT_STATUS_INVALID_PARAMETER;
6268 raw_unixmode = IVAL(pdata,8);
6269 /* Next 4 bytes are not yet defined. */
6271 status = unix_perms_from_wire(conn,
6272 psbuf,
6273 raw_unixmode,
6274 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6275 &unixmode);
6277 if (!NT_STATUS_IS_OK(status)) {
6278 return status;
6281 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6283 if (wire_open_mode & SMB_O_SYNC) {
6284 create_options |= FILE_WRITE_THROUGH;
6286 if (wire_open_mode & SMB_O_APPEND) {
6287 access_mask |= FILE_APPEND_DATA;
6289 if (wire_open_mode & SMB_O_DIRECT) {
6290 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6293 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6294 fname,
6295 (unsigned int)wire_open_mode,
6296 (unsigned int)unixmode ));
6298 status = open_file_ntcreate(conn, req,
6299 fname,
6300 psbuf,
6301 access_mask,
6302 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6303 create_disp,
6304 0, /* no create options yet. */
6305 mod_unixmode,
6306 oplock_request,
6307 &info,
6308 &fsp);
6310 if (!NT_STATUS_IS_OK(status)) {
6311 return status;
6314 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6315 extended_oplock_granted = True;
6318 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6319 extended_oplock_granted = True;
6322 info_level_return = SVAL(pdata,16);
6324 /* Allocate the correct return size. */
6326 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6327 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6328 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6329 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6330 } else {
6331 *pdata_return_size = 12;
6334 /* Realloc the data size */
6335 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6336 if (*ppdata == NULL) {
6337 close_file(fsp,ERROR_CLOSE);
6338 *pdata_return_size = 0;
6339 return NT_STATUS_NO_MEMORY;
6341 pdata = *ppdata;
6343 if (extended_oplock_granted) {
6344 if (flags & REQUEST_BATCH_OPLOCK) {
6345 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6346 } else {
6347 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6349 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6350 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6351 } else {
6352 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6355 SSVAL(pdata,2,fsp->fnum);
6356 SIVAL(pdata,4,info); /* Was file created etc. */
6358 switch (info_level_return) {
6359 case SMB_QUERY_FILE_UNIX_BASIC:
6360 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6361 SSVAL(pdata,10,0); /* padding. */
6362 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6363 break;
6364 case SMB_QUERY_FILE_UNIX_INFO2:
6365 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6366 SSVAL(pdata,10,0); /* padding. */
6367 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6368 break;
6369 default:
6370 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6371 SSVAL(pdata,10,0); /* padding. */
6372 break;
6374 return NT_STATUS_OK;
6377 /****************************************************************************
6378 Delete a file with POSIX semantics.
6379 ****************************************************************************/
6381 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6382 struct smb_request *req,
6383 const char *pdata,
6384 int total_data,
6385 const char *fname,
6386 SMB_STRUCT_STAT *psbuf)
6388 NTSTATUS status = NT_STATUS_OK;
6389 files_struct *fsp = NULL;
6390 uint16 flags = 0;
6391 char del = 1;
6392 int info = 0;
6393 int i;
6394 struct share_mode_lock *lck = NULL;
6396 if (total_data < 2) {
6397 return NT_STATUS_INVALID_PARAMETER;
6400 flags = SVAL(pdata,0);
6402 if (!VALID_STAT(*psbuf)) {
6403 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6406 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6407 !VALID_STAT_OF_DIR(*psbuf)) {
6408 return NT_STATUS_NOT_A_DIRECTORY;
6411 DEBUG(10,("smb_posix_unlink: %s %s\n",
6412 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6413 fname));
6415 if (VALID_STAT_OF_DIR(*psbuf)) {
6416 status = open_directory(conn, req,
6417 fname,
6418 psbuf,
6419 DELETE_ACCESS,
6420 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6421 FILE_OPEN,
6423 FILE_FLAG_POSIX_SEMANTICS|0777,
6424 &info,
6425 &fsp);
6426 } else {
6428 status = open_file_ntcreate(conn, req,
6429 fname,
6430 psbuf,
6431 DELETE_ACCESS,
6432 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6433 FILE_OPEN,
6435 FILE_FLAG_POSIX_SEMANTICS|0777,
6436 0, /* No oplock, but break existing ones. */
6437 &info,
6438 &fsp);
6441 if (!NT_STATUS_IS_OK(status)) {
6442 return status;
6446 * Don't lie to client. If we can't really delete due to
6447 * non-POSIX opens return SHARING_VIOLATION.
6450 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6451 NULL);
6452 if (lck == NULL) {
6453 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6454 "lock for file %s\n", fsp->fsp_name));
6455 close_file(fsp, NORMAL_CLOSE);
6456 return NT_STATUS_INVALID_PARAMETER;
6460 * See if others still have the file open. If this is the case, then
6461 * don't delete. If all opens are POSIX delete we can set the delete
6462 * on close disposition.
6464 for (i=0; i<lck->num_share_modes; i++) {
6465 struct share_mode_entry *e = &lck->share_modes[i];
6466 if (is_valid_share_mode_entry(e)) {
6467 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6468 continue;
6470 /* Fail with sharing violation. */
6471 close_file(fsp, NORMAL_CLOSE);
6472 TALLOC_FREE(lck);
6473 return NT_STATUS_SHARING_VIOLATION;
6478 * Set the delete on close.
6480 status = smb_set_file_disposition_info(conn,
6481 &del,
6483 fsp,
6484 fname,
6485 psbuf);
6487 if (!NT_STATUS_IS_OK(status)) {
6488 close_file(fsp, NORMAL_CLOSE);
6489 TALLOC_FREE(lck);
6490 return status;
6492 TALLOC_FREE(lck);
6493 return close_file(fsp, NORMAL_CLOSE);
6496 /****************************************************************************
6497 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6498 ****************************************************************************/
6500 static void call_trans2setfilepathinfo(connection_struct *conn,
6501 struct smb_request *req,
6502 unsigned int tran_call,
6503 char **pparams, int total_params,
6504 char **ppdata, int total_data,
6505 unsigned int max_data_bytes)
6507 char *params = *pparams;
6508 char *pdata = *ppdata;
6509 uint16 info_level;
6510 SMB_STRUCT_STAT sbuf;
6511 char *fname = NULL;
6512 files_struct *fsp = NULL;
6513 NTSTATUS status = NT_STATUS_OK;
6514 int data_return_size = 0;
6515 TALLOC_CTX *ctx = talloc_tos();
6517 if (!params) {
6518 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6519 return;
6522 ZERO_STRUCT(sbuf);
6524 if (tran_call == TRANSACT2_SETFILEINFO) {
6525 if (total_params < 4) {
6526 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6527 return;
6530 fsp = file_fsp(SVAL(params,0));
6531 /* Basic check for non-null fsp. */
6532 if (!check_fsp_open(conn, req, fsp, &current_user)) {
6533 return;
6535 info_level = SVAL(params,2);
6537 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6538 if (!fname) {
6539 reply_nterror(req, NT_STATUS_NO_MEMORY);
6540 return;
6543 if(fsp->is_directory || fsp->fh->fd == -1) {
6545 * This is actually a SETFILEINFO on a directory
6546 * handle (returned from an NT SMB). NT5.0 seems
6547 * to do this call. JRA.
6549 if (INFO_LEVEL_IS_UNIX(info_level)) {
6550 /* Always do lstat for UNIX calls. */
6551 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6552 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6553 reply_unixerror(req,ERRDOS,ERRbadpath);
6554 return;
6556 } else {
6557 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6558 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6559 reply_unixerror(req,ERRDOS,ERRbadpath);
6560 return;
6563 } else if (fsp->print_file) {
6565 * Doing a DELETE_ON_CLOSE should cancel a print job.
6567 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6568 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6570 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6572 SSVAL(params,0,0);
6573 send_trans2_replies(conn, req, params, 2,
6574 *ppdata, 0,
6575 max_data_bytes);
6576 return;
6577 } else {
6578 reply_unixerror(req, ERRDOS, ERRbadpath);
6579 return;
6581 } else {
6583 * Original code - this is an open file.
6585 if (!check_fsp(conn, req, fsp, &current_user)) {
6586 return;
6589 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6590 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6591 reply_unixerror(req, ERRDOS, ERRbadfid);
6592 return;
6595 } else {
6596 /* set path info */
6597 if (total_params < 7) {
6598 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6599 return;
6602 info_level = SVAL(params,0);
6603 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6604 total_params - 6, STR_TERMINATE,
6605 &status);
6606 if (!NT_STATUS_IS_OK(status)) {
6607 reply_nterror(req, status);
6608 return;
6611 status = resolve_dfspath(ctx, conn,
6612 req->flags2 & FLAGS2_DFS_PATHNAMES,
6613 fname,
6614 &fname);
6615 if (!NT_STATUS_IS_OK(status)) {
6616 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6617 reply_botherror(req,
6618 NT_STATUS_PATH_NOT_COVERED,
6619 ERRSRV, ERRbadpath);
6620 return;
6622 reply_nterror(req, status);
6623 return;
6626 status = unix_convert(ctx, conn, fname, False,
6627 &fname, NULL, &sbuf);
6628 if (!NT_STATUS_IS_OK(status)) {
6629 reply_nterror(req, status);
6630 return;
6633 status = check_name(conn, fname);
6634 if (!NT_STATUS_IS_OK(status)) {
6635 reply_nterror(req, status);
6636 return;
6639 if (INFO_LEVEL_IS_UNIX(info_level)) {
6641 * For CIFS UNIX extensions the target name may not exist.
6644 /* Always do lstat for UNIX calls. */
6645 SMB_VFS_LSTAT(conn,fname,&sbuf);
6647 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6648 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6649 reply_unixerror(req, ERRDOS, ERRbadpath);
6650 return;
6654 if (!CAN_WRITE(conn)) {
6655 reply_doserror(req, ERRSRV, ERRaccess);
6656 return;
6659 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6660 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6661 return;
6664 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6665 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6667 /* Realloc the parameter size */
6668 *pparams = (char *)SMB_REALLOC(*pparams,2);
6669 if (*pparams == NULL) {
6670 reply_nterror(req, NT_STATUS_NO_MEMORY);
6671 return;
6673 params = *pparams;
6675 SSVAL(params,0,0);
6677 switch (info_level) {
6679 case SMB_INFO_STANDARD:
6681 status = smb_set_info_standard(conn,
6682 pdata,
6683 total_data,
6684 fsp,
6685 fname,
6686 &sbuf);
6687 break;
6690 case SMB_INFO_SET_EA:
6692 status = smb_info_set_ea(conn,
6693 pdata,
6694 total_data,
6695 fsp,
6696 fname);
6697 break;
6700 case SMB_SET_FILE_BASIC_INFO:
6701 case SMB_FILE_BASIC_INFORMATION:
6703 status = smb_set_file_basic_info(conn,
6704 pdata,
6705 total_data,
6706 fsp,
6707 fname,
6708 &sbuf);
6709 break;
6712 case SMB_FILE_ALLOCATION_INFORMATION:
6713 case SMB_SET_FILE_ALLOCATION_INFO:
6715 status = smb_set_file_allocation_info(conn, req,
6716 pdata,
6717 total_data,
6718 fsp,
6719 fname,
6720 &sbuf);
6721 break;
6724 case SMB_FILE_END_OF_FILE_INFORMATION:
6725 case SMB_SET_FILE_END_OF_FILE_INFO:
6727 status = smb_set_file_end_of_file_info(conn, req,
6728 pdata,
6729 total_data,
6730 fsp,
6731 fname,
6732 &sbuf);
6733 break;
6736 case SMB_FILE_DISPOSITION_INFORMATION:
6737 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6739 #if 0
6740 /* JRA - We used to just ignore this on a path ?
6741 * Shouldn't this be invalid level on a pathname
6742 * based call ?
6744 if (tran_call != TRANSACT2_SETFILEINFO) {
6745 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6747 #endif
6748 status = smb_set_file_disposition_info(conn,
6749 pdata,
6750 total_data,
6751 fsp,
6752 fname,
6753 &sbuf);
6754 break;
6757 case SMB_FILE_POSITION_INFORMATION:
6759 status = smb_file_position_information(conn,
6760 pdata,
6761 total_data,
6762 fsp);
6763 break;
6766 /* From tridge Samba4 :
6767 * MODE_INFORMATION in setfileinfo (I have no
6768 * idea what "mode information" on a file is - it takes a value of 0,
6769 * 2, 4 or 6. What could it be?).
6772 case SMB_FILE_MODE_INFORMATION:
6774 status = smb_file_mode_information(conn,
6775 pdata,
6776 total_data);
6777 break;
6781 * CIFS UNIX extensions.
6784 case SMB_SET_FILE_UNIX_BASIC:
6786 status = smb_set_file_unix_basic(conn, req,
6787 pdata,
6788 total_data,
6789 fsp,
6790 fname,
6791 &sbuf);
6792 break;
6795 case SMB_SET_FILE_UNIX_INFO2:
6797 status = smb_set_file_unix_info2(conn, req,
6798 pdata,
6799 total_data,
6800 fsp,
6801 fname,
6802 &sbuf);
6803 break;
6806 case SMB_SET_FILE_UNIX_LINK:
6808 if (tran_call != TRANSACT2_SETPATHINFO) {
6809 /* We must have a pathname for this. */
6810 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6811 return;
6813 status = smb_set_file_unix_link(conn, req, pdata,
6814 total_data, fname);
6815 break;
6818 case SMB_SET_FILE_UNIX_HLINK:
6820 if (tran_call != TRANSACT2_SETPATHINFO) {
6821 /* We must have a pathname for this. */
6822 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6823 return;
6825 status = smb_set_file_unix_hlink(conn, req,
6826 pdata, total_data,
6827 fname);
6828 break;
6831 case SMB_FILE_RENAME_INFORMATION:
6833 status = smb_file_rename_information(conn, req,
6834 pdata, total_data,
6835 fsp, fname);
6836 break;
6839 #if defined(HAVE_POSIX_ACLS)
6840 case SMB_SET_POSIX_ACL:
6842 status = smb_set_posix_acl(conn,
6843 pdata,
6844 total_data,
6845 fsp,
6846 fname,
6847 &sbuf);
6848 break;
6850 #endif
6852 case SMB_SET_POSIX_LOCK:
6854 if (tran_call != TRANSACT2_SETFILEINFO) {
6855 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6856 return;
6858 status = smb_set_posix_lock(conn, req,
6859 pdata, total_data, fsp);
6860 break;
6863 case SMB_POSIX_PATH_OPEN:
6865 if (tran_call != TRANSACT2_SETPATHINFO) {
6866 /* We must have a pathname for this. */
6867 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6868 return;
6871 status = smb_posix_open(conn, req,
6872 ppdata,
6873 total_data,
6874 fname,
6875 &sbuf,
6876 &data_return_size);
6877 break;
6880 case SMB_POSIX_PATH_UNLINK:
6882 if (tran_call != TRANSACT2_SETPATHINFO) {
6883 /* We must have a pathname for this. */
6884 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6885 return;
6888 status = smb_posix_unlink(conn, req,
6889 pdata,
6890 total_data,
6891 fname,
6892 &sbuf);
6893 break;
6896 default:
6897 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6898 return;
6902 if (!NT_STATUS_IS_OK(status)) {
6903 if (open_was_deferred(req->mid)) {
6904 /* We have re-scheduled this call. */
6905 return;
6907 if (blocking_lock_was_deferred(req->mid)) {
6908 /* We have re-scheduled this call. */
6909 return;
6911 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6912 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6913 ERRSRV, ERRbadpath);
6914 return;
6916 if (info_level == SMB_POSIX_PATH_OPEN) {
6917 reply_openerror(req, status);
6918 return;
6921 reply_nterror(req, status);
6922 return;
6925 SSVAL(params,0,0);
6926 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
6927 max_data_bytes);
6929 return;
6932 /****************************************************************************
6933 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6934 ****************************************************************************/
6936 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6937 char **pparams, int total_params,
6938 char **ppdata, int total_data,
6939 unsigned int max_data_bytes)
6941 char *params = *pparams;
6942 char *pdata = *ppdata;
6943 char *directory = NULL;
6944 SMB_STRUCT_STAT sbuf;
6945 NTSTATUS status = NT_STATUS_OK;
6946 struct ea_list *ea_list = NULL;
6947 TALLOC_CTX *ctx = talloc_tos();
6949 if (!CAN_WRITE(conn)) {
6950 reply_doserror(req, ERRSRV, ERRaccess);
6951 return;
6954 if (total_params < 5) {
6955 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6956 return;
6959 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
6960 total_params - 4, STR_TERMINATE,
6961 &status);
6962 if (!NT_STATUS_IS_OK(status)) {
6963 reply_nterror(req, status);
6964 return;
6967 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6969 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6970 if (!NT_STATUS_IS_OK(status)) {
6971 reply_nterror(req, status);
6972 return;
6975 status = check_name(conn, directory);
6976 if (!NT_STATUS_IS_OK(status)) {
6977 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6978 reply_nterror(req, status);
6979 return;
6982 /* Any data in this call is an EA list. */
6983 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6984 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6985 return;
6989 * OS/2 workplace shell seems to send SET_EA requests of "null"
6990 * length (4 bytes containing IVAL 4).
6991 * They seem to have no effect. Bug #3212. JRA.
6994 if (total_data != 4) {
6995 if (total_data < 10) {
6996 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6997 return;
7000 if (IVAL(pdata,0) > total_data) {
7001 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7002 IVAL(pdata,0), (unsigned int)total_data));
7003 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7004 return;
7007 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7008 total_data - 4);
7009 if (!ea_list) {
7010 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7011 return;
7013 } else if (IVAL(pdata,0) != 4) {
7014 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7015 return;
7018 status = create_directory(conn, req, directory);
7020 if (!NT_STATUS_IS_OK(status)) {
7021 reply_nterror(req, status);
7022 return;
7025 /* Try and set any given EA. */
7026 if (ea_list) {
7027 status = set_ea(conn, NULL, directory, ea_list);
7028 if (!NT_STATUS_IS_OK(status)) {
7029 reply_nterror(req, status);
7030 return;
7034 /* Realloc the parameter and data sizes */
7035 *pparams = (char *)SMB_REALLOC(*pparams,2);
7036 if(*pparams == NULL) {
7037 reply_nterror(req, NT_STATUS_NO_MEMORY);
7038 return;
7040 params = *pparams;
7042 SSVAL(params,0,0);
7044 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7046 return;
7049 /****************************************************************************
7050 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7051 We don't actually do this - we just send a null response.
7052 ****************************************************************************/
7054 static void call_trans2findnotifyfirst(connection_struct *conn,
7055 struct smb_request *req,
7056 char **pparams, int total_params,
7057 char **ppdata, int total_data,
7058 unsigned int max_data_bytes)
7060 static uint16 fnf_handle = 257;
7061 char *params = *pparams;
7062 uint16 info_level;
7064 if (total_params < 6) {
7065 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7066 return;
7069 info_level = SVAL(params,4);
7070 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7072 switch (info_level) {
7073 case 1:
7074 case 2:
7075 break;
7076 default:
7077 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7078 return;
7081 /* Realloc the parameter and data sizes */
7082 *pparams = (char *)SMB_REALLOC(*pparams,6);
7083 if (*pparams == NULL) {
7084 reply_nterror(req, NT_STATUS_NO_MEMORY);
7085 return;
7087 params = *pparams;
7089 SSVAL(params,0,fnf_handle);
7090 SSVAL(params,2,0); /* No changes */
7091 SSVAL(params,4,0); /* No EA errors */
7093 fnf_handle++;
7095 if(fnf_handle == 0)
7096 fnf_handle = 257;
7098 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7100 return;
7103 /****************************************************************************
7104 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7105 changes). Currently this does nothing.
7106 ****************************************************************************/
7108 static void call_trans2findnotifynext(connection_struct *conn,
7109 struct smb_request *req,
7110 char **pparams, int total_params,
7111 char **ppdata, int total_data,
7112 unsigned int max_data_bytes)
7114 char *params = *pparams;
7116 DEBUG(3,("call_trans2findnotifynext\n"));
7118 /* Realloc the parameter and data sizes */
7119 *pparams = (char *)SMB_REALLOC(*pparams,4);
7120 if (*pparams == NULL) {
7121 reply_nterror(req, NT_STATUS_NO_MEMORY);
7122 return;
7124 params = *pparams;
7126 SSVAL(params,0,0); /* No changes */
7127 SSVAL(params,2,0); /* No EA errors */
7129 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7131 return;
7134 /****************************************************************************
7135 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7136 ****************************************************************************/
7138 static void call_trans2getdfsreferral(connection_struct *conn,
7139 struct smb_request *req,
7140 char **pparams, int total_params,
7141 char **ppdata, int total_data,
7142 unsigned int max_data_bytes)
7144 char *params = *pparams;
7145 char *pathname = NULL;
7146 int reply_size = 0;
7147 int max_referral_level;
7148 NTSTATUS status = NT_STATUS_OK;
7149 TALLOC_CTX *ctx = talloc_tos();
7151 DEBUG(10,("call_trans2getdfsreferral\n"));
7153 if (total_params < 3) {
7154 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7155 return;
7158 max_referral_level = SVAL(params,0);
7160 if(!lp_host_msdfs()) {
7161 reply_doserror(req, ERRDOS, ERRbadfunc);
7162 return;
7165 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7166 total_params - 2, STR_TERMINATE);
7167 if (!pathname) {
7168 reply_nterror(req, NT_STATUS_NOT_FOUND);
7169 return;
7171 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7172 ppdata,&status)) < 0) {
7173 reply_nterror(req, status);
7174 return;
7177 SSVAL(req->inbuf, smb_flg2,
7178 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7179 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7181 return;
7184 #define LMCAT_SPL 0x53
7185 #define LMFUNC_GETJOBID 0x60
7187 /****************************************************************************
7188 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7189 ****************************************************************************/
7191 static void call_trans2ioctl(connection_struct *conn,
7192 struct smb_request *req,
7193 char **pparams, int total_params,
7194 char **ppdata, int total_data,
7195 unsigned int max_data_bytes)
7197 char *pdata = *ppdata;
7198 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7200 /* check for an invalid fid before proceeding */
7202 if (!fsp) {
7203 reply_doserror(req, ERRDOS, ERRbadfid);
7204 return;
7207 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7208 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7209 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7210 if (*ppdata == NULL) {
7211 reply_nterror(req, NT_STATUS_NO_MEMORY);
7212 return;
7214 pdata = *ppdata;
7216 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7217 CAN ACCEPT THIS IN UNICODE. JRA. */
7219 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7220 srvstr_push(pdata, req->flags2, pdata + 2,
7221 global_myname(), 15,
7222 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7223 srvstr_push(pdata, req->flags2, pdata+18,
7224 lp_servicename(SNUM(conn)), 13,
7225 STR_ASCII|STR_TERMINATE); /* Service name */
7226 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7227 max_data_bytes);
7228 return;
7231 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7232 reply_doserror(req, ERRSRV, ERRerror);
7235 /****************************************************************************
7236 Reply to a SMBfindclose (stop trans2 directory search).
7237 ****************************************************************************/
7239 void reply_findclose(struct smb_request *req)
7241 int dptr_num;
7243 START_PROFILE(SMBfindclose);
7245 if (req->wct < 1) {
7246 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7247 END_PROFILE(SMBfindclose);
7248 return;
7251 dptr_num = SVALS(req->inbuf,smb_vwv0);
7253 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7255 dptr_close(&dptr_num);
7257 reply_outbuf(req, 0, 0);
7259 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7261 END_PROFILE(SMBfindclose);
7262 return;
7265 /****************************************************************************
7266 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7267 ****************************************************************************/
7269 void reply_findnclose(struct smb_request *req)
7271 int dptr_num;
7273 START_PROFILE(SMBfindnclose);
7275 if (req->wct < 1) {
7276 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7277 END_PROFILE(SMBfindnclose);
7278 return;
7281 dptr_num = SVAL(req->inbuf,smb_vwv0);
7283 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7285 /* We never give out valid handles for a
7286 findnotifyfirst - so any dptr_num is ok here.
7287 Just ignore it. */
7289 reply_outbuf(req, 0, 0);
7291 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7293 END_PROFILE(SMBfindnclose);
7294 return;
7297 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7298 struct trans_state *state)
7300 if (Protocol >= PROTOCOL_NT1) {
7301 req->flags2 |= 0x40; /* IS_LONG_NAME */
7302 SSVAL(req->inbuf,smb_flg2,req->flags2);
7305 if (conn->encrypt_level == Required && !req->encrypted) {
7306 if (state->call != TRANSACT2_QFSINFO &&
7307 state->call != TRANSACT2_SETFSINFO) {
7308 DEBUG(0,("handle_trans2: encryption required "
7309 "with call 0x%x\n",
7310 (unsigned int)state->call));
7311 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7312 return;
7316 /* Now we must call the relevant TRANS2 function */
7317 switch(state->call) {
7318 case TRANSACT2_OPEN:
7320 START_PROFILE(Trans2_open);
7321 call_trans2open(conn, req,
7322 &state->param, state->total_param,
7323 &state->data, state->total_data,
7324 state->max_data_return);
7325 END_PROFILE(Trans2_open);
7326 break;
7329 case TRANSACT2_FINDFIRST:
7331 START_PROFILE(Trans2_findfirst);
7332 call_trans2findfirst(conn, req,
7333 &state->param, state->total_param,
7334 &state->data, state->total_data,
7335 state->max_data_return);
7336 END_PROFILE(Trans2_findfirst);
7337 break;
7340 case TRANSACT2_FINDNEXT:
7342 START_PROFILE(Trans2_findnext);
7343 call_trans2findnext(conn, req,
7344 &state->param, state->total_param,
7345 &state->data, state->total_data,
7346 state->max_data_return);
7347 END_PROFILE(Trans2_findnext);
7348 break;
7351 case TRANSACT2_QFSINFO:
7353 START_PROFILE(Trans2_qfsinfo);
7354 call_trans2qfsinfo(conn, req,
7355 &state->param, state->total_param,
7356 &state->data, state->total_data,
7357 state->max_data_return);
7358 END_PROFILE(Trans2_qfsinfo);
7359 break;
7362 case TRANSACT2_SETFSINFO:
7364 START_PROFILE(Trans2_setfsinfo);
7365 call_trans2setfsinfo(conn, req,
7366 &state->param, state->total_param,
7367 &state->data, state->total_data,
7368 state->max_data_return);
7369 END_PROFILE(Trans2_setfsinfo);
7370 break;
7373 case TRANSACT2_QPATHINFO:
7374 case TRANSACT2_QFILEINFO:
7376 START_PROFILE(Trans2_qpathinfo);
7377 call_trans2qfilepathinfo(conn, req, state->call,
7378 &state->param, state->total_param,
7379 &state->data, state->total_data,
7380 state->max_data_return);
7381 END_PROFILE(Trans2_qpathinfo);
7382 break;
7385 case TRANSACT2_SETPATHINFO:
7386 case TRANSACT2_SETFILEINFO:
7388 START_PROFILE(Trans2_setpathinfo);
7389 call_trans2setfilepathinfo(conn, req, state->call,
7390 &state->param, state->total_param,
7391 &state->data, state->total_data,
7392 state->max_data_return);
7393 END_PROFILE(Trans2_setpathinfo);
7394 break;
7397 case TRANSACT2_FINDNOTIFYFIRST:
7399 START_PROFILE(Trans2_findnotifyfirst);
7400 call_trans2findnotifyfirst(conn, req,
7401 &state->param, state->total_param,
7402 &state->data, state->total_data,
7403 state->max_data_return);
7404 END_PROFILE(Trans2_findnotifyfirst);
7405 break;
7408 case TRANSACT2_FINDNOTIFYNEXT:
7410 START_PROFILE(Trans2_findnotifynext);
7411 call_trans2findnotifynext(conn, req,
7412 &state->param, state->total_param,
7413 &state->data, state->total_data,
7414 state->max_data_return);
7415 END_PROFILE(Trans2_findnotifynext);
7416 break;
7419 case TRANSACT2_MKDIR:
7421 START_PROFILE(Trans2_mkdir);
7422 call_trans2mkdir(conn, req,
7423 &state->param, state->total_param,
7424 &state->data, state->total_data,
7425 state->max_data_return);
7426 END_PROFILE(Trans2_mkdir);
7427 break;
7430 case TRANSACT2_GET_DFS_REFERRAL:
7432 START_PROFILE(Trans2_get_dfs_referral);
7433 call_trans2getdfsreferral(conn, req,
7434 &state->param, state->total_param,
7435 &state->data, state->total_data,
7436 state->max_data_return);
7437 END_PROFILE(Trans2_get_dfs_referral);
7438 break;
7441 case TRANSACT2_IOCTL:
7443 START_PROFILE(Trans2_ioctl);
7444 call_trans2ioctl(conn, req,
7445 &state->param, state->total_param,
7446 &state->data, state->total_data,
7447 state->max_data_return);
7448 END_PROFILE(Trans2_ioctl);
7449 break;
7452 default:
7453 /* Error in request */
7454 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7455 reply_doserror(req, ERRSRV,ERRerror);
7459 /****************************************************************************
7460 Reply to a SMBtrans2.
7461 ****************************************************************************/
7463 void reply_trans2(struct smb_request *req)
7465 connection_struct *conn = req->conn;
7466 unsigned int dsoff;
7467 unsigned int dscnt;
7468 unsigned int psoff;
7469 unsigned int pscnt;
7470 unsigned int tran_call;
7471 unsigned int size;
7472 unsigned int av_size;
7473 struct trans_state *state;
7474 NTSTATUS result;
7476 START_PROFILE(SMBtrans2);
7478 if (req->wct < 14) {
7479 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7480 END_PROFILE(SMBtrans2);
7481 return;
7484 dsoff = SVAL(req->inbuf, smb_dsoff);
7485 dscnt = SVAL(req->inbuf, smb_dscnt);
7486 psoff = SVAL(req->inbuf, smb_psoff);
7487 pscnt = SVAL(req->inbuf, smb_pscnt);
7488 tran_call = SVAL(req->inbuf, smb_setup0);
7489 size = smb_len(req->inbuf) + 4;
7490 av_size = smb_len(req->inbuf);
7492 result = allow_new_trans(conn->pending_trans, req->mid);
7493 if (!NT_STATUS_IS_OK(result)) {
7494 DEBUG(2, ("Got invalid trans2 request: %s\n",
7495 nt_errstr(result)));
7496 reply_nterror(req, result);
7497 END_PROFILE(SMBtrans2);
7498 return;
7501 if (IS_IPC(conn)) {
7502 switch (tran_call) {
7503 /* List the allowed trans2 calls on IPC$ */
7504 case TRANSACT2_OPEN:
7505 case TRANSACT2_GET_DFS_REFERRAL:
7506 case TRANSACT2_QFILEINFO:
7507 case TRANSACT2_QFSINFO:
7508 case TRANSACT2_SETFSINFO:
7509 break;
7510 default:
7511 reply_doserror(req, ERRSRV, ERRaccess);
7512 END_PROFILE(SMBtrans2);
7513 return;
7517 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7518 DEBUG(0, ("talloc failed\n"));
7519 reply_nterror(req, NT_STATUS_NO_MEMORY);
7520 END_PROFILE(SMBtrans2);
7521 return;
7524 state->cmd = SMBtrans2;
7526 state->mid = req->mid;
7527 state->vuid = req->vuid;
7528 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7529 state->setup = NULL;
7530 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7531 state->param = NULL;
7532 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7533 state->data = NULL;
7534 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7535 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7536 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7537 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7538 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7540 state->call = tran_call;
7542 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7543 is so as a sanity check */
7544 if (state->setup_count != 1) {
7546 * Need to have rc=0 for ioctl to get job id for OS/2.
7547 * Network printing will fail if function is not successful.
7548 * Similar function in reply.c will be used if protocol
7549 * is LANMAN1.0 instead of LM1.2X002.
7550 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7551 * outbuf doesn't have to be set(only job id is used).
7553 if ( (state->setup_count == 4)
7554 && (tran_call == TRANSACT2_IOCTL)
7555 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7556 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7557 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7558 } else {
7559 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7560 DEBUG(2,("Transaction is %d\n",tran_call));
7561 TALLOC_FREE(state);
7562 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7563 END_PROFILE(SMBtrans2);
7564 return;
7568 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7569 goto bad_param;
7571 if (state->total_data) {
7572 /* Can't use talloc here, the core routines do realloc on the
7573 * params and data. */
7574 state->data = (char *)SMB_MALLOC(state->total_data);
7575 if (state->data == NULL) {
7576 DEBUG(0,("reply_trans2: data malloc fail for %u "
7577 "bytes !\n", (unsigned int)state->total_data));
7578 TALLOC_FREE(state);
7579 reply_nterror(req, NT_STATUS_NO_MEMORY);
7580 END_PROFILE(SMBtrans2);
7581 return;
7584 if (dscnt > state->total_data ||
7585 dsoff+dscnt < dsoff) {
7586 goto bad_param;
7589 if (dsoff > av_size ||
7590 dscnt > av_size ||
7591 dsoff+dscnt > av_size) {
7592 goto bad_param;
7595 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7598 if (state->total_param) {
7599 /* Can't use talloc here, the core routines do realloc on the
7600 * params and data. */
7601 state->param = (char *)SMB_MALLOC(state->total_param);
7602 if (state->param == NULL) {
7603 DEBUG(0,("reply_trans: param malloc fail for %u "
7604 "bytes !\n", (unsigned int)state->total_param));
7605 SAFE_FREE(state->data);
7606 TALLOC_FREE(state);
7607 reply_nterror(req, NT_STATUS_NO_MEMORY);
7608 END_PROFILE(SMBtrans2);
7609 return;
7612 if (pscnt > state->total_param ||
7613 psoff+pscnt < psoff) {
7614 goto bad_param;
7617 if (psoff > av_size ||
7618 pscnt > av_size ||
7619 psoff+pscnt > av_size) {
7620 goto bad_param;
7623 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7626 state->received_data = dscnt;
7627 state->received_param = pscnt;
7629 if ((state->received_param == state->total_param) &&
7630 (state->received_data == state->total_data)) {
7632 handle_trans2(conn, req, state);
7634 SAFE_FREE(state->data);
7635 SAFE_FREE(state->param);
7636 TALLOC_FREE(state);
7637 END_PROFILE(SMBtrans2);
7638 return;
7641 DLIST_ADD(conn->pending_trans, state);
7643 /* We need to send an interim response then receive the rest
7644 of the parameter/data bytes */
7645 reply_outbuf(req, 0, 0);
7646 show_msg((char *)req->outbuf);
7647 END_PROFILE(SMBtrans2);
7648 return;
7650 bad_param:
7652 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7653 SAFE_FREE(state->data);
7654 SAFE_FREE(state->param);
7655 TALLOC_FREE(state);
7656 END_PROFILE(SMBtrans2);
7657 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7661 /****************************************************************************
7662 Reply to a SMBtranss2
7663 ****************************************************************************/
7665 void reply_transs2(struct smb_request *req)
7667 connection_struct *conn = req->conn;
7668 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7669 struct trans_state *state;
7670 unsigned int size;
7671 unsigned int av_size;
7673 START_PROFILE(SMBtranss2);
7675 show_msg((char *)req->inbuf);
7677 if (req->wct < 8) {
7678 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7679 END_PROFILE(SMBtranss2);
7680 return;
7683 size = smb_len(req->inbuf)+4;
7684 av_size = smb_len(req->inbuf);
7686 for (state = conn->pending_trans; state != NULL;
7687 state = state->next) {
7688 if (state->mid == req->mid) {
7689 break;
7693 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7694 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7695 END_PROFILE(SMBtranss2);
7696 return;
7699 /* Revise state->total_param and state->total_data in case they have
7700 changed downwards */
7702 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7703 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7704 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7705 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7707 pcnt = SVAL(req->inbuf, smb_spscnt);
7708 poff = SVAL(req->inbuf, smb_spsoff);
7709 pdisp = SVAL(req->inbuf, smb_spsdisp);
7711 dcnt = SVAL(req->inbuf, smb_sdscnt);
7712 doff = SVAL(req->inbuf, smb_sdsoff);
7713 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7715 state->received_param += pcnt;
7716 state->received_data += dcnt;
7718 if ((state->received_data > state->total_data) ||
7719 (state->received_param > state->total_param))
7720 goto bad_param;
7722 if (pcnt) {
7723 if (pdisp > state->total_param ||
7724 pcnt > state->total_param ||
7725 pdisp+pcnt > state->total_param ||
7726 pdisp+pcnt < pdisp) {
7727 goto bad_param;
7730 if (poff > av_size ||
7731 pcnt > av_size ||
7732 poff+pcnt > av_size ||
7733 poff+pcnt < poff) {
7734 goto bad_param;
7737 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7738 pcnt);
7741 if (dcnt) {
7742 if (ddisp > state->total_data ||
7743 dcnt > state->total_data ||
7744 ddisp+dcnt > state->total_data ||
7745 ddisp+dcnt < ddisp) {
7746 goto bad_param;
7749 if (ddisp > av_size ||
7750 dcnt > av_size ||
7751 ddisp+dcnt > av_size ||
7752 ddisp+dcnt < ddisp) {
7753 goto bad_param;
7756 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7757 dcnt);
7760 if ((state->received_param < state->total_param) ||
7761 (state->received_data < state->total_data)) {
7762 END_PROFILE(SMBtranss2);
7763 return;
7767 * construct_reply_common will copy smb_com from inbuf to
7768 * outbuf. SMBtranss2 is wrong here.
7770 SCVAL(req->inbuf,smb_com,SMBtrans2);
7772 handle_trans2(conn, req, state);
7774 DLIST_REMOVE(conn->pending_trans, state);
7775 SAFE_FREE(state->data);
7776 SAFE_FREE(state->param);
7777 TALLOC_FREE(state);
7779 END_PROFILE(SMBtranss2);
7780 return;
7782 bad_param:
7784 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7785 DLIST_REMOVE(conn->pending_trans, state);
7786 SAFE_FREE(state->data);
7787 SAFE_FREE(state->param);
7788 TALLOC_FREE(state);
7789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7790 END_PROFILE(SMBtranss2);
7791 return;