Cleanup size_t return values in callers of convert_string_allocate
[Samba/bb.git] / source3 / smbd / trans2.c
blob72688bbd66b5db913bbe60dee0b5802c6bcdb77a
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 = -1;
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 converted_size, 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 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
526 &converted_size)) {
527 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
528 "failed: %s", strerror(errno)));
530 if (!eal->ea.name) {
531 return NULL;
534 offset += (namelen + 1); /* Go past the name + terminating zero. */
535 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
536 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
539 return ea_list_head;
542 /****************************************************************************
543 Read one EA list entry from the buffer.
544 ****************************************************************************/
546 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
548 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
549 uint16 val_len;
550 unsigned int namelen;
551 size_t converted_size;
553 if (!eal) {
554 return NULL;
557 if (data_size < 6) {
558 return NULL;
561 eal->ea.flags = CVAL(pdata,0);
562 namelen = CVAL(pdata,1);
563 val_len = SVAL(pdata,2);
565 if (4 + namelen + 1 + val_len > data_size) {
566 return NULL;
569 /* Ensure the name is null terminated. */
570 if (pdata[namelen + 4] != '\0') {
571 return NULL;
573 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
574 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
575 strerror(errno)));
577 if (!eal->ea.name) {
578 return NULL;
581 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
582 if (!eal->ea.value.data) {
583 return NULL;
586 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
588 /* Ensure we're null terminated just in case we print the value. */
589 eal->ea.value.data[val_len] = '\0';
590 /* But don't count the null. */
591 eal->ea.value.length--;
593 if (pbytes_used) {
594 *pbytes_used = 4 + namelen + 1 + val_len;
597 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
598 dump_data(10, eal->ea.value.data, eal->ea.value.length);
600 return eal;
603 /****************************************************************************
604 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
605 ****************************************************************************/
607 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
609 struct ea_list *ea_list_head = NULL;
610 size_t offset = 0;
611 size_t bytes_used = 0;
613 while (offset < data_size) {
614 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
616 if (!eal) {
617 return NULL;
620 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
621 offset += bytes_used;
624 return ea_list_head;
627 /****************************************************************************
628 Count the total EA size needed.
629 ****************************************************************************/
631 static size_t ea_list_size(struct ea_list *ealist)
633 fstring dos_ea_name;
634 struct ea_list *listp;
635 size_t ret = 0;
637 for (listp = ealist; listp; listp = listp->next) {
638 push_ascii_fstring(dos_ea_name, listp->ea.name);
639 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
641 /* Add on 4 for total length. */
642 if (ret) {
643 ret += 4;
646 return ret;
649 /****************************************************************************
650 Return a union of EA's from a file list and a list of names.
651 The TALLOC context for the two lists *MUST* be identical as we steal
652 memory from one list to add to another. JRA.
653 ****************************************************************************/
655 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
657 struct ea_list *nlistp, *flistp;
659 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
660 for (flistp = file_list; flistp; flistp = flistp->next) {
661 if (strequal(nlistp->ea.name, flistp->ea.name)) {
662 break;
666 if (flistp) {
667 /* Copy the data from this entry. */
668 nlistp->ea.flags = flistp->ea.flags;
669 nlistp->ea.value = flistp->ea.value;
670 } else {
671 /* Null entry. */
672 nlistp->ea.flags = 0;
673 ZERO_STRUCT(nlistp->ea.value);
677 *total_ea_len = ea_list_size(name_list);
678 return name_list;
681 /****************************************************************************
682 Send the required number of replies back.
683 We assume all fields other than the data fields are
684 set correctly for the type of call.
685 HACK ! Always assumes smb_setup field is zero.
686 ****************************************************************************/
688 void send_trans2_replies(connection_struct *conn,
689 struct smb_request *req,
690 const char *params,
691 int paramsize,
692 const char *pdata,
693 int datasize,
694 int max_data_bytes)
696 /* As we are using a protocol > LANMAN1 then the max_send
697 variable must have been set in the sessetupX call.
698 This takes precedence over the max_xmit field in the
699 global struct. These different max_xmit variables should
700 be merged as this is now too confusing */
702 int data_to_send = datasize;
703 int params_to_send = paramsize;
704 int useable_space;
705 const char *pp = params;
706 const char *pd = pdata;
707 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
708 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
709 int data_alignment_offset = 0;
710 bool overflow = False;
712 /* Modify the data_to_send and datasize and set the error if
713 we're trying to send more than max_data_bytes. We still send
714 the part of the packet(s) that fit. Strange, but needed
715 for OS/2. */
717 if (max_data_bytes > 0 && datasize > max_data_bytes) {
718 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
719 max_data_bytes, datasize ));
720 datasize = data_to_send = max_data_bytes;
721 overflow = True;
724 /* If there genuinely are no parameters or data to send just send the empty packet */
726 if(params_to_send == 0 && data_to_send == 0) {
727 reply_outbuf(req, 10, 0);
728 show_msg((char *)req->outbuf);
729 return;
732 /* When sending params and data ensure that both are nicely aligned */
733 /* Only do this alignment when there is also data to send - else
734 can cause NT redirector problems. */
736 if (((params_to_send % 4) != 0) && (data_to_send != 0))
737 data_alignment_offset = 4 - (params_to_send % 4);
739 /* Space is bufsize minus Netbios over TCP header minus SMB header */
740 /* The alignment_offset is to align the param bytes on an even byte
741 boundary. NT 4.0 Beta needs this to work correctly. */
743 useable_space = max_send - (smb_size
744 + 2 * 10 /* wct */
745 + alignment_offset
746 + data_alignment_offset);
748 /* useable_space can never be more than max_send minus the alignment offset. */
750 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
752 while (params_to_send || data_to_send) {
753 /* Calculate whether we will totally or partially fill this packet */
755 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
757 /* We can never send more than useable_space */
759 * Note that 'useable_space' does not include the alignment offsets,
760 * but we must include the alignment offsets in the calculation of
761 * the length of the data we send over the wire, as the alignment offsets
762 * are sent here. Fix from Marc_Jacobsen@hp.com.
765 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
767 reply_outbuf(req, 10, total_sent_thistime);
769 /* Set total params and data to be sent */
770 SSVAL(req->outbuf,smb_tprcnt,paramsize);
771 SSVAL(req->outbuf,smb_tdrcnt,datasize);
773 /* Calculate how many parameters and data we can fit into
774 * this packet. Parameters get precedence
777 params_sent_thistime = MIN(params_to_send,useable_space);
778 data_sent_thistime = useable_space - params_sent_thistime;
779 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
781 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
783 /* smb_proff is the offset from the start of the SMB header to the
784 parameter bytes, however the first 4 bytes of outbuf are
785 the Netbios over TCP header. Thus use smb_base() to subtract
786 them from the calculation */
788 SSVAL(req->outbuf,smb_proff,
789 ((smb_buf(req->outbuf)+alignment_offset)
790 - smb_base(req->outbuf)));
792 if(params_sent_thistime == 0)
793 SSVAL(req->outbuf,smb_prdisp,0);
794 else
795 /* Absolute displacement of param bytes sent in this packet */
796 SSVAL(req->outbuf,smb_prdisp,pp - params);
798 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
799 if(data_sent_thistime == 0) {
800 SSVAL(req->outbuf,smb_droff,0);
801 SSVAL(req->outbuf,smb_drdisp, 0);
802 } else {
803 /* The offset of the data bytes is the offset of the
804 parameter bytes plus the number of parameters being sent this time */
805 SSVAL(req->outbuf, smb_droff,
806 ((smb_buf(req->outbuf)+alignment_offset)
807 - smb_base(req->outbuf))
808 + params_sent_thistime + data_alignment_offset);
809 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
812 /* Initialize the padding for alignment */
814 if (alignment_offset != 0) {
815 memset(smb_buf(req->outbuf), 0, alignment_offset);
818 /* Copy the param bytes into the packet */
820 if(params_sent_thistime) {
821 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
822 params_sent_thistime);
825 /* Copy in the data bytes */
826 if(data_sent_thistime) {
827 if (data_alignment_offset != 0) {
828 memset((smb_buf(req->outbuf)+alignment_offset+
829 params_sent_thistime), 0,
830 data_alignment_offset);
832 memcpy(smb_buf(req->outbuf)+alignment_offset
833 +params_sent_thistime+data_alignment_offset,
834 pd,data_sent_thistime);
837 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
838 params_sent_thistime, data_sent_thistime, useable_space));
839 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
840 params_to_send, data_to_send, paramsize, datasize));
842 if (overflow) {
843 error_packet_set((char *)req->outbuf,
844 ERRDOS,ERRbufferoverflow,
845 STATUS_BUFFER_OVERFLOW,
846 __LINE__,__FILE__);
849 /* Send the packet */
850 show_msg((char *)req->outbuf);
851 if (!srv_send_smb(smbd_server_fd(),
852 (char *)req->outbuf,
853 IS_CONN_ENCRYPTED(conn)))
854 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
856 TALLOC_FREE(req->outbuf);
858 pp += params_sent_thistime;
859 pd += data_sent_thistime;
861 params_to_send -= params_sent_thistime;
862 data_to_send -= data_sent_thistime;
864 /* Sanity check */
865 if(params_to_send < 0 || data_to_send < 0) {
866 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
867 params_to_send, data_to_send));
868 return;
872 return;
875 /****************************************************************************
876 Reply to a TRANSACT2_OPEN.
877 ****************************************************************************/
879 static void call_trans2open(connection_struct *conn,
880 struct smb_request *req,
881 char **pparams, int total_params,
882 char **ppdata, int total_data,
883 unsigned int max_data_bytes)
885 char *params = *pparams;
886 char *pdata = *ppdata;
887 int deny_mode;
888 int32 open_attr;
889 bool oplock_request;
890 #if 0
891 bool return_additional_info;
892 int16 open_sattr;
893 time_t open_time;
894 #endif
895 int open_ofun;
896 uint32 open_size;
897 char *pname;
898 char *fname = NULL;
899 SMB_OFF_T size=0;
900 int fattr=0,mtime=0;
901 SMB_INO_T inode = 0;
902 SMB_STRUCT_STAT sbuf;
903 int smb_action = 0;
904 files_struct *fsp;
905 struct ea_list *ea_list = NULL;
906 uint16 flags = 0;
907 NTSTATUS status;
908 uint32 access_mask;
909 uint32 share_mode;
910 uint32 create_disposition;
911 uint32 create_options = 0;
912 TALLOC_CTX *ctx = talloc_tos();
915 * Ensure we have enough parameters to perform the operation.
918 if (total_params < 29) {
919 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
920 return;
923 flags = SVAL(params, 0);
924 deny_mode = SVAL(params, 2);
925 open_attr = SVAL(params,6);
926 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
927 if (oplock_request) {
928 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
931 #if 0
932 return_additional_info = BITSETW(params,0);
933 open_sattr = SVAL(params, 4);
934 open_time = make_unix_date3(params+8);
935 #endif
936 open_ofun = SVAL(params,12);
937 open_size = IVAL(params,14);
938 pname = &params[28];
940 if (IS_IPC(conn)) {
941 reply_doserror(req, ERRSRV, ERRaccess);
942 return;
945 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
946 total_params - 28, STR_TERMINATE,
947 &status);
948 if (!NT_STATUS_IS_OK(status)) {
949 reply_nterror(req, status);
950 return;
953 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
954 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
955 (unsigned int)open_ofun, open_size));
957 if (open_ofun == 0) {
958 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
959 return;
962 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
963 &access_mask,
964 &share_mode,
965 &create_disposition,
966 &create_options)) {
967 reply_doserror(req, ERRDOS, ERRbadaccess);
968 return;
971 /* Any data in this call is an EA list. */
972 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
973 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
974 return;
977 if (total_data != 4) {
978 if (total_data < 10) {
979 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
980 return;
983 if (IVAL(pdata,0) > total_data) {
984 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
985 IVAL(pdata,0), (unsigned int)total_data));
986 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
987 return;
990 ea_list = read_ea_list(talloc_tos(), pdata + 4,
991 total_data - 4);
992 if (!ea_list) {
993 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
994 return;
996 } else if (IVAL(pdata,0) != 4) {
997 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
998 return;
1001 status = create_file(conn, /* conn */
1002 req, /* req */
1003 0, /* root_dir_fid */
1004 fname, /* fname */
1005 access_mask, /* access_mask */
1006 share_mode, /* share_access */
1007 create_disposition, /* create_disposition*/
1008 create_options, /* create_options */
1009 open_attr, /* file_attributes */
1010 oplock_request, /* oplock_request */
1011 open_size, /* allocation_size */
1012 NULL, /* sd */
1013 ea_list, /* ea_list */
1014 &fsp, /* result */
1015 &smb_action, /* pinfo */
1016 &sbuf); /* psbuf */
1018 if (!NT_STATUS_IS_OK(status)) {
1019 if (open_was_deferred(req->mid)) {
1020 /* We have re-scheduled this call. */
1021 return;
1023 reply_openerror(req, status);
1024 return;
1027 size = get_file_size(sbuf);
1028 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1029 mtime = sbuf.st_mtime;
1030 inode = sbuf.st_ino;
1031 if (fattr & aDIR) {
1032 close_file(fsp,ERROR_CLOSE);
1033 reply_doserror(req, ERRDOS,ERRnoaccess);
1034 return;
1037 /* Realloc the size of parameters and data we will return */
1038 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1039 if(*pparams == NULL ) {
1040 reply_nterror(req, NT_STATUS_NO_MEMORY);
1041 return;
1043 params = *pparams;
1045 SSVAL(params,0,fsp->fnum);
1046 SSVAL(params,2,fattr);
1047 srv_put_dos_date2(params,4, mtime);
1048 SIVAL(params,8, (uint32)size);
1049 SSVAL(params,12,deny_mode);
1050 SSVAL(params,14,0); /* open_type - file or directory. */
1051 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1053 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1054 smb_action |= EXTENDED_OPLOCK_GRANTED;
1057 SSVAL(params,18,smb_action);
1060 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1062 SIVAL(params,20,inode);
1063 SSVAL(params,24,0); /* Padding. */
1064 if (flags & 8) {
1065 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1066 SIVAL(params, 26, ea_size);
1067 } else {
1068 SIVAL(params, 26, 0);
1071 /* Send the required number of replies */
1072 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1075 /*********************************************************
1076 Routine to check if a given string matches exactly.
1077 as a special case a mask of "." does NOT match. That
1078 is required for correct wildcard semantics
1079 Case can be significant or not.
1080 **********************************************************/
1082 static bool exact_match(connection_struct *conn,
1083 const char *str,
1084 const char *mask)
1086 if (mask[0] == '.' && mask[1] == 0)
1087 return False;
1088 if (conn->case_sensitive)
1089 return strcmp(str,mask)==0;
1090 if (StrCaseCmp(str,mask) != 0) {
1091 return False;
1093 if (dptr_has_wild(conn->dirptr)) {
1094 return False;
1096 return True;
1099 /****************************************************************************
1100 Return the filetype for UNIX extensions.
1101 ****************************************************************************/
1103 static uint32 unix_filetype(mode_t mode)
1105 if(S_ISREG(mode))
1106 return UNIX_TYPE_FILE;
1107 else if(S_ISDIR(mode))
1108 return UNIX_TYPE_DIR;
1109 #ifdef S_ISLNK
1110 else if(S_ISLNK(mode))
1111 return UNIX_TYPE_SYMLINK;
1112 #endif
1113 #ifdef S_ISCHR
1114 else if(S_ISCHR(mode))
1115 return UNIX_TYPE_CHARDEV;
1116 #endif
1117 #ifdef S_ISBLK
1118 else if(S_ISBLK(mode))
1119 return UNIX_TYPE_BLKDEV;
1120 #endif
1121 #ifdef S_ISFIFO
1122 else if(S_ISFIFO(mode))
1123 return UNIX_TYPE_FIFO;
1124 #endif
1125 #ifdef S_ISSOCK
1126 else if(S_ISSOCK(mode))
1127 return UNIX_TYPE_SOCKET;
1128 #endif
1130 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1131 return UNIX_TYPE_UNKNOWN;
1134 /****************************************************************************
1135 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1136 ****************************************************************************/
1138 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1140 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1141 SMB_STRUCT_STAT *psbuf,
1142 uint32 perms,
1143 enum perm_type ptype,
1144 mode_t *ret_perms)
1146 mode_t ret = 0;
1148 if (perms == SMB_MODE_NO_CHANGE) {
1149 if (!VALID_STAT(*psbuf)) {
1150 return NT_STATUS_INVALID_PARAMETER;
1151 } else {
1152 *ret_perms = psbuf->st_mode;
1153 return NT_STATUS_OK;
1157 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1158 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1159 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1160 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1161 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1162 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1163 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1164 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1165 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1166 #ifdef S_ISVTX
1167 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1168 #endif
1169 #ifdef S_ISGID
1170 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1171 #endif
1172 #ifdef S_ISUID
1173 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1174 #endif
1176 switch (ptype) {
1177 case PERM_NEW_FILE:
1178 /* Apply mode mask */
1179 ret &= lp_create_mask(SNUM(conn));
1180 /* Add in force bits */
1181 ret |= lp_force_create_mode(SNUM(conn));
1182 break;
1183 case PERM_NEW_DIR:
1184 ret &= lp_dir_mask(SNUM(conn));
1185 /* Add in force bits */
1186 ret |= lp_force_dir_mode(SNUM(conn));
1187 break;
1188 case PERM_EXISTING_FILE:
1189 /* Apply mode mask */
1190 ret &= lp_security_mask(SNUM(conn));
1191 /* Add in force bits */
1192 ret |= lp_force_security_mode(SNUM(conn));
1193 break;
1194 case PERM_EXISTING_DIR:
1195 /* Apply mode mask */
1196 ret &= lp_dir_security_mask(SNUM(conn));
1197 /* Add in force bits */
1198 ret |= lp_force_dir_security_mode(SNUM(conn));
1199 break;
1202 *ret_perms = ret;
1203 return NT_STATUS_OK;
1206 /****************************************************************************
1207 Needed to show the msdfs symlinks as directories. Modifies psbuf
1208 to be a directory if it's a msdfs link.
1209 ****************************************************************************/
1211 static bool check_msdfs_link(connection_struct *conn,
1212 const char *pathname,
1213 SMB_STRUCT_STAT *psbuf)
1215 int saved_errno = errno;
1216 if(lp_host_msdfs() &&
1217 lp_msdfs_root(SNUM(conn)) &&
1218 is_msdfs_link(conn, pathname, psbuf)) {
1220 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1221 "as a directory\n",
1222 pathname));
1223 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1224 errno = saved_errno;
1225 return true;
1227 errno = saved_errno;
1228 return false;
1232 /****************************************************************************
1233 Get a level dependent lanman2 dir entry.
1234 ****************************************************************************/
1236 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1237 connection_struct *conn,
1238 uint16 flags2,
1239 const char *path_mask,
1240 uint32 dirtype,
1241 int info_level,
1242 int requires_resume_key,
1243 bool dont_descend,
1244 bool ask_sharemode,
1245 char **ppdata,
1246 char *base_data,
1247 char *end_data,
1248 int space_remaining,
1249 bool *out_of_space,
1250 bool *got_exact_match,
1251 int *last_entry_off,
1252 struct ea_list *name_list)
1254 const char *dname;
1255 bool found = False;
1256 SMB_STRUCT_STAT sbuf;
1257 const char *mask = NULL;
1258 char *pathreal = NULL;
1259 const char *fname = NULL;
1260 char *p, *q, *pdata = *ppdata;
1261 uint32 reskey=0;
1262 long prev_dirpos=0;
1263 uint32 mode=0;
1264 SMB_OFF_T file_size = 0;
1265 SMB_BIG_UINT allocation_size = 0;
1266 uint32 len;
1267 struct timespec mdate_ts, adate_ts, create_date_ts;
1268 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1269 char *nameptr;
1270 char *last_entry_ptr;
1271 bool was_8_3;
1272 uint32 nt_extmode; /* Used for NT connections instead of mode */
1273 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1274 bool check_mangled_names = lp_manglednames(conn->params);
1275 char mangled_name[13]; /* mangled 8.3 name. */
1277 *out_of_space = False;
1278 *got_exact_match = False;
1280 ZERO_STRUCT(mdate_ts);
1281 ZERO_STRUCT(adate_ts);
1282 ZERO_STRUCT(create_date_ts);
1284 if (!conn->dirptr) {
1285 return(False);
1288 p = strrchr_m(path_mask,'/');
1289 if(p != NULL) {
1290 if(p[1] == '\0') {
1291 mask = talloc_strdup(ctx,"*.*");
1292 } else {
1293 mask = p+1;
1295 } else {
1296 mask = path_mask;
1299 while (!found) {
1300 bool got_match;
1301 bool ms_dfs_link = False;
1303 /* Needed if we run out of space */
1304 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1305 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1308 * Due to bugs in NT client redirectors we are not using
1309 * resume keys any more - set them to zero.
1310 * Check out the related comments in findfirst/findnext.
1311 * JRA.
1314 reskey = 0;
1316 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1317 (long)conn->dirptr,curr_dirpos));
1319 if (!dname) {
1320 return(False);
1324 * fname may get mangled, dname is never mangled.
1325 * Whenever we're accessing the filesystem we use
1326 * pathreal which is composed from dname.
1329 pathreal = NULL;
1330 fname = dname;
1332 /* Mangle fname if it's an illegal name. */
1333 if (mangle_must_mangle(dname,conn->params)) {
1334 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1335 continue; /* Error - couldn't mangle. */
1337 fname = mangled_name;
1340 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1341 got_match = mask_match(fname, mask, conn->case_sensitive);
1344 if(!got_match && check_mangled_names &&
1345 !mangle_is_8_3(fname, False, conn->params)) {
1347 * It turns out that NT matches wildcards against
1348 * both long *and* short names. This may explain some
1349 * of the wildcard wierdness from old DOS clients
1350 * that some people have been seeing.... JRA.
1352 /* Force the mangling into 8.3. */
1353 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1354 continue; /* Error - couldn't mangle. */
1357 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1358 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1362 if (got_match) {
1363 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1365 if (dont_descend && !isdots) {
1366 continue;
1369 if (needslash) {
1370 pathreal = NULL;
1371 pathreal = talloc_asprintf(ctx,
1372 "%s/%s",
1373 conn->dirpath,
1374 dname);
1375 } else {
1376 pathreal = talloc_asprintf(ctx,
1377 "%s%s",
1378 conn->dirpath,
1379 dname);
1382 if (!pathreal) {
1383 return False;
1386 if (INFO_LEVEL_IS_UNIX(info_level)) {
1387 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1388 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1389 pathreal,strerror(errno)));
1390 TALLOC_FREE(pathreal);
1391 continue;
1393 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1394 /* Needed to show the msdfs symlinks as
1395 * directories */
1397 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1398 if (!ms_dfs_link) {
1399 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1400 pathreal,strerror(errno)));
1401 TALLOC_FREE(pathreal);
1402 continue;
1406 if (ms_dfs_link) {
1407 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1408 } else {
1409 mode = dos_mode(conn,pathreal,&sbuf);
1412 if (!dir_check_ftype(conn,mode,dirtype)) {
1413 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1414 TALLOC_FREE(pathreal);
1415 continue;
1418 if (!(mode & aDIR)) {
1419 file_size = get_file_size(sbuf);
1421 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1423 mdate_ts = get_mtimespec(&sbuf);
1424 adate_ts = get_atimespec(&sbuf);
1425 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1427 if (ask_sharemode) {
1428 struct timespec write_time_ts;
1429 struct file_id fileid;
1431 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1432 get_file_infos(fileid, NULL, &write_time_ts);
1433 if (!null_timespec(write_time_ts)) {
1434 mdate_ts = write_time_ts;
1438 if (lp_dos_filetime_resolution(SNUM(conn))) {
1439 dos_filetime_timespec(&create_date_ts);
1440 dos_filetime_timespec(&mdate_ts);
1441 dos_filetime_timespec(&adate_ts);
1444 create_date = convert_timespec_to_time_t(create_date_ts);
1445 mdate = convert_timespec_to_time_t(mdate_ts);
1446 adate = convert_timespec_to_time_t(adate_ts);
1448 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1450 found = True;
1452 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1456 p = pdata;
1457 last_entry_ptr = p;
1459 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1461 switch (info_level) {
1462 case SMB_FIND_INFO_STANDARD:
1463 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1464 if(requires_resume_key) {
1465 SIVAL(p,0,reskey);
1466 p += 4;
1468 srv_put_dos_date2(p,0,create_date);
1469 srv_put_dos_date2(p,4,adate);
1470 srv_put_dos_date2(p,8,mdate);
1471 SIVAL(p,12,(uint32)file_size);
1472 SIVAL(p,16,(uint32)allocation_size);
1473 SSVAL(p,20,mode);
1474 p += 23;
1475 nameptr = p;
1476 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1477 p += ucs2_align(base_data, p, 0);
1479 len = srvstr_push(base_data, flags2, p,
1480 fname, PTR_DIFF(end_data, p),
1481 STR_TERMINATE);
1482 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1483 if (len > 2) {
1484 SCVAL(nameptr, -1, len - 2);
1485 } else {
1486 SCVAL(nameptr, -1, 0);
1488 } else {
1489 if (len > 1) {
1490 SCVAL(nameptr, -1, len - 1);
1491 } else {
1492 SCVAL(nameptr, -1, 0);
1495 p += len;
1496 break;
1498 case SMB_FIND_EA_SIZE:
1499 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1500 if(requires_resume_key) {
1501 SIVAL(p,0,reskey);
1502 p += 4;
1504 srv_put_dos_date2(p,0,create_date);
1505 srv_put_dos_date2(p,4,adate);
1506 srv_put_dos_date2(p,8,mdate);
1507 SIVAL(p,12,(uint32)file_size);
1508 SIVAL(p,16,(uint32)allocation_size);
1509 SSVAL(p,20,mode);
1511 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1512 SIVAL(p,22,ea_size); /* Extended attributes */
1514 p += 27;
1515 nameptr = p - 1;
1516 len = srvstr_push(base_data, flags2,
1517 p, fname, PTR_DIFF(end_data, p),
1518 STR_TERMINATE | STR_NOALIGN);
1519 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1520 if (len > 2) {
1521 len -= 2;
1522 } else {
1523 len = 0;
1525 } else {
1526 if (len > 1) {
1527 len -= 1;
1528 } else {
1529 len = 0;
1532 SCVAL(nameptr,0,len);
1533 p += len;
1534 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1535 break;
1537 case SMB_FIND_EA_LIST:
1539 struct ea_list *file_list = NULL;
1540 size_t ea_len = 0;
1542 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1543 if (!name_list) {
1544 return False;
1546 if(requires_resume_key) {
1547 SIVAL(p,0,reskey);
1548 p += 4;
1550 srv_put_dos_date2(p,0,create_date);
1551 srv_put_dos_date2(p,4,adate);
1552 srv_put_dos_date2(p,8,mdate);
1553 SIVAL(p,12,(uint32)file_size);
1554 SIVAL(p,16,(uint32)allocation_size);
1555 SSVAL(p,20,mode);
1556 p += 22; /* p now points to the EA area. */
1558 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1559 name_list = ea_list_union(name_list, file_list, &ea_len);
1561 /* We need to determine if this entry will fit in the space available. */
1562 /* Max string size is 255 bytes. */
1563 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1564 /* Move the dirptr back to prev_dirpos */
1565 dptr_SeekDir(conn->dirptr, prev_dirpos);
1566 *out_of_space = True;
1567 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1568 return False; /* Not finished - just out of space */
1571 /* Push the ea_data followed by the name. */
1572 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1573 nameptr = p;
1574 len = srvstr_push(base_data, flags2,
1575 p + 1, fname, PTR_DIFF(end_data, p+1),
1576 STR_TERMINATE | STR_NOALIGN);
1577 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1578 if (len > 2) {
1579 len -= 2;
1580 } else {
1581 len = 0;
1583 } else {
1584 if (len > 1) {
1585 len -= 1;
1586 } else {
1587 len = 0;
1590 SCVAL(nameptr,0,len);
1591 p += len + 1;
1592 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1593 break;
1596 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1597 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1598 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1599 p += 4;
1600 SIVAL(p,0,reskey); p += 4;
1601 put_long_date_timespec(p,create_date_ts); p += 8;
1602 put_long_date_timespec(p,adate_ts); p += 8;
1603 put_long_date_timespec(p,mdate_ts); p += 8;
1604 put_long_date_timespec(p,mdate_ts); p += 8;
1605 SOFF_T(p,0,file_size); p += 8;
1606 SOFF_T(p,0,allocation_size); p += 8;
1607 SIVAL(p,0,nt_extmode); p += 4;
1608 q = p; p += 4; /* q is placeholder for name length. */
1610 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1611 SIVAL(p,0,ea_size); /* Extended attributes */
1612 p += 4;
1614 /* Clear the short name buffer. This is
1615 * IMPORTANT as not doing so will trigger
1616 * a Win2k client bug. JRA.
1618 if (!was_8_3 && check_mangled_names) {
1619 if (!name_to_8_3(fname,mangled_name,True,
1620 conn->params)) {
1621 /* Error - mangle failed ! */
1622 memset(mangled_name,'\0',12);
1624 mangled_name[12] = 0;
1625 len = srvstr_push(base_data, flags2,
1626 p+2, mangled_name, 24,
1627 STR_UPPER|STR_UNICODE);
1628 if (len < 24) {
1629 memset(p + 2 + len,'\0',24 - len);
1631 SSVAL(p, 0, len);
1632 } else {
1633 memset(p,'\0',26);
1635 p += 2 + 24;
1636 len = srvstr_push(base_data, flags2, p,
1637 fname, PTR_DIFF(end_data, p),
1638 STR_TERMINATE_ASCII);
1639 SIVAL(q,0,len);
1640 p += len;
1641 SIVAL(p,0,0); /* Ensure any padding is null. */
1642 len = PTR_DIFF(p, pdata);
1643 len = (len + 3) & ~3;
1644 SIVAL(pdata,0,len);
1645 p = pdata + len;
1646 break;
1648 case SMB_FIND_FILE_DIRECTORY_INFO:
1649 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1650 p += 4;
1651 SIVAL(p,0,reskey); p += 4;
1652 put_long_date_timespec(p,create_date_ts); p += 8;
1653 put_long_date_timespec(p,adate_ts); p += 8;
1654 put_long_date_timespec(p,mdate_ts); p += 8;
1655 put_long_date_timespec(p,mdate_ts); p += 8;
1656 SOFF_T(p,0,file_size); p += 8;
1657 SOFF_T(p,0,allocation_size); p += 8;
1658 SIVAL(p,0,nt_extmode); p += 4;
1659 len = srvstr_push(base_data, flags2,
1660 p + 4, fname, PTR_DIFF(end_data, p+4),
1661 STR_TERMINATE_ASCII);
1662 SIVAL(p,0,len);
1663 p += 4 + len;
1664 SIVAL(p,0,0); /* Ensure any padding is null. */
1665 len = PTR_DIFF(p, pdata);
1666 len = (len + 3) & ~3;
1667 SIVAL(pdata,0,len);
1668 p = pdata + len;
1669 break;
1671 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1672 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1673 p += 4;
1674 SIVAL(p,0,reskey); p += 4;
1675 put_long_date_timespec(p,create_date_ts); p += 8;
1676 put_long_date_timespec(p,adate_ts); p += 8;
1677 put_long_date_timespec(p,mdate_ts); p += 8;
1678 put_long_date_timespec(p,mdate_ts); p += 8;
1679 SOFF_T(p,0,file_size); p += 8;
1680 SOFF_T(p,0,allocation_size); p += 8;
1681 SIVAL(p,0,nt_extmode); p += 4;
1682 q = p; p += 4; /* q is placeholder for name length. */
1684 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1685 SIVAL(p,0,ea_size); /* Extended attributes */
1686 p +=4;
1688 len = srvstr_push(base_data, flags2, p,
1689 fname, PTR_DIFF(end_data, p),
1690 STR_TERMINATE_ASCII);
1691 SIVAL(q, 0, len);
1692 p += len;
1694 SIVAL(p,0,0); /* Ensure any padding is null. */
1695 len = PTR_DIFF(p, pdata);
1696 len = (len + 3) & ~3;
1697 SIVAL(pdata,0,len);
1698 p = pdata + len;
1699 break;
1701 case SMB_FIND_FILE_NAMES_INFO:
1702 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1703 p += 4;
1704 SIVAL(p,0,reskey); p += 4;
1705 p += 4;
1706 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1707 acl on a dir (tridge) */
1708 len = srvstr_push(base_data, flags2, p,
1709 fname, PTR_DIFF(end_data, p),
1710 STR_TERMINATE_ASCII);
1711 SIVAL(p, -4, len);
1712 p += len;
1713 SIVAL(p,0,0); /* Ensure any padding is null. */
1714 len = PTR_DIFF(p, pdata);
1715 len = (len + 3) & ~3;
1716 SIVAL(pdata,0,len);
1717 p = pdata + len;
1718 break;
1720 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1721 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1722 p += 4;
1723 SIVAL(p,0,reskey); p += 4;
1724 put_long_date_timespec(p,create_date_ts); p += 8;
1725 put_long_date_timespec(p,adate_ts); p += 8;
1726 put_long_date_timespec(p,mdate_ts); p += 8;
1727 put_long_date_timespec(p,mdate_ts); p += 8;
1728 SOFF_T(p,0,file_size); p += 8;
1729 SOFF_T(p,0,allocation_size); p += 8;
1730 SIVAL(p,0,nt_extmode); p += 4;
1731 q = p; p += 4; /* q is placeholder for name length. */
1733 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1734 SIVAL(p,0,ea_size); /* Extended attributes */
1735 p +=4;
1737 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1738 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1739 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1740 len = srvstr_push(base_data, flags2, p,
1741 fname, PTR_DIFF(end_data, p),
1742 STR_TERMINATE_ASCII);
1743 SIVAL(q, 0, len);
1744 p += len;
1745 SIVAL(p,0,0); /* Ensure any padding is null. */
1746 len = PTR_DIFF(p, pdata);
1747 len = (len + 3) & ~3;
1748 SIVAL(pdata,0,len);
1749 p = pdata + len;
1750 break;
1752 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1753 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1754 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1755 p += 4;
1756 SIVAL(p,0,reskey); p += 4;
1757 put_long_date_timespec(p,create_date_ts); p += 8;
1758 put_long_date_timespec(p,adate_ts); p += 8;
1759 put_long_date_timespec(p,mdate_ts); p += 8;
1760 put_long_date_timespec(p,mdate_ts); p += 8;
1761 SOFF_T(p,0,file_size); p += 8;
1762 SOFF_T(p,0,allocation_size); p += 8;
1763 SIVAL(p,0,nt_extmode); p += 4;
1764 q = p; p += 4; /* q is placeholder for name length */
1766 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1767 SIVAL(p,0,ea_size); /* Extended attributes */
1768 p +=4;
1770 /* Clear the short name buffer. This is
1771 * IMPORTANT as not doing so will trigger
1772 * a Win2k client bug. JRA.
1774 if (!was_8_3 && check_mangled_names) {
1775 if (!name_to_8_3(fname,mangled_name,True,
1776 conn->params)) {
1777 /* Error - mangle failed ! */
1778 memset(mangled_name,'\0',12);
1780 mangled_name[12] = 0;
1781 len = srvstr_push(base_data, flags2,
1782 p+2, mangled_name, 24,
1783 STR_UPPER|STR_UNICODE);
1784 SSVAL(p, 0, len);
1785 if (len < 24) {
1786 memset(p + 2 + len,'\0',24 - len);
1788 SSVAL(p, 0, len);
1789 } else {
1790 memset(p,'\0',26);
1792 p += 26;
1793 SSVAL(p,0,0); p += 2; /* Reserved ? */
1794 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1795 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1796 len = srvstr_push(base_data, flags2, p,
1797 fname, PTR_DIFF(end_data, p),
1798 STR_TERMINATE_ASCII);
1799 SIVAL(q,0,len);
1800 p += len;
1801 SIVAL(p,0,0); /* Ensure any padding is null. */
1802 len = PTR_DIFF(p, pdata);
1803 len = (len + 3) & ~3;
1804 SIVAL(pdata,0,len);
1805 p = pdata + len;
1806 break;
1808 /* CIFS UNIX Extension. */
1810 case SMB_FIND_FILE_UNIX:
1811 case SMB_FIND_FILE_UNIX_INFO2:
1812 p+= 4;
1813 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1815 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1817 if (info_level == SMB_FIND_FILE_UNIX) {
1818 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1819 p = store_file_unix_basic(conn, p,
1820 NULL, &sbuf);
1821 len = srvstr_push(base_data, flags2, p,
1822 fname, PTR_DIFF(end_data, p),
1823 STR_TERMINATE);
1824 } else {
1825 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1826 p = store_file_unix_basic_info2(conn, p,
1827 NULL, &sbuf);
1828 nameptr = p;
1829 p += 4;
1830 len = srvstr_push(base_data, flags2, p, fname,
1831 PTR_DIFF(end_data, p), 0);
1832 SIVAL(nameptr, 0, len);
1835 p += len;
1836 SIVAL(p,0,0); /* Ensure any padding is null. */
1838 len = PTR_DIFF(p, pdata);
1839 len = (len + 3) & ~3;
1840 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1841 p = pdata + len;
1842 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1844 break;
1846 default:
1847 return(False);
1851 if (PTR_DIFF(p,pdata) > space_remaining) {
1852 /* Move the dirptr back to prev_dirpos */
1853 dptr_SeekDir(conn->dirptr, prev_dirpos);
1854 *out_of_space = True;
1855 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1856 return False; /* Not finished - just out of space */
1859 /* Setup the last entry pointer, as an offset from base_data */
1860 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1861 /* Advance the data pointer to the next slot */
1862 *ppdata = p;
1864 return(found);
1867 /****************************************************************************
1868 Reply to a TRANS2_FINDFIRST.
1869 ****************************************************************************/
1871 static void call_trans2findfirst(connection_struct *conn,
1872 struct smb_request *req,
1873 char **pparams, int total_params,
1874 char **ppdata, int total_data,
1875 unsigned int max_data_bytes)
1877 /* We must be careful here that we don't return more than the
1878 allowed number of data bytes. If this means returning fewer than
1879 maxentries then so be it. We assume that the redirector has
1880 enough room for the fixed number of parameter bytes it has
1881 requested. */
1882 char *params = *pparams;
1883 char *pdata = *ppdata;
1884 char *data_end;
1885 uint32 dirtype;
1886 int maxentries;
1887 uint16 findfirst_flags;
1888 bool close_after_first;
1889 bool close_if_end;
1890 bool requires_resume_key;
1891 int info_level;
1892 char *directory = NULL;
1893 const char *mask = NULL;
1894 char *p;
1895 int last_entry_off=0;
1896 int dptr_num = -1;
1897 int numentries = 0;
1898 int i;
1899 bool finished = False;
1900 bool dont_descend = False;
1901 bool out_of_space = False;
1902 int space_remaining;
1903 bool mask_contains_wcard = False;
1904 SMB_STRUCT_STAT sbuf;
1905 struct ea_list *ea_list = NULL;
1906 NTSTATUS ntstatus = NT_STATUS_OK;
1907 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1908 TALLOC_CTX *ctx = talloc_tos();
1910 if (total_params < 13) {
1911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1912 return;
1915 dirtype = SVAL(params,0);
1916 maxentries = SVAL(params,2);
1917 findfirst_flags = SVAL(params,4);
1918 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1919 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1920 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1921 info_level = SVAL(params,6);
1923 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1924 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1925 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1926 info_level, max_data_bytes));
1928 if (!maxentries) {
1929 /* W2K3 seems to treat zero as 1. */
1930 maxentries = 1;
1933 switch (info_level) {
1934 case SMB_FIND_INFO_STANDARD:
1935 case SMB_FIND_EA_SIZE:
1936 case SMB_FIND_EA_LIST:
1937 case SMB_FIND_FILE_DIRECTORY_INFO:
1938 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1939 case SMB_FIND_FILE_NAMES_INFO:
1940 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1941 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1942 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1943 break;
1944 case SMB_FIND_FILE_UNIX:
1945 case SMB_FIND_FILE_UNIX_INFO2:
1946 if (!lp_unix_extensions()) {
1947 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1948 return;
1950 break;
1951 default:
1952 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1953 return;
1956 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1957 params+12, total_params - 12,
1958 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1959 if (!NT_STATUS_IS_OK(ntstatus)) {
1960 reply_nterror(req, ntstatus);
1961 return;
1964 ntstatus = resolve_dfspath_wcard(ctx, conn,
1965 req->flags2 & FLAGS2_DFS_PATHNAMES,
1966 directory,
1967 &directory,
1968 &mask_contains_wcard);
1969 if (!NT_STATUS_IS_OK(ntstatus)) {
1970 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1971 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1972 ERRSRV, ERRbadpath);
1973 return;
1975 reply_nterror(req, ntstatus);
1976 return;
1979 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1980 if (!NT_STATUS_IS_OK(ntstatus)) {
1981 reply_nterror(req, ntstatus);
1982 return;
1985 ntstatus = check_name(conn, directory);
1986 if (!NT_STATUS_IS_OK(ntstatus)) {
1987 reply_nterror(req, ntstatus);
1988 return;
1991 p = strrchr_m(directory,'/');
1992 if(p == NULL) {
1993 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1994 if((directory[0] == '.') && (directory[1] == '\0')) {
1995 mask = "*";
1996 mask_contains_wcard = True;
1997 } else {
1998 mask = directory;
2000 directory = talloc_strdup(talloc_tos(), "./");
2001 if (!directory) {
2002 reply_nterror(req, NT_STATUS_NO_MEMORY);
2003 return;
2005 } else {
2006 mask = p+1;
2007 *p = 0;
2010 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2012 if (info_level == SMB_FIND_EA_LIST) {
2013 uint32 ea_size;
2015 if (total_data < 4) {
2016 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2017 return;
2020 ea_size = IVAL(pdata,0);
2021 if (ea_size != total_data) {
2022 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2023 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2024 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2025 return;
2028 if (!lp_ea_support(SNUM(conn))) {
2029 reply_doserror(req, ERRDOS, ERReasnotsupported);
2030 return;
2033 /* Pull out the list of names. */
2034 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2035 if (!ea_list) {
2036 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2037 return;
2041 *ppdata = (char *)SMB_REALLOC(
2042 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2043 if(*ppdata == NULL ) {
2044 reply_nterror(req, NT_STATUS_NO_MEMORY);
2045 return;
2047 pdata = *ppdata;
2048 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2050 /* Realloc the params space */
2051 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2052 if (*pparams == NULL) {
2053 reply_nterror(req, NT_STATUS_NO_MEMORY);
2054 return;
2056 params = *pparams;
2058 /* Save the wildcard match and attribs we are using on this directory -
2059 needed as lanman2 assumes these are being saved between calls */
2061 ntstatus = dptr_create(conn,
2062 directory,
2063 False,
2064 True,
2065 req->smbpid,
2066 mask,
2067 mask_contains_wcard,
2068 dirtype,
2069 &conn->dirptr);
2071 if (!NT_STATUS_IS_OK(ntstatus)) {
2072 reply_nterror(req, ntstatus);
2073 return;
2076 dptr_num = dptr_dnum(conn->dirptr);
2077 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2079 /* We don't need to check for VOL here as this is returned by
2080 a different TRANS2 call. */
2082 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2083 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2084 dont_descend = True;
2086 p = pdata;
2087 space_remaining = max_data_bytes;
2088 out_of_space = False;
2090 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2091 bool got_exact_match = False;
2093 /* this is a heuristic to avoid seeking the dirptr except when
2094 absolutely necessary. It allows for a filename of about 40 chars */
2095 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2096 out_of_space = True;
2097 finished = False;
2098 } else {
2099 finished = !get_lanman2_dir_entry(ctx,
2100 conn,
2101 req->flags2,
2102 mask,dirtype,info_level,
2103 requires_resume_key,dont_descend,
2104 ask_sharemode,
2105 &p,pdata,data_end,
2106 space_remaining, &out_of_space,
2107 &got_exact_match,
2108 &last_entry_off, ea_list);
2111 if (finished && out_of_space)
2112 finished = False;
2114 if (!finished && !out_of_space)
2115 numentries++;
2118 * As an optimisation if we know we aren't looking
2119 * for a wildcard name (ie. the name matches the wildcard exactly)
2120 * then we can finish on any (first) match.
2121 * This speeds up large directory searches. JRA.
2124 if(got_exact_match)
2125 finished = True;
2127 /* Ensure space_remaining never goes -ve. */
2128 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2129 space_remaining = 0;
2130 out_of_space = true;
2131 } else {
2132 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2136 /* Check if we can close the dirptr */
2137 if(close_after_first || (finished && close_if_end)) {
2138 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2139 dptr_close(&dptr_num);
2143 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2144 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2145 * the protocol level is less than NT1. Tested with smbclient. JRA.
2146 * This should fix the OS/2 client bug #2335.
2149 if(numentries == 0) {
2150 dptr_close(&dptr_num);
2151 if (Protocol < PROTOCOL_NT1) {
2152 reply_doserror(req, ERRDOS, ERRnofiles);
2153 return;
2154 } else {
2155 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2156 ERRDOS, ERRbadfile);
2157 return;
2161 /* At this point pdata points to numentries directory entries. */
2163 /* Set up the return parameter block */
2164 SSVAL(params,0,dptr_num);
2165 SSVAL(params,2,numentries);
2166 SSVAL(params,4,finished);
2167 SSVAL(params,6,0); /* Never an EA error */
2168 SSVAL(params,8,last_entry_off);
2170 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2171 max_data_bytes);
2173 if ((! *directory) && dptr_path(dptr_num)) {
2174 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2175 if (!directory) {
2176 reply_nterror(req, NT_STATUS_NO_MEMORY);
2180 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2181 smb_fn_name(CVAL(req->inbuf,smb_com)),
2182 mask, directory, dirtype, numentries ) );
2185 * Force a name mangle here to ensure that the
2186 * mask as an 8.3 name is top of the mangled cache.
2187 * The reasons for this are subtle. Don't remove
2188 * this code unless you know what you are doing
2189 * (see PR#13758). JRA.
2192 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2193 char mangled_name[13];
2194 name_to_8_3(mask, mangled_name, True, conn->params);
2197 return;
2200 /****************************************************************************
2201 Reply to a TRANS2_FINDNEXT.
2202 ****************************************************************************/
2204 static void call_trans2findnext(connection_struct *conn,
2205 struct smb_request *req,
2206 char **pparams, int total_params,
2207 char **ppdata, int total_data,
2208 unsigned int max_data_bytes)
2210 /* We must be careful here that we don't return more than the
2211 allowed number of data bytes. If this means returning fewer than
2212 maxentries then so be it. We assume that the redirector has
2213 enough room for the fixed number of parameter bytes it has
2214 requested. */
2215 char *params = *pparams;
2216 char *pdata = *ppdata;
2217 char *data_end;
2218 int dptr_num;
2219 int maxentries;
2220 uint16 info_level;
2221 uint32 resume_key;
2222 uint16 findnext_flags;
2223 bool close_after_request;
2224 bool close_if_end;
2225 bool requires_resume_key;
2226 bool continue_bit;
2227 bool mask_contains_wcard = False;
2228 char *resume_name = NULL;
2229 const char *mask = NULL;
2230 const char *directory = NULL;
2231 char *p = NULL;
2232 uint16 dirtype;
2233 int numentries = 0;
2234 int i, last_entry_off=0;
2235 bool finished = False;
2236 bool dont_descend = False;
2237 bool out_of_space = False;
2238 int space_remaining;
2239 struct ea_list *ea_list = NULL;
2240 NTSTATUS ntstatus = NT_STATUS_OK;
2241 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2242 TALLOC_CTX *ctx = talloc_tos();
2244 if (total_params < 13) {
2245 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2246 return;
2249 dptr_num = SVAL(params,0);
2250 maxentries = SVAL(params,2);
2251 info_level = SVAL(params,4);
2252 resume_key = IVAL(params,6);
2253 findnext_flags = SVAL(params,10);
2254 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2255 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2256 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2257 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2259 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2260 params+12,
2261 total_params - 12, STR_TERMINATE, &ntstatus,
2262 &mask_contains_wcard);
2263 if (!NT_STATUS_IS_OK(ntstatus)) {
2264 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2265 complain (it thinks we're asking for the directory above the shared
2266 path or an invalid name). Catch this as the resume name is only compared, never used in
2267 a file access. JRA. */
2268 srvstr_pull_talloc(ctx, params, req->flags2,
2269 &resume_name, params+12,
2270 total_params - 12,
2271 STR_TERMINATE);
2273 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2274 reply_nterror(req, ntstatus);
2275 return;
2279 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2280 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2281 resume_key = %d resume name = %s continue=%d level = %d\n",
2282 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2283 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2285 if (!maxentries) {
2286 /* W2K3 seems to treat zero as 1. */
2287 maxentries = 1;
2290 switch (info_level) {
2291 case SMB_FIND_INFO_STANDARD:
2292 case SMB_FIND_EA_SIZE:
2293 case SMB_FIND_EA_LIST:
2294 case SMB_FIND_FILE_DIRECTORY_INFO:
2295 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2296 case SMB_FIND_FILE_NAMES_INFO:
2297 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2298 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2299 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2300 break;
2301 case SMB_FIND_FILE_UNIX:
2302 case SMB_FIND_FILE_UNIX_INFO2:
2303 if (!lp_unix_extensions()) {
2304 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2305 return;
2307 break;
2308 default:
2309 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2310 return;
2313 if (info_level == SMB_FIND_EA_LIST) {
2314 uint32 ea_size;
2316 if (total_data < 4) {
2317 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2318 return;
2321 ea_size = IVAL(pdata,0);
2322 if (ea_size != total_data) {
2323 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2324 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2325 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2326 return;
2329 if (!lp_ea_support(SNUM(conn))) {
2330 reply_doserror(req, ERRDOS, ERReasnotsupported);
2331 return;
2334 /* Pull out the list of names. */
2335 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2336 if (!ea_list) {
2337 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2338 return;
2342 *ppdata = (char *)SMB_REALLOC(
2343 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2344 if(*ppdata == NULL) {
2345 reply_nterror(req, NT_STATUS_NO_MEMORY);
2346 return;
2349 pdata = *ppdata;
2350 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2352 /* Realloc the params space */
2353 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2354 if(*pparams == NULL ) {
2355 reply_nterror(req, NT_STATUS_NO_MEMORY);
2356 return;
2359 params = *pparams;
2361 /* Check that the dptr is valid */
2362 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2363 reply_doserror(req, ERRDOS, ERRnofiles);
2364 return;
2367 string_set(&conn->dirpath,dptr_path(dptr_num));
2369 /* Get the wildcard mask from the dptr */
2370 if((p = dptr_wcard(dptr_num))== NULL) {
2371 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2372 reply_doserror(req, ERRDOS, ERRnofiles);
2373 return;
2376 mask = p;
2377 directory = conn->dirpath;
2379 /* Get the attr mask from the dptr */
2380 dirtype = dptr_attr(dptr_num);
2382 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2383 dptr_num, mask, dirtype,
2384 (long)conn->dirptr,
2385 dptr_TellDir(conn->dirptr)));
2387 /* We don't need to check for VOL here as this is returned by
2388 a different TRANS2 call. */
2390 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2391 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2392 dont_descend = True;
2394 p = pdata;
2395 space_remaining = max_data_bytes;
2396 out_of_space = False;
2399 * Seek to the correct position. We no longer use the resume key but
2400 * depend on the last file name instead.
2403 if(*resume_name && !continue_bit) {
2404 SMB_STRUCT_STAT st;
2406 long current_pos = 0;
2408 * Remember, name_to_8_3 is called by
2409 * get_lanman2_dir_entry(), so the resume name
2410 * could be mangled. Ensure we check the unmangled name.
2413 if (mangle_is_mangled(resume_name, conn->params)) {
2414 char *new_resume_name = NULL;
2415 mangle_lookup_name_from_8_3(ctx,
2416 resume_name,
2417 &new_resume_name,
2418 conn->params);
2419 if (new_resume_name) {
2420 resume_name = new_resume_name;
2425 * Fix for NT redirector problem triggered by resume key indexes
2426 * changing between directory scans. We now return a resume key of 0
2427 * and instead look for the filename to continue from (also given
2428 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2429 * findfirst/findnext (as is usual) then the directory pointer
2430 * should already be at the correct place.
2433 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2434 } /* end if resume_name && !continue_bit */
2436 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2437 bool got_exact_match = False;
2439 /* this is a heuristic to avoid seeking the dirptr except when
2440 absolutely necessary. It allows for a filename of about 40 chars */
2441 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2442 out_of_space = True;
2443 finished = False;
2444 } else {
2445 finished = !get_lanman2_dir_entry(ctx,
2446 conn,
2447 req->flags2,
2448 mask,dirtype,info_level,
2449 requires_resume_key,dont_descend,
2450 ask_sharemode,
2451 &p,pdata,data_end,
2452 space_remaining, &out_of_space,
2453 &got_exact_match,
2454 &last_entry_off, ea_list);
2457 if (finished && out_of_space)
2458 finished = False;
2460 if (!finished && !out_of_space)
2461 numentries++;
2464 * As an optimisation if we know we aren't looking
2465 * for a wildcard name (ie. the name matches the wildcard exactly)
2466 * then we can finish on any (first) match.
2467 * This speeds up large directory searches. JRA.
2470 if(got_exact_match)
2471 finished = True;
2473 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2476 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2477 smb_fn_name(CVAL(req->inbuf,smb_com)),
2478 mask, directory, dirtype, numentries ) );
2480 /* Check if we can close the dirptr */
2481 if(close_after_request || (finished && close_if_end)) {
2482 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2483 dptr_close(&dptr_num); /* This frees up the saved mask */
2486 /* Set up the return parameter block */
2487 SSVAL(params,0,numentries);
2488 SSVAL(params,2,finished);
2489 SSVAL(params,4,0); /* Never an EA error */
2490 SSVAL(params,6,last_entry_off);
2492 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2493 max_data_bytes);
2495 return;
2498 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2500 E_md4hash(lp_servicename(SNUM(conn)),objid);
2501 return objid;
2504 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2506 SMB_ASSERT(extended_info != NULL);
2508 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2509 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2510 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2511 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2512 #ifdef SAMBA_VERSION_REVISION
2513 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2514 #endif
2515 extended_info->samba_subversion = 0;
2516 #ifdef SAMBA_VERSION_RC_RELEASE
2517 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2518 #else
2519 #ifdef SAMBA_VERSION_PRE_RELEASE
2520 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2521 #endif
2522 #endif
2523 #ifdef SAMBA_VERSION_VENDOR_PATCH
2524 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2525 #endif
2526 extended_info->samba_gitcommitdate = 0;
2527 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2528 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2529 #endif
2531 memset(extended_info->samba_version_string, 0,
2532 sizeof(extended_info->samba_version_string));
2534 snprintf (extended_info->samba_version_string,
2535 sizeof(extended_info->samba_version_string),
2536 "%s", samba_version_string());
2539 /****************************************************************************
2540 Reply to a TRANS2_QFSINFO (query filesystem info).
2541 ****************************************************************************/
2543 static void call_trans2qfsinfo(connection_struct *conn,
2544 struct smb_request *req,
2545 char **pparams, int total_params,
2546 char **ppdata, int total_data,
2547 unsigned int max_data_bytes)
2549 char *pdata, *end_data;
2550 char *params = *pparams;
2551 uint16 info_level;
2552 int data_len, len;
2553 SMB_STRUCT_STAT st;
2554 const char *vname = volume_label(SNUM(conn));
2555 int snum = SNUM(conn);
2556 char *fstype = lp_fstype(SNUM(conn));
2557 uint32 additional_flags = 0;
2559 if (total_params < 2) {
2560 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2561 return;
2564 info_level = SVAL(params,0);
2566 if (IS_IPC(conn)) {
2567 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2568 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2569 "info level (0x%x) on IPC$.\n",
2570 (unsigned int)info_level));
2571 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2572 return;
2576 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2577 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2578 DEBUG(0,("call_trans2qfsinfo: encryption required "
2579 "and info level 0x%x sent.\n",
2580 (unsigned int)info_level));
2581 exit_server_cleanly("encryption required "
2582 "on connection");
2583 return;
2587 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2589 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2590 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2591 reply_doserror(req, ERRSRV, ERRinvdevice);
2592 return;
2595 *ppdata = (char *)SMB_REALLOC(
2596 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2597 if (*ppdata == NULL ) {
2598 reply_nterror(req, NT_STATUS_NO_MEMORY);
2599 return;
2602 pdata = *ppdata;
2603 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2604 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2606 switch (info_level) {
2607 case SMB_INFO_ALLOCATION:
2609 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2610 data_len = 18;
2611 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2612 reply_unixerror(req, ERRHRD, ERRgeneral);
2613 return;
2616 block_size = lp_block_size(snum);
2617 if (bsize < block_size) {
2618 SMB_BIG_UINT factor = block_size/bsize;
2619 bsize = block_size;
2620 dsize /= factor;
2621 dfree /= factor;
2623 if (bsize > block_size) {
2624 SMB_BIG_UINT factor = bsize/block_size;
2625 bsize = block_size;
2626 dsize *= factor;
2627 dfree *= factor;
2629 bytes_per_sector = 512;
2630 sectors_per_unit = bsize/bytes_per_sector;
2632 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2633 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2634 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2636 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2637 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2638 SIVAL(pdata,l1_cUnit,dsize);
2639 SIVAL(pdata,l1_cUnitAvail,dfree);
2640 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2641 break;
2644 case SMB_INFO_VOLUME:
2645 /* Return volume name */
2647 * Add volume serial number - hash of a combination of
2648 * the called hostname and the service name.
2650 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2652 * Win2k3 and previous mess this up by sending a name length
2653 * one byte short. I believe only older clients (OS/2 Win9x) use
2654 * this call so try fixing this by adding a terminating null to
2655 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2657 len = srvstr_push(
2658 pdata, req->flags2,
2659 pdata+l2_vol_szVolLabel, vname,
2660 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2661 STR_NOALIGN|STR_TERMINATE);
2662 SCVAL(pdata,l2_vol_cch,len);
2663 data_len = l2_vol_szVolLabel + len;
2664 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2665 (unsigned)st.st_ctime, len, vname));
2666 break;
2668 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2669 case SMB_FS_ATTRIBUTE_INFORMATION:
2671 additional_flags = 0;
2672 #if defined(HAVE_SYS_QUOTAS)
2673 additional_flags |= FILE_VOLUME_QUOTAS;
2674 #endif
2676 if(lp_nt_acl_support(SNUM(conn))) {
2677 additional_flags |= FILE_PERSISTENT_ACLS;
2680 /* Capabilities are filled in at connection time through STATVFS call */
2681 additional_flags |= conn->fs_capabilities;
2683 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2684 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2685 additional_flags); /* FS ATTRIBUTES */
2687 SIVAL(pdata,4,255); /* Max filename component length */
2688 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2689 and will think we can't do long filenames */
2690 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2691 PTR_DIFF(end_data, pdata+12),
2692 STR_UNICODE);
2693 SIVAL(pdata,8,len);
2694 data_len = 12 + len;
2695 break;
2697 case SMB_QUERY_FS_LABEL_INFO:
2698 case SMB_FS_LABEL_INFORMATION:
2699 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2700 PTR_DIFF(end_data, pdata+4), 0);
2701 data_len = 4 + len;
2702 SIVAL(pdata,0,len);
2703 break;
2705 case SMB_QUERY_FS_VOLUME_INFO:
2706 case SMB_FS_VOLUME_INFORMATION:
2709 * Add volume serial number - hash of a combination of
2710 * the called hostname and the service name.
2712 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2713 (str_checksum(get_local_machine_name())<<16));
2715 /* Max label len is 32 characters. */
2716 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2717 PTR_DIFF(end_data, pdata+18),
2718 STR_UNICODE);
2719 SIVAL(pdata,12,len);
2720 data_len = 18+len;
2722 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2723 (int)strlen(vname),vname, lp_servicename(snum)));
2724 break;
2726 case SMB_QUERY_FS_SIZE_INFO:
2727 case SMB_FS_SIZE_INFORMATION:
2729 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2730 data_len = 24;
2731 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2732 reply_unixerror(req, ERRHRD, ERRgeneral);
2733 return;
2735 block_size = lp_block_size(snum);
2736 if (bsize < block_size) {
2737 SMB_BIG_UINT factor = block_size/bsize;
2738 bsize = block_size;
2739 dsize /= factor;
2740 dfree /= factor;
2742 if (bsize > block_size) {
2743 SMB_BIG_UINT factor = bsize/block_size;
2744 bsize = block_size;
2745 dsize *= factor;
2746 dfree *= factor;
2748 bytes_per_sector = 512;
2749 sectors_per_unit = bsize/bytes_per_sector;
2750 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2751 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2752 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2753 SBIG_UINT(pdata,0,dsize);
2754 SBIG_UINT(pdata,8,dfree);
2755 SIVAL(pdata,16,sectors_per_unit);
2756 SIVAL(pdata,20,bytes_per_sector);
2757 break;
2760 case SMB_FS_FULL_SIZE_INFORMATION:
2762 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2763 data_len = 32;
2764 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2765 reply_unixerror(req, ERRHRD, ERRgeneral);
2766 return;
2768 block_size = lp_block_size(snum);
2769 if (bsize < block_size) {
2770 SMB_BIG_UINT factor = block_size/bsize;
2771 bsize = block_size;
2772 dsize /= factor;
2773 dfree /= factor;
2775 if (bsize > block_size) {
2776 SMB_BIG_UINT factor = bsize/block_size;
2777 bsize = block_size;
2778 dsize *= factor;
2779 dfree *= factor;
2781 bytes_per_sector = 512;
2782 sectors_per_unit = bsize/bytes_per_sector;
2783 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2784 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2785 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2786 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2787 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2788 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2789 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2790 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2791 break;
2794 case SMB_QUERY_FS_DEVICE_INFO:
2795 case SMB_FS_DEVICE_INFORMATION:
2796 data_len = 8;
2797 SIVAL(pdata,0,0); /* dev type */
2798 SIVAL(pdata,4,0); /* characteristics */
2799 break;
2801 #ifdef HAVE_SYS_QUOTAS
2802 case SMB_FS_QUOTA_INFORMATION:
2804 * what we have to send --metze:
2806 * Unknown1: 24 NULL bytes
2807 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2808 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2809 * Quota Flags: 2 byte :
2810 * Unknown3: 6 NULL bytes
2812 * 48 bytes total
2814 * details for Quota Flags:
2816 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2817 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2818 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2819 * 0x0001 Enable Quotas: enable quota for this fs
2823 /* we need to fake up a fsp here,
2824 * because its not send in this call
2826 files_struct fsp;
2827 SMB_NTQUOTA_STRUCT quotas;
2829 ZERO_STRUCT(fsp);
2830 ZERO_STRUCT(quotas);
2832 fsp.conn = conn;
2833 fsp.fnum = -1;
2835 /* access check */
2836 if (current_user.ut.uid != 0) {
2837 DEBUG(0,("set_user_quota: access_denied "
2838 "service [%s] user [%s]\n",
2839 lp_servicename(SNUM(conn)),
2840 conn->server_info->unix_name));
2841 reply_doserror(req, ERRDOS, ERRnoaccess);
2842 return;
2845 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2846 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2847 reply_doserror(req, ERRSRV, ERRerror);
2848 return;
2851 data_len = 48;
2853 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2855 /* Unknown1 24 NULL bytes*/
2856 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2857 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2858 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2860 /* Default Soft Quota 8 bytes */
2861 SBIG_UINT(pdata,24,quotas.softlim);
2863 /* Default Hard Quota 8 bytes */
2864 SBIG_UINT(pdata,32,quotas.hardlim);
2866 /* Quota flag 2 bytes */
2867 SSVAL(pdata,40,quotas.qflags);
2869 /* Unknown3 6 NULL bytes */
2870 SSVAL(pdata,42,0);
2871 SIVAL(pdata,44,0);
2873 break;
2875 #endif /* HAVE_SYS_QUOTAS */
2876 case SMB_FS_OBJECTID_INFORMATION:
2878 unsigned char objid[16];
2879 struct smb_extended_info extended_info;
2880 memcpy(pdata,create_volume_objectid(conn, objid),16);
2881 samba_extended_info_version (&extended_info);
2882 SIVAL(pdata,16,extended_info.samba_magic);
2883 SIVAL(pdata,20,extended_info.samba_version);
2884 SIVAL(pdata,24,extended_info.samba_subversion);
2885 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2886 memcpy(pdata+36,extended_info.samba_version_string,28);
2887 data_len = 64;
2888 break;
2892 * Query the version and capabilities of the CIFS UNIX extensions
2893 * in use.
2896 case SMB_QUERY_CIFS_UNIX_INFO:
2898 bool large_write = lp_min_receive_file_size() &&
2899 !srv_is_signing_active();
2900 bool large_read = !srv_is_signing_active();
2901 int encrypt_caps = 0;
2903 if (!lp_unix_extensions()) {
2904 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2905 return;
2908 switch (conn->encrypt_level) {
2909 case 0:
2910 encrypt_caps = 0;
2911 break;
2912 case 1:
2913 case Auto:
2914 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2915 break;
2916 case Required:
2917 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2918 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2919 large_write = false;
2920 large_read = false;
2921 break;
2924 data_len = 12;
2925 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2926 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2928 /* We have POSIX ACLs, pathname, encryption,
2929 * large read/write, and locking capability. */
2931 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2932 CIFS_UNIX_POSIX_ACLS_CAP|
2933 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2934 CIFS_UNIX_FCNTL_LOCKS_CAP|
2935 CIFS_UNIX_EXTATTR_CAP|
2936 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2937 encrypt_caps|
2938 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2939 (large_write ?
2940 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2941 break;
2944 case SMB_QUERY_POSIX_FS_INFO:
2946 int rc;
2947 vfs_statvfs_struct svfs;
2949 if (!lp_unix_extensions()) {
2950 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2951 return;
2954 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2956 if (!rc) {
2957 data_len = 56;
2958 SIVAL(pdata,0,svfs.OptimalTransferSize);
2959 SIVAL(pdata,4,svfs.BlockSize);
2960 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2961 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2962 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2963 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2964 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2965 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2966 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2967 #ifdef EOPNOTSUPP
2968 } else if (rc == EOPNOTSUPP) {
2969 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2970 return;
2971 #endif /* EOPNOTSUPP */
2972 } else {
2973 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2974 reply_doserror(req, ERRSRV, ERRerror);
2975 return;
2977 break;
2980 case SMB_QUERY_POSIX_WHOAMI:
2982 uint32_t flags = 0;
2983 uint32_t sid_bytes;
2984 int i;
2986 if (!lp_unix_extensions()) {
2987 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2988 return;
2991 if (max_data_bytes < 40) {
2992 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2993 return;
2996 /* We ARE guest if global_sid_Builtin_Guests is
2997 * in our list of SIDs.
2999 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3000 current_user.nt_user_token)) {
3001 flags |= SMB_WHOAMI_GUEST;
3004 /* We are NOT guest if global_sid_Authenticated_Users
3005 * is in our list of SIDs.
3007 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3008 current_user.nt_user_token)) {
3009 flags &= ~SMB_WHOAMI_GUEST;
3012 /* NOTE: 8 bytes for UID/GID, irrespective of native
3013 * platform size. This matches
3014 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3016 data_len = 4 /* flags */
3017 + 4 /* flag mask */
3018 + 8 /* uid */
3019 + 8 /* gid */
3020 + 4 /* ngroups */
3021 + 4 /* num_sids */
3022 + 4 /* SID bytes */
3023 + 4 /* pad/reserved */
3024 + (current_user.ut.ngroups * 8)
3025 /* groups list */
3026 + (current_user.nt_user_token->num_sids *
3027 SID_MAX_SIZE)
3028 /* SID list */;
3030 SIVAL(pdata, 0, flags);
3031 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3032 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
3033 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
3036 if (data_len >= max_data_bytes) {
3037 /* Potential overflow, skip the GIDs and SIDs. */
3039 SIVAL(pdata, 24, 0); /* num_groups */
3040 SIVAL(pdata, 28, 0); /* num_sids */
3041 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3042 SIVAL(pdata, 36, 0); /* reserved */
3044 data_len = 40;
3045 break;
3048 SIVAL(pdata, 24, current_user.ut.ngroups);
3049 SIVAL(pdata, 28,
3050 current_user.nt_user_token->num_sids);
3052 /* We walk the SID list twice, but this call is fairly
3053 * infrequent, and I don't expect that it's performance
3054 * sensitive -- jpeach
3056 for (i = 0, sid_bytes = 0;
3057 i < current_user.nt_user_token->num_sids; ++i) {
3058 sid_bytes += ndr_size_dom_sid(
3059 &current_user.nt_user_token->user_sids[i], 0);
3062 /* SID list byte count */
3063 SIVAL(pdata, 32, sid_bytes);
3065 /* 4 bytes pad/reserved - must be zero */
3066 SIVAL(pdata, 36, 0);
3067 data_len = 40;
3069 /* GID list */
3070 for (i = 0; i < current_user.ut.ngroups; ++i) {
3071 SBIG_UINT(pdata, data_len,
3072 (SMB_BIG_UINT)current_user.ut.groups[i]);
3073 data_len += 8;
3076 /* SID list */
3077 for (i = 0;
3078 i < current_user.nt_user_token->num_sids; ++i) {
3079 int sid_len = ndr_size_dom_sid(
3080 &current_user.nt_user_token->user_sids[i], 0);
3082 sid_linearize(pdata + data_len, sid_len,
3083 &current_user.nt_user_token->user_sids[i]);
3084 data_len += sid_len;
3087 break;
3090 case SMB_MAC_QUERY_FS_INFO:
3092 * Thursby MAC extension... ONLY on NTFS filesystems
3093 * once we do streams then we don't need this
3095 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3096 data_len = 88;
3097 SIVAL(pdata,84,0x100); /* Don't support mac... */
3098 break;
3100 /* drop through */
3101 default:
3102 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3103 return;
3107 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3108 max_data_bytes);
3110 DEBUG( 4, ( "%s info_level = %d\n",
3111 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
3113 return;
3116 /****************************************************************************
3117 Reply to a TRANS2_SETFSINFO (set filesystem info).
3118 ****************************************************************************/
3120 static void call_trans2setfsinfo(connection_struct *conn,
3121 struct smb_request *req,
3122 char **pparams, int total_params,
3123 char **ppdata, int total_data,
3124 unsigned int max_data_bytes)
3126 char *pdata = *ppdata;
3127 char *params = *pparams;
3128 uint16 info_level;
3130 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3132 /* */
3133 if (total_params < 4) {
3134 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3135 total_params));
3136 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3137 return;
3140 info_level = SVAL(params,2);
3142 if (IS_IPC(conn)) {
3143 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3144 info_level != SMB_SET_CIFS_UNIX_INFO) {
3145 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3146 "info level (0x%x) on IPC$.\n",
3147 (unsigned int)info_level));
3148 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3149 return;
3153 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3154 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3155 DEBUG(0,("call_trans2setfsinfo: encryption required "
3156 "and info level 0x%x sent.\n",
3157 (unsigned int)info_level));
3158 exit_server_cleanly("encryption required "
3159 "on connection");
3160 return;
3164 switch(info_level) {
3165 case SMB_SET_CIFS_UNIX_INFO:
3167 uint16 client_unix_major;
3168 uint16 client_unix_minor;
3169 uint32 client_unix_cap_low;
3170 uint32 client_unix_cap_high;
3172 if (!lp_unix_extensions()) {
3173 reply_nterror(req,
3174 NT_STATUS_INVALID_LEVEL);
3175 return;
3178 /* There should be 12 bytes of capabilities set. */
3179 if (total_data < 8) {
3180 reply_nterror(
3181 req,
3182 NT_STATUS_INVALID_PARAMETER);
3183 return;
3185 client_unix_major = SVAL(pdata,0);
3186 client_unix_minor = SVAL(pdata,2);
3187 client_unix_cap_low = IVAL(pdata,4);
3188 client_unix_cap_high = IVAL(pdata,8);
3189 /* Just print these values for now. */
3190 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3191 cap_low = 0x%x, cap_high = 0x%x\n",
3192 (unsigned int)client_unix_major,
3193 (unsigned int)client_unix_minor,
3194 (unsigned int)client_unix_cap_low,
3195 (unsigned int)client_unix_cap_high ));
3197 /* Here is where we must switch to posix pathname processing... */
3198 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3199 lp_set_posix_pathnames();
3200 mangle_change_to_posix();
3203 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3204 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3205 /* Client that knows how to do posix locks,
3206 * but not posix open/mkdir operations. Set a
3207 * default type for read/write checks. */
3209 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3212 break;
3215 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3217 NTSTATUS status;
3218 size_t param_len = 0;
3219 size_t data_len = total_data;
3221 if (!lp_unix_extensions()) {
3222 reply_nterror(
3223 req,
3224 NT_STATUS_INVALID_LEVEL);
3225 return;
3228 if (lp_smb_encrypt(SNUM(conn)) == false) {
3229 reply_nterror(
3230 req,
3231 NT_STATUS_NOT_SUPPORTED);
3232 return;
3235 DEBUG( 4,("call_trans2setfsinfo: "
3236 "request transport encryption.\n"));
3238 status = srv_request_encryption_setup(conn,
3239 (unsigned char **)ppdata,
3240 &data_len,
3241 (unsigned char **)pparams,
3242 &param_len);
3244 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3245 !NT_STATUS_IS_OK(status)) {
3246 reply_nterror(req, status);
3247 return;
3250 send_trans2_replies(conn, req,
3251 *pparams,
3252 param_len,
3253 *ppdata,
3254 data_len,
3255 max_data_bytes);
3257 if (NT_STATUS_IS_OK(status)) {
3258 /* Server-side transport
3259 * encryption is now *on*. */
3260 status = srv_encryption_start(conn);
3261 if (!NT_STATUS_IS_OK(status)) {
3262 exit_server_cleanly(
3263 "Failure in setting "
3264 "up encrypted transport");
3267 return;
3270 case SMB_FS_QUOTA_INFORMATION:
3272 files_struct *fsp = NULL;
3273 SMB_NTQUOTA_STRUCT quotas;
3275 ZERO_STRUCT(quotas);
3277 /* access check */
3278 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3279 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3280 lp_servicename(SNUM(conn)),
3281 conn->server_info->unix_name));
3282 reply_doserror(req, ERRSRV, ERRaccess);
3283 return;
3286 /* note: normaly there're 48 bytes,
3287 * but we didn't use the last 6 bytes for now
3288 * --metze
3290 fsp = file_fsp(SVAL(params,0));
3291 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3292 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3293 reply_nterror(
3294 req, NT_STATUS_INVALID_HANDLE);
3295 return;
3298 if (total_data < 42) {
3299 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3300 total_data));
3301 reply_nterror(
3302 req,
3303 NT_STATUS_INVALID_PARAMETER);
3304 return;
3307 /* unknown_1 24 NULL bytes in pdata*/
3309 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3310 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3311 #ifdef LARGE_SMB_OFF_T
3312 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3313 #else /* LARGE_SMB_OFF_T */
3314 if ((IVAL(pdata,28) != 0)&&
3315 ((quotas.softlim != 0xFFFFFFFF)||
3316 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3317 /* more than 32 bits? */
3318 reply_nterror(
3319 req,
3320 NT_STATUS_INVALID_PARAMETER);
3321 return;
3323 #endif /* LARGE_SMB_OFF_T */
3325 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3326 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3327 #ifdef LARGE_SMB_OFF_T
3328 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3329 #else /* LARGE_SMB_OFF_T */
3330 if ((IVAL(pdata,36) != 0)&&
3331 ((quotas.hardlim != 0xFFFFFFFF)||
3332 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3333 /* more than 32 bits? */
3334 reply_nterror(
3335 req,
3336 NT_STATUS_INVALID_PARAMETER);
3337 return;
3339 #endif /* LARGE_SMB_OFF_T */
3341 /* quota_flags 2 bytes **/
3342 quotas.qflags = SVAL(pdata,40);
3344 /* unknown_2 6 NULL bytes follow*/
3346 /* now set the quotas */
3347 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3348 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3349 reply_doserror(req, ERRSRV, ERRerror);
3350 return;
3353 break;
3355 default:
3356 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3357 info_level));
3358 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3359 return;
3360 break;
3364 * sending this reply works fine,
3365 * but I'm not sure it's the same
3366 * like windows do...
3367 * --metze
3369 reply_outbuf(req, 10, 0);
3372 #if defined(HAVE_POSIX_ACLS)
3373 /****************************************************************************
3374 Utility function to count the number of entries in a POSIX acl.
3375 ****************************************************************************/
3377 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3379 unsigned int ace_count = 0;
3380 int entry_id = SMB_ACL_FIRST_ENTRY;
3381 SMB_ACL_ENTRY_T entry;
3383 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3384 /* get_next... */
3385 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3386 entry_id = SMB_ACL_NEXT_ENTRY;
3388 ace_count++;
3390 return ace_count;
3393 /****************************************************************************
3394 Utility function to marshall a POSIX acl into wire format.
3395 ****************************************************************************/
3397 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3399 int entry_id = SMB_ACL_FIRST_ENTRY;
3400 SMB_ACL_ENTRY_T entry;
3402 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3403 SMB_ACL_TAG_T tagtype;
3404 SMB_ACL_PERMSET_T permset;
3405 unsigned char perms = 0;
3406 unsigned int own_grp;
3408 /* get_next... */
3409 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3410 entry_id = SMB_ACL_NEXT_ENTRY;
3413 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3414 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3415 return False;
3418 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3419 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3420 return False;
3423 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3424 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3425 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3427 SCVAL(pdata,1,perms);
3429 switch (tagtype) {
3430 case SMB_ACL_USER_OBJ:
3431 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3432 own_grp = (unsigned int)pst->st_uid;
3433 SIVAL(pdata,2,own_grp);
3434 SIVAL(pdata,6,0);
3435 break;
3436 case SMB_ACL_USER:
3438 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3439 if (!puid) {
3440 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3441 return False;
3443 own_grp = (unsigned int)*puid;
3444 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3445 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3446 SIVAL(pdata,2,own_grp);
3447 SIVAL(pdata,6,0);
3448 break;
3450 case SMB_ACL_GROUP_OBJ:
3451 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3452 own_grp = (unsigned int)pst->st_gid;
3453 SIVAL(pdata,2,own_grp);
3454 SIVAL(pdata,6,0);
3455 break;
3456 case SMB_ACL_GROUP:
3458 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3459 if (!pgid) {
3460 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3461 return False;
3463 own_grp = (unsigned int)*pgid;
3464 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3465 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3466 SIVAL(pdata,2,own_grp);
3467 SIVAL(pdata,6,0);
3468 break;
3470 case SMB_ACL_MASK:
3471 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3472 SIVAL(pdata,2,0xFFFFFFFF);
3473 SIVAL(pdata,6,0xFFFFFFFF);
3474 break;
3475 case SMB_ACL_OTHER:
3476 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3477 SIVAL(pdata,2,0xFFFFFFFF);
3478 SIVAL(pdata,6,0xFFFFFFFF);
3479 break;
3480 default:
3481 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3482 return False;
3484 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3487 return True;
3489 #endif
3491 /****************************************************************************
3492 Store the FILE_UNIX_BASIC info.
3493 ****************************************************************************/
3495 static char *store_file_unix_basic(connection_struct *conn,
3496 char *pdata,
3497 files_struct *fsp,
3498 const SMB_STRUCT_STAT *psbuf)
3500 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3501 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3503 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3504 pdata += 8;
3506 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3507 pdata += 8;
3509 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3510 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3511 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3512 pdata += 24;
3514 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3515 SIVAL(pdata,4,0);
3516 pdata += 8;
3518 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3519 SIVAL(pdata,4,0);
3520 pdata += 8;
3522 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3523 pdata += 4;
3525 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3526 SIVAL(pdata,4,0);
3527 pdata += 8;
3529 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3530 SIVAL(pdata,4,0);
3531 pdata += 8;
3533 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3534 pdata += 8;
3536 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3537 SIVAL(pdata,4,0);
3538 pdata += 8;
3540 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3541 SIVAL(pdata,4,0);
3542 pdata += 8;
3544 return pdata;
3547 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3548 * the chflags(2) (or equivalent) flags.
3550 * XXX: this really should be behind the VFS interface. To do this, we would
3551 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3552 * Each VFS module could then implement its own mapping as appropriate for the
3553 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3555 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3556 info2_flags_map[] =
3558 #ifdef UF_NODUMP
3559 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3560 #endif
3562 #ifdef UF_IMMUTABLE
3563 { UF_IMMUTABLE, EXT_IMMUTABLE },
3564 #endif
3566 #ifdef UF_APPEND
3567 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3568 #endif
3570 #ifdef UF_HIDDEN
3571 { UF_HIDDEN, EXT_HIDDEN },
3572 #endif
3574 /* Do not remove. We need to guarantee that this array has at least one
3575 * entry to build on HP-UX.
3577 { 0, 0 }
3581 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3582 uint32 *smb_fflags, uint32 *smb_fmask)
3584 #ifdef HAVE_STAT_ST_FLAGS
3585 int i;
3587 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3588 *smb_fmask |= info2_flags_map[i].smb_fflag;
3589 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3590 *smb_fflags |= info2_flags_map[i].smb_fflag;
3593 #endif /* HAVE_STAT_ST_FLAGS */
3596 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3597 const uint32 smb_fflags,
3598 const uint32 smb_fmask,
3599 int *stat_fflags)
3601 #ifdef HAVE_STAT_ST_FLAGS
3602 uint32 max_fmask = 0;
3603 int i;
3605 *stat_fflags = psbuf->st_flags;
3607 /* For each flags requested in smb_fmask, check the state of the
3608 * corresponding flag in smb_fflags and set or clear the matching
3609 * stat flag.
3612 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3613 max_fmask |= info2_flags_map[i].smb_fflag;
3614 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3615 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3616 *stat_fflags |= info2_flags_map[i].stat_fflag;
3617 } else {
3618 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3623 /* If smb_fmask is asking to set any bits that are not supported by
3624 * our flag mappings, we should fail.
3626 if ((smb_fmask & max_fmask) != smb_fmask) {
3627 return False;
3630 return True;
3631 #else
3632 return False;
3633 #endif /* HAVE_STAT_ST_FLAGS */
3637 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3638 * of file flags and birth (create) time.
3640 static char *store_file_unix_basic_info2(connection_struct *conn,
3641 char *pdata,
3642 files_struct *fsp,
3643 const SMB_STRUCT_STAT *psbuf)
3645 uint32 file_flags = 0;
3646 uint32 flags_mask = 0;
3648 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3650 /* Create (birth) time 64 bit */
3651 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3652 pdata += 8;
3654 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3655 SIVAL(pdata, 0, file_flags); /* flags */
3656 SIVAL(pdata, 4, flags_mask); /* mask */
3657 pdata += 8;
3659 return pdata;
3662 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3663 const struct stream_struct *streams,
3664 char *data,
3665 unsigned int max_data_bytes,
3666 unsigned int *data_size)
3668 unsigned int i;
3669 unsigned int ofs = 0;
3671 for (i=0; i<num_streams; i++) {
3672 unsigned int next_offset;
3673 size_t namelen;
3674 smb_ucs2_t *namebuf;
3676 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3677 streams[i].name, &namelen) ||
3678 namelen <= 2)
3680 return NT_STATUS_INVALID_PARAMETER;
3684 * name_buf is now null-terminated, we need to marshall as not
3685 * terminated
3688 namelen -= 2;
3690 if (ofs + 24 + namelen > max_data_bytes) {
3691 TALLOC_FREE(namebuf);
3692 return NT_STATUS_BUFFER_TOO_SMALL;
3695 SIVAL(data, ofs+4, namelen);
3696 SOFF_T(data, ofs+8, streams[i].size);
3697 SOFF_T(data, ofs+16, streams[i].alloc_size);
3698 memcpy(data+ofs+24, namebuf, namelen);
3699 TALLOC_FREE(namebuf);
3701 next_offset = ofs + 24 + namelen;
3703 if (i == num_streams-1) {
3704 SIVAL(data, ofs, 0);
3706 else {
3707 unsigned int align = ndr_align_size(next_offset, 8);
3709 if (next_offset + align > max_data_bytes) {
3710 return NT_STATUS_BUFFER_TOO_SMALL;
3713 memset(data+next_offset, 0, align);
3714 next_offset += align;
3716 SIVAL(data, ofs, next_offset - ofs);
3717 ofs = next_offset;
3720 ofs = next_offset;
3723 *data_size = ofs;
3725 return NT_STATUS_OK;
3728 /****************************************************************************
3729 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3730 ****************************************************************************/
3732 static void call_trans2qpipeinfo(connection_struct *conn,
3733 struct smb_request *req,
3734 unsigned int tran_call,
3735 char **pparams, int total_params,
3736 char **ppdata, int total_data,
3737 unsigned int max_data_bytes)
3739 char *params = *pparams;
3740 char *pdata = *ppdata;
3741 unsigned int data_size = 0;
3742 unsigned int param_size = 2;
3743 uint16 info_level;
3744 smb_np_struct *p_pipe = NULL;
3746 if (!params) {
3747 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3748 return;
3751 if (total_params < 4) {
3752 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3753 return;
3756 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3757 if (p_pipe == NULL) {
3758 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3759 return;
3762 info_level = SVAL(params,2);
3764 *pparams = (char *)SMB_REALLOC(*pparams,2);
3765 if (*pparams == NULL) {
3766 reply_nterror(req, NT_STATUS_NO_MEMORY);
3767 return;
3769 params = *pparams;
3770 SSVAL(params,0,0);
3771 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3772 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3773 if (*ppdata == NULL ) {
3774 reply_nterror(req, NT_STATUS_NO_MEMORY);
3775 return;
3777 pdata = *ppdata;
3779 switch (info_level) {
3780 case SMB_FILE_STANDARD_INFORMATION:
3781 memset(pdata,0,24);
3782 SOFF_T(pdata,0,4096LL);
3783 SIVAL(pdata,16,1);
3784 SIVAL(pdata,20,1);
3785 data_size = 24;
3786 break;
3788 default:
3789 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3790 return;
3793 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3794 max_data_bytes);
3796 return;
3799 /****************************************************************************
3800 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3801 file name or file id).
3802 ****************************************************************************/
3804 static void call_trans2qfilepathinfo(connection_struct *conn,
3805 struct smb_request *req,
3806 unsigned int tran_call,
3807 char **pparams, int total_params,
3808 char **ppdata, int total_data,
3809 unsigned int max_data_bytes)
3811 char *params = *pparams;
3812 char *pdata = *ppdata;
3813 char *dstart, *dend;
3814 uint16 info_level;
3815 int mode=0;
3816 int nlink;
3817 SMB_OFF_T file_size=0;
3818 SMB_BIG_UINT allocation_size=0;
3819 unsigned int data_size = 0;
3820 unsigned int param_size = 2;
3821 SMB_STRUCT_STAT sbuf;
3822 char *dos_fname = NULL;
3823 char *fname = NULL;
3824 char *fullpathname;
3825 char *base_name;
3826 char *p;
3827 SMB_OFF_T pos = 0;
3828 bool delete_pending = False;
3829 int len;
3830 time_t create_time, mtime, atime;
3831 struct timespec create_time_ts, mtime_ts, atime_ts;
3832 struct timespec write_time_ts;
3833 files_struct *fsp = NULL;
3834 struct file_id fileid;
3835 struct ea_list *ea_list = NULL;
3836 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3837 char *lock_data = NULL;
3838 bool ms_dfs_link = false;
3839 TALLOC_CTX *ctx = talloc_tos();
3841 if (!params) {
3842 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3843 return;
3846 ZERO_STRUCT(sbuf);
3847 ZERO_STRUCT(write_time_ts);
3849 if (tran_call == TRANSACT2_QFILEINFO) {
3850 if (total_params < 4) {
3851 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3852 return;
3855 if (IS_IPC(conn)) {
3856 call_trans2qpipeinfo(conn, req, tran_call,
3857 pparams, total_params,
3858 ppdata, total_data,
3859 max_data_bytes);
3860 return;
3863 fsp = file_fsp(SVAL(params,0));
3864 info_level = SVAL(params,2);
3866 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3868 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3869 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3870 return;
3873 /* Initial check for valid fsp ptr. */
3874 if (!check_fsp_open(conn, req, fsp, &current_user)) {
3875 return;
3878 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3879 if (!fname) {
3880 reply_nterror(req, NT_STATUS_NO_MEMORY);
3881 return;
3884 if(fsp->fake_file_handle) {
3886 * This is actually for the QUOTA_FAKE_FILE --metze
3889 /* We know this name is ok, it's already passed the checks. */
3891 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3893 * This is actually a QFILEINFO on a directory
3894 * handle (returned from an NT SMB). NT5.0 seems
3895 * to do this call. JRA.
3898 if (INFO_LEVEL_IS_UNIX(info_level)) {
3899 /* Always do lstat for UNIX calls. */
3900 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3901 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3902 reply_unixerror(req,ERRDOS,ERRbadpath);
3903 return;
3905 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3906 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3907 reply_unixerror(req, ERRDOS, ERRbadpath);
3908 return;
3911 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3912 get_file_infos(fileid, &delete_pending, &write_time_ts);
3913 } else {
3915 * Original code - this is an open file.
3917 if (!check_fsp(conn, req, fsp, &current_user)) {
3918 return;
3921 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3922 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3923 reply_unixerror(req, ERRDOS, ERRbadfid);
3924 return;
3926 pos = fsp->fh->position_information;
3927 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3928 get_file_infos(fileid, &delete_pending, &write_time_ts);
3929 access_mask = fsp->access_mask;
3932 } else {
3933 NTSTATUS status = NT_STATUS_OK;
3935 /* qpathinfo */
3936 if (total_params < 7) {
3937 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3938 return;
3941 info_level = SVAL(params,0);
3943 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3945 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3946 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3947 return;
3950 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3951 total_params - 6,
3952 STR_TERMINATE, &status);
3953 if (!NT_STATUS_IS_OK(status)) {
3954 reply_nterror(req, status);
3955 return;
3958 status = resolve_dfspath(ctx,
3959 conn,
3960 req->flags2 & FLAGS2_DFS_PATHNAMES,
3961 fname,
3962 &fname);
3963 if (!NT_STATUS_IS_OK(status)) {
3964 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3965 reply_botherror(req,
3966 NT_STATUS_PATH_NOT_COVERED,
3967 ERRSRV, ERRbadpath);
3969 reply_nterror(req, status);
3970 return;
3973 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3974 if (!NT_STATUS_IS_OK(status)) {
3975 reply_nterror(req, status);
3976 return;
3978 status = check_name(conn, fname);
3979 if (!NT_STATUS_IS_OK(status)) {
3980 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3981 reply_nterror(req, status);
3982 return;
3985 if (INFO_LEVEL_IS_UNIX(info_level)) {
3986 /* Always do lstat for UNIX calls. */
3987 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3988 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3989 reply_unixerror(req, ERRDOS, ERRbadpath);
3990 return;
3993 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3994 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
3996 if (!ms_dfs_link) {
3997 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3998 reply_unixerror(req, ERRDOS, ERRbadpath);
3999 return;
4003 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4004 get_file_infos(fileid, &delete_pending, &write_time_ts);
4005 if (delete_pending) {
4006 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4007 return;
4011 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4012 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4013 return;
4016 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4017 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4019 p = strrchr_m(fname,'/');
4020 if (!p)
4021 base_name = fname;
4022 else
4023 base_name = p+1;
4025 if (ms_dfs_link) {
4026 mode = dos_mode_msdfs(conn,fname,&sbuf);
4027 } else {
4028 mode = dos_mode(conn,fname,&sbuf);
4030 if (!mode)
4031 mode = FILE_ATTRIBUTE_NORMAL;
4033 nlink = sbuf.st_nlink;
4035 if (nlink && (mode&aDIR)) {
4036 nlink = 1;
4039 if ((nlink > 0) && delete_pending) {
4040 nlink -= 1;
4043 fullpathname = fname;
4044 if (!(mode & aDIR))
4045 file_size = get_file_size(sbuf);
4047 /* Pull out any data sent here before we realloc. */
4048 switch (info_level) {
4049 case SMB_INFO_QUERY_EAS_FROM_LIST:
4051 /* Pull any EA list from the data portion. */
4052 uint32 ea_size;
4054 if (total_data < 4) {
4055 reply_nterror(
4056 req, NT_STATUS_INVALID_PARAMETER);
4057 return;
4059 ea_size = IVAL(pdata,0);
4061 if (total_data > 0 && ea_size != total_data) {
4062 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4063 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4064 reply_nterror(
4065 req, NT_STATUS_INVALID_PARAMETER);
4066 return;
4069 if (!lp_ea_support(SNUM(conn))) {
4070 reply_doserror(req, ERRDOS,
4071 ERReasnotsupported);
4072 return;
4075 /* Pull out the list of names. */
4076 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4077 if (!ea_list) {
4078 reply_nterror(
4079 req, NT_STATUS_INVALID_PARAMETER);
4080 return;
4082 break;
4085 case SMB_QUERY_POSIX_LOCK:
4087 if (fsp == NULL || fsp->fh->fd == -1) {
4088 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4089 return;
4092 if (total_data != POSIX_LOCK_DATA_SIZE) {
4093 reply_nterror(
4094 req, NT_STATUS_INVALID_PARAMETER);
4095 return;
4098 /* Copy the lock range data. */
4099 lock_data = (char *)TALLOC_MEMDUP(
4100 ctx, pdata, total_data);
4101 if (!lock_data) {
4102 reply_nterror(req, NT_STATUS_NO_MEMORY);
4103 return;
4106 default:
4107 break;
4110 *pparams = (char *)SMB_REALLOC(*pparams,2);
4111 if (*pparams == NULL) {
4112 reply_nterror(req, NT_STATUS_NO_MEMORY);
4113 return;
4115 params = *pparams;
4116 SSVAL(params,0,0);
4117 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4118 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4119 if (*ppdata == NULL ) {
4120 reply_nterror(req, NT_STATUS_NO_MEMORY);
4121 return;
4123 pdata = *ppdata;
4124 dstart = pdata;
4125 dend = dstart + data_size - 1;
4127 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4128 mtime_ts = get_mtimespec(&sbuf);
4129 atime_ts = get_atimespec(&sbuf);
4131 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4133 if (!fsp) {
4134 /* Do we have this path open ? */
4135 files_struct *fsp1;
4136 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4137 fsp1 = file_find_di_first(fileid);
4138 if (fsp1 && fsp1->initial_allocation_size) {
4139 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4143 if (!null_timespec(write_time_ts)) {
4144 mtime_ts = write_time_ts;
4147 if (lp_dos_filetime_resolution(SNUM(conn))) {
4148 dos_filetime_timespec(&create_time_ts);
4149 dos_filetime_timespec(&mtime_ts);
4150 dos_filetime_timespec(&atime_ts);
4153 create_time = convert_timespec_to_time_t(create_time_ts);
4154 mtime = convert_timespec_to_time_t(mtime_ts);
4155 atime = convert_timespec_to_time_t(atime_ts);
4157 /* NT expects the name to be in an exact form of the *full*
4158 filename. See the trans2 torture test */
4159 if (ISDOT(base_name)) {
4160 dos_fname = talloc_strdup(ctx, "\\");
4161 if (!dos_fname) {
4162 reply_nterror(req, NT_STATUS_NO_MEMORY);
4163 return;
4165 } else {
4166 dos_fname = talloc_asprintf(ctx,
4167 "\\%s",
4168 fname);
4169 if (!dos_fname) {
4170 reply_nterror(req, NT_STATUS_NO_MEMORY);
4171 return;
4173 string_replace(dos_fname, '/', '\\');
4176 switch (info_level) {
4177 case SMB_INFO_STANDARD:
4178 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4179 data_size = 22;
4180 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4181 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4182 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4183 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4184 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4185 SSVAL(pdata,l1_attrFile,mode);
4186 break;
4188 case SMB_INFO_QUERY_EA_SIZE:
4190 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4191 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4192 data_size = 26;
4193 srv_put_dos_date2(pdata,0,create_time);
4194 srv_put_dos_date2(pdata,4,atime);
4195 srv_put_dos_date2(pdata,8,mtime); /* write time */
4196 SIVAL(pdata,12,(uint32)file_size);
4197 SIVAL(pdata,16,(uint32)allocation_size);
4198 SSVAL(pdata,20,mode);
4199 SIVAL(pdata,22,ea_size);
4200 break;
4203 case SMB_INFO_IS_NAME_VALID:
4204 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4205 if (tran_call == TRANSACT2_QFILEINFO) {
4206 /* os/2 needs this ? really ?*/
4207 reply_doserror(req, ERRDOS, ERRbadfunc);
4208 return;
4210 data_size = 0;
4211 param_size = 0;
4212 break;
4214 case SMB_INFO_QUERY_EAS_FROM_LIST:
4216 size_t total_ea_len = 0;
4217 struct ea_list *ea_file_list = NULL;
4219 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4221 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4222 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4224 if (!ea_list || (total_ea_len > data_size)) {
4225 data_size = 4;
4226 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4227 break;
4230 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4231 break;
4234 case SMB_INFO_QUERY_ALL_EAS:
4236 /* We have data_size bytes to put EA's into. */
4237 size_t total_ea_len = 0;
4239 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4241 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4242 if (!ea_list || (total_ea_len > data_size)) {
4243 data_size = 4;
4244 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4245 break;
4248 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4249 break;
4252 case SMB_FILE_BASIC_INFORMATION:
4253 case SMB_QUERY_FILE_BASIC_INFO:
4255 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4256 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4257 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4258 } else {
4259 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4260 data_size = 40;
4261 SIVAL(pdata,36,0);
4263 put_long_date_timespec(pdata,create_time_ts);
4264 put_long_date_timespec(pdata+8,atime_ts);
4265 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4266 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4267 SIVAL(pdata,32,mode);
4269 DEBUG(5,("SMB_QFBI - "));
4270 DEBUG(5,("create: %s ", ctime(&create_time)));
4271 DEBUG(5,("access: %s ", ctime(&atime)));
4272 DEBUG(5,("write: %s ", ctime(&mtime)));
4273 DEBUG(5,("change: %s ", ctime(&mtime)));
4274 DEBUG(5,("mode: %x\n", mode));
4275 break;
4277 case SMB_FILE_STANDARD_INFORMATION:
4278 case SMB_QUERY_FILE_STANDARD_INFO:
4280 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4281 data_size = 24;
4282 SOFF_T(pdata,0,allocation_size);
4283 SOFF_T(pdata,8,file_size);
4284 SIVAL(pdata,16,nlink);
4285 SCVAL(pdata,20,delete_pending?1:0);
4286 SCVAL(pdata,21,(mode&aDIR)?1:0);
4287 SSVAL(pdata,22,0); /* Padding. */
4288 break;
4290 case SMB_FILE_EA_INFORMATION:
4291 case SMB_QUERY_FILE_EA_INFO:
4293 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4294 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4295 data_size = 4;
4296 SIVAL(pdata,0,ea_size);
4297 break;
4300 /* Get the 8.3 name - used if NT SMB was negotiated. */
4301 case SMB_QUERY_FILE_ALT_NAME_INFO:
4302 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4304 char mangled_name[13];
4305 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4306 if (!name_to_8_3(base_name,mangled_name,
4307 True,conn->params)) {
4308 reply_nterror(
4309 req,
4310 NT_STATUS_NO_MEMORY);
4312 len = srvstr_push(dstart, req->flags2,
4313 pdata+4, mangled_name,
4314 PTR_DIFF(dend, pdata+4),
4315 STR_UNICODE);
4316 data_size = 4 + len;
4317 SIVAL(pdata,0,len);
4318 break;
4321 case SMB_QUERY_FILE_NAME_INFO:
4323 this must be *exactly* right for ACLs on mapped drives to work
4325 len = srvstr_push(dstart, req->flags2,
4326 pdata+4, dos_fname,
4327 PTR_DIFF(dend, pdata+4),
4328 STR_UNICODE);
4329 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4330 data_size = 4 + len;
4331 SIVAL(pdata,0,len);
4332 break;
4334 case SMB_FILE_ALLOCATION_INFORMATION:
4335 case SMB_QUERY_FILE_ALLOCATION_INFO:
4336 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4337 data_size = 8;
4338 SOFF_T(pdata,0,allocation_size);
4339 break;
4341 case SMB_FILE_END_OF_FILE_INFORMATION:
4342 case SMB_QUERY_FILE_END_OF_FILEINFO:
4343 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4344 data_size = 8;
4345 SOFF_T(pdata,0,file_size);
4346 break;
4348 case SMB_QUERY_FILE_ALL_INFO:
4349 case SMB_FILE_ALL_INFORMATION:
4351 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4352 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4353 put_long_date_timespec(pdata,create_time_ts);
4354 put_long_date_timespec(pdata+8,atime_ts);
4355 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4356 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4357 SIVAL(pdata,32,mode);
4358 SIVAL(pdata,36,0); /* padding. */
4359 pdata += 40;
4360 SOFF_T(pdata,0,allocation_size);
4361 SOFF_T(pdata,8,file_size);
4362 SIVAL(pdata,16,nlink);
4363 SCVAL(pdata,20,delete_pending);
4364 SCVAL(pdata,21,(mode&aDIR)?1:0);
4365 SSVAL(pdata,22,0);
4366 pdata += 24;
4367 SIVAL(pdata,0,ea_size);
4368 pdata += 4; /* EA info */
4369 len = srvstr_push(dstart, req->flags2,
4370 pdata+4, dos_fname,
4371 PTR_DIFF(dend, pdata+4),
4372 STR_UNICODE);
4373 SIVAL(pdata,0,len);
4374 pdata += 4 + len;
4375 data_size = PTR_DIFF(pdata,(*ppdata));
4376 break;
4378 case SMB_FILE_INTERNAL_INFORMATION:
4379 /* This should be an index number - looks like
4380 dev/ino to me :-)
4382 I think this causes us to fail the IFSKIT
4383 BasicFileInformationTest. -tpot */
4385 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4386 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4387 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4388 data_size = 8;
4389 break;
4391 case SMB_FILE_ACCESS_INFORMATION:
4392 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4393 SIVAL(pdata,0,access_mask);
4394 data_size = 4;
4395 break;
4397 case SMB_FILE_NAME_INFORMATION:
4398 /* Pathname with leading '\'. */
4400 size_t byte_len;
4401 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4402 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4403 SIVAL(pdata,0,byte_len);
4404 data_size = 4 + byte_len;
4405 break;
4408 case SMB_FILE_DISPOSITION_INFORMATION:
4409 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4410 data_size = 1;
4411 SCVAL(pdata,0,delete_pending);
4412 break;
4414 case SMB_FILE_POSITION_INFORMATION:
4415 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4416 data_size = 8;
4417 SOFF_T(pdata,0,pos);
4418 break;
4420 case SMB_FILE_MODE_INFORMATION:
4421 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4422 SIVAL(pdata,0,mode);
4423 data_size = 4;
4424 break;
4426 case SMB_FILE_ALIGNMENT_INFORMATION:
4427 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4428 SIVAL(pdata,0,0); /* No alignment needed. */
4429 data_size = 4;
4430 break;
4433 * NT4 server just returns "invalid query" to this - if we try
4434 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4435 * want this. JRA.
4437 /* The first statement above is false - verified using Thursby
4438 * client against NT4 -- gcolley.
4440 case SMB_QUERY_FILE_STREAM_INFO:
4441 case SMB_FILE_STREAM_INFORMATION: {
4442 unsigned int num_streams;
4443 struct stream_struct *streams;
4444 NTSTATUS status;
4446 DEBUG(10,("call_trans2qfilepathinfo: "
4447 "SMB_FILE_STREAM_INFORMATION\n"));
4449 status = SMB_VFS_STREAMINFO(
4450 conn, fsp, fname, talloc_tos(),
4451 &num_streams, &streams);
4453 if (!NT_STATUS_IS_OK(status)) {
4454 DEBUG(10, ("could not get stream info: %s\n",
4455 nt_errstr(status)));
4456 reply_nterror(req, status);
4457 return;
4460 status = marshall_stream_info(num_streams, streams,
4461 pdata, max_data_bytes,
4462 &data_size);
4464 if (!NT_STATUS_IS_OK(status)) {
4465 DEBUG(10, ("marshall_stream_info failed: %s\n",
4466 nt_errstr(status)));
4467 reply_nterror(req, status);
4468 return;
4471 TALLOC_FREE(streams);
4473 break;
4475 case SMB_QUERY_COMPRESSION_INFO:
4476 case SMB_FILE_COMPRESSION_INFORMATION:
4477 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4478 SOFF_T(pdata,0,file_size);
4479 SIVAL(pdata,8,0); /* ??? */
4480 SIVAL(pdata,12,0); /* ??? */
4481 data_size = 16;
4482 break;
4484 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4485 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4486 put_long_date_timespec(pdata,create_time_ts);
4487 put_long_date_timespec(pdata+8,atime_ts);
4488 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4489 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4490 SOFF_T(pdata,32,allocation_size);
4491 SOFF_T(pdata,40,file_size);
4492 SIVAL(pdata,48,mode);
4493 SIVAL(pdata,52,0); /* ??? */
4494 data_size = 56;
4495 break;
4497 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4498 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4499 SIVAL(pdata,0,mode);
4500 SIVAL(pdata,4,0);
4501 data_size = 8;
4502 break;
4505 * CIFS UNIX Extensions.
4508 case SMB_QUERY_FILE_UNIX_BASIC:
4510 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4511 data_size = PTR_DIFF(pdata,(*ppdata));
4514 int i;
4515 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4517 for (i=0; i<100; i++)
4518 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4519 DEBUG(4,("\n"));
4522 break;
4524 case SMB_QUERY_FILE_UNIX_INFO2:
4526 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4527 data_size = PTR_DIFF(pdata,(*ppdata));
4530 int i;
4531 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4533 for (i=0; i<100; i++)
4534 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4535 DEBUG(4,("\n"));
4538 break;
4540 case SMB_QUERY_FILE_UNIX_LINK:
4542 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4544 if (!buffer) {
4545 reply_nterror(req, NT_STATUS_NO_MEMORY);
4546 return;
4549 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4550 #ifdef S_ISLNK
4551 if(!S_ISLNK(sbuf.st_mode)) {
4552 reply_unixerror(req, ERRSRV,
4553 ERRbadlink);
4554 return;
4556 #else
4557 reply_unixerror(req, ERRDOS, ERRbadlink);
4558 return;
4559 #endif
4560 len = SMB_VFS_READLINK(conn,fullpathname,
4561 buffer, PATH_MAX);
4562 if (len == -1) {
4563 reply_unixerror(req, ERRDOS,
4564 ERRnoaccess);
4565 return;
4567 buffer[len] = 0;
4568 len = srvstr_push(dstart, req->flags2,
4569 pdata, buffer,
4570 PTR_DIFF(dend, pdata),
4571 STR_TERMINATE);
4572 pdata += len;
4573 data_size = PTR_DIFF(pdata,(*ppdata));
4575 break;
4578 #if defined(HAVE_POSIX_ACLS)
4579 case SMB_QUERY_POSIX_ACL:
4581 SMB_ACL_T file_acl = NULL;
4582 SMB_ACL_T def_acl = NULL;
4583 uint16 num_file_acls = 0;
4584 uint16 num_def_acls = 0;
4586 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4587 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4588 } else {
4589 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4592 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4593 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4594 fname ));
4595 reply_nterror(
4596 req,
4597 NT_STATUS_NOT_IMPLEMENTED);
4598 return;
4601 if (S_ISDIR(sbuf.st_mode)) {
4602 if (fsp && fsp->is_directory) {
4603 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4604 } else {
4605 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4607 def_acl = free_empty_sys_acl(conn, def_acl);
4610 num_file_acls = count_acl_entries(conn, file_acl);
4611 num_def_acls = count_acl_entries(conn, def_acl);
4613 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4614 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4615 data_size,
4616 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4617 SMB_POSIX_ACL_HEADER_SIZE) ));
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 reply_nterror(
4625 req,
4626 NT_STATUS_BUFFER_TOO_SMALL);
4627 return;
4630 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4631 SSVAL(pdata,2,num_file_acls);
4632 SSVAL(pdata,4,num_def_acls);
4633 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4634 if (file_acl) {
4635 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4637 if (def_acl) {
4638 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4640 reply_nterror(
4641 req, NT_STATUS_INTERNAL_ERROR);
4642 return;
4644 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4645 if (file_acl) {
4646 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4648 if (def_acl) {
4649 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4651 reply_nterror(
4652 req,
4653 NT_STATUS_INTERNAL_ERROR);
4654 return;
4657 if (file_acl) {
4658 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4660 if (def_acl) {
4661 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4663 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4664 break;
4666 #endif
4669 case SMB_QUERY_POSIX_LOCK:
4671 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4672 SMB_BIG_UINT count;
4673 SMB_BIG_UINT offset;
4674 uint32 lock_pid;
4675 enum brl_type lock_type;
4677 if (total_data != POSIX_LOCK_DATA_SIZE) {
4678 reply_nterror(
4679 req, NT_STATUS_INVALID_PARAMETER);
4680 return;
4683 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4684 case POSIX_LOCK_TYPE_READ:
4685 lock_type = READ_LOCK;
4686 break;
4687 case POSIX_LOCK_TYPE_WRITE:
4688 lock_type = WRITE_LOCK;
4689 break;
4690 case POSIX_LOCK_TYPE_UNLOCK:
4691 default:
4692 /* There's no point in asking for an unlock... */
4693 reply_nterror(
4694 req,
4695 NT_STATUS_INVALID_PARAMETER);
4696 return;
4699 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4700 #if defined(HAVE_LONGLONG)
4701 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4702 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4703 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4704 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4705 #else /* HAVE_LONGLONG */
4706 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4707 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4708 #endif /* HAVE_LONGLONG */
4710 status = query_lock(fsp,
4711 &lock_pid,
4712 &count,
4713 &offset,
4714 &lock_type,
4715 POSIX_LOCK);
4717 if (ERROR_WAS_LOCK_DENIED(status)) {
4718 /* Here we need to report who has it locked... */
4719 data_size = POSIX_LOCK_DATA_SIZE;
4721 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4722 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4723 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4724 #if defined(HAVE_LONGLONG)
4725 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4726 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4727 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4728 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4729 #else /* HAVE_LONGLONG */
4730 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4731 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4732 #endif /* HAVE_LONGLONG */
4734 } else if (NT_STATUS_IS_OK(status)) {
4735 /* For success we just return a copy of what we sent
4736 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4737 data_size = POSIX_LOCK_DATA_SIZE;
4738 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4739 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4740 } else {
4741 reply_nterror(req, status);
4742 return;
4744 break;
4747 default:
4748 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4749 return;
4752 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4753 max_data_bytes);
4755 return;
4758 /****************************************************************************
4759 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4760 code.
4761 ****************************************************************************/
4763 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4764 connection_struct *conn,
4765 const char *oldname_in,
4766 const char *newname_in)
4768 SMB_STRUCT_STAT sbuf1, sbuf2;
4769 char *last_component_oldname = NULL;
4770 char *last_component_newname = NULL;
4771 char *oldname = NULL;
4772 char *newname = NULL;
4773 NTSTATUS status = NT_STATUS_OK;
4775 ZERO_STRUCT(sbuf1);
4776 ZERO_STRUCT(sbuf2);
4778 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4779 &last_component_oldname, &sbuf1);
4780 if (!NT_STATUS_IS_OK(status)) {
4781 return status;
4784 status = check_name(conn, oldname);
4785 if (!NT_STATUS_IS_OK(status)) {
4786 return status;
4789 /* source must already exist. */
4790 if (!VALID_STAT(sbuf1)) {
4791 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4794 status = unix_convert(ctx, conn, newname_in, False, &newname,
4795 &last_component_newname, &sbuf2);
4796 if (!NT_STATUS_IS_OK(status)) {
4797 return status;
4800 status = check_name(conn, newname);
4801 if (!NT_STATUS_IS_OK(status)) {
4802 return status;
4805 /* Disallow if newname already exists. */
4806 if (VALID_STAT(sbuf2)) {
4807 return NT_STATUS_OBJECT_NAME_COLLISION;
4810 /* No links from a directory. */
4811 if (S_ISDIR(sbuf1.st_mode)) {
4812 return NT_STATUS_FILE_IS_A_DIRECTORY;
4815 /* Ensure this is within the share. */
4816 status = check_reduced_name(conn, oldname);
4817 if (!NT_STATUS_IS_OK(status)) {
4818 return status;
4821 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4823 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4824 status = map_nt_error_from_unix(errno);
4825 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4826 nt_errstr(status), newname, oldname));
4829 return status;
4832 /****************************************************************************
4833 Deal with setting the time from any of the setfilepathinfo functions.
4834 ****************************************************************************/
4836 NTSTATUS smb_set_file_time(connection_struct *conn,
4837 files_struct *fsp,
4838 const char *fname,
4839 const SMB_STRUCT_STAT *psbuf,
4840 struct timespec ts[2],
4841 bool setting_write_time)
4843 uint32 action =
4844 FILE_NOTIFY_CHANGE_LAST_ACCESS
4845 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4847 if (!VALID_STAT(*psbuf)) {
4848 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4851 /* get some defaults (no modifications) if any info is zero or -1. */
4852 if (null_timespec(ts[0])) {
4853 ts[0] = get_atimespec(psbuf);
4854 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4857 if (null_timespec(ts[1])) {
4858 ts[1] = get_mtimespec(psbuf);
4859 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4862 if (!setting_write_time) {
4863 /* ts[1] comes from change time, not write time. */
4864 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4867 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4868 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4871 * Try and set the times of this file if
4872 * they are different from the current values.
4876 struct timespec mts = get_mtimespec(psbuf);
4877 struct timespec ats = get_atimespec(psbuf);
4878 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4879 return NT_STATUS_OK;
4883 if (setting_write_time) {
4885 * This was a setfileinfo on an open file.
4886 * NT does this a lot. We also need to
4887 * set the time here, as it can be read by
4888 * FindFirst/FindNext and with the patch for bug #2045
4889 * in smbd/fileio.c it ensures that this timestamp is
4890 * kept sticky even after a write. We save the request
4891 * away and will set it on file close and after a write. JRA.
4894 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4895 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4897 if (fsp != NULL) {
4898 set_write_time_fsp(fsp, ts[1], true);
4899 } else {
4900 set_write_time_path(conn, fname,
4901 vfs_file_id_from_sbuf(conn, psbuf),
4902 ts[1], true);
4906 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4908 if(file_ntimes(conn, fname, ts)!=0) {
4909 return map_nt_error_from_unix(errno);
4911 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4913 return NT_STATUS_OK;
4916 /****************************************************************************
4917 Deal with setting the dosmode from any of the setfilepathinfo functions.
4918 ****************************************************************************/
4920 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4921 const char *fname,
4922 SMB_STRUCT_STAT *psbuf,
4923 uint32 dosmode)
4925 if (!VALID_STAT(*psbuf)) {
4926 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4929 if (dosmode) {
4930 if (S_ISDIR(psbuf->st_mode)) {
4931 dosmode |= aDIR;
4932 } else {
4933 dosmode &= ~aDIR;
4937 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4939 /* check the mode isn't different, before changing it */
4940 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4942 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4943 fname, (unsigned int)dosmode ));
4945 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4946 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4947 fname, strerror(errno)));
4948 return map_nt_error_from_unix(errno);
4951 return NT_STATUS_OK;
4954 /****************************************************************************
4955 Deal with setting the size from any of the setfilepathinfo functions.
4956 ****************************************************************************/
4958 static NTSTATUS smb_set_file_size(connection_struct *conn,
4959 struct smb_request *req,
4960 files_struct *fsp,
4961 const char *fname,
4962 SMB_STRUCT_STAT *psbuf,
4963 SMB_OFF_T size)
4965 NTSTATUS status = NT_STATUS_OK;
4966 files_struct *new_fsp = NULL;
4968 if (!VALID_STAT(*psbuf)) {
4969 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4972 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4974 if (size == get_file_size(*psbuf)) {
4975 return NT_STATUS_OK;
4978 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4979 fname, (double)size ));
4981 if (fsp && fsp->fh->fd != -1) {
4982 /* Handle based call. */
4983 if (vfs_set_filelen(fsp, size) == -1) {
4984 return map_nt_error_from_unix(errno);
4986 return NT_STATUS_OK;
4989 status = open_file_ntcreate(conn, req, fname, psbuf,
4990 FILE_WRITE_ATTRIBUTES,
4991 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4992 FILE_OPEN,
4994 FILE_ATTRIBUTE_NORMAL,
4995 FORCE_OPLOCK_BREAK_TO_NONE,
4996 NULL, &new_fsp);
4998 if (!NT_STATUS_IS_OK(status)) {
4999 /* NB. We check for open_was_deferred in the caller. */
5000 return status;
5003 if (vfs_set_filelen(new_fsp, size) == -1) {
5004 status = map_nt_error_from_unix(errno);
5005 close_file(new_fsp,NORMAL_CLOSE);
5006 return status;
5009 close_file(new_fsp,NORMAL_CLOSE);
5010 return NT_STATUS_OK;
5013 /****************************************************************************
5014 Deal with SMB_INFO_SET_EA.
5015 ****************************************************************************/
5017 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5018 const char *pdata,
5019 int total_data,
5020 files_struct *fsp,
5021 const char *fname)
5023 struct ea_list *ea_list = NULL;
5024 TALLOC_CTX *ctx = NULL;
5025 NTSTATUS status = NT_STATUS_OK;
5027 if (total_data < 10) {
5029 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5030 length. They seem to have no effect. Bug #3212. JRA */
5032 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5033 /* We're done. We only get EA info in this call. */
5034 return NT_STATUS_OK;
5037 return NT_STATUS_INVALID_PARAMETER;
5040 if (IVAL(pdata,0) > total_data) {
5041 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5042 IVAL(pdata,0), (unsigned int)total_data));
5043 return NT_STATUS_INVALID_PARAMETER;
5046 ctx = talloc_tos();
5047 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5048 if (!ea_list) {
5049 return NT_STATUS_INVALID_PARAMETER;
5051 status = set_ea(conn, fsp, fname, ea_list);
5053 return status;
5056 /****************************************************************************
5057 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5058 ****************************************************************************/
5060 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5061 const char *pdata,
5062 int total_data,
5063 files_struct *fsp,
5064 const char *fname,
5065 SMB_STRUCT_STAT *psbuf)
5067 NTSTATUS status = NT_STATUS_OK;
5068 bool delete_on_close;
5069 uint32 dosmode = 0;
5071 if (total_data < 1) {
5072 return NT_STATUS_INVALID_PARAMETER;
5075 if (fsp == NULL) {
5076 return NT_STATUS_INVALID_HANDLE;
5079 delete_on_close = (CVAL(pdata,0) ? True : False);
5080 dosmode = dos_mode(conn, fname, psbuf);
5082 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5083 "delete_on_close = %u\n",
5084 fsp->fsp_name,
5085 (unsigned int)dosmode,
5086 (unsigned int)delete_on_close ));
5088 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5090 if (!NT_STATUS_IS_OK(status)) {
5091 return status;
5094 /* The set is across all open files on this dev/inode pair. */
5095 if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
5096 return NT_STATUS_ACCESS_DENIED;
5098 return NT_STATUS_OK;
5101 /****************************************************************************
5102 Deal with SMB_FILE_POSITION_INFORMATION.
5103 ****************************************************************************/
5105 static NTSTATUS smb_file_position_information(connection_struct *conn,
5106 const char *pdata,
5107 int total_data,
5108 files_struct *fsp)
5110 SMB_BIG_UINT position_information;
5112 if (total_data < 8) {
5113 return NT_STATUS_INVALID_PARAMETER;
5116 if (fsp == NULL) {
5117 /* Ignore on pathname based set. */
5118 return NT_STATUS_OK;
5121 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5122 #ifdef LARGE_SMB_OFF_T
5123 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5124 #else /* LARGE_SMB_OFF_T */
5125 if (IVAL(pdata,4) != 0) {
5126 /* more than 32 bits? */
5127 return NT_STATUS_INVALID_PARAMETER;
5129 #endif /* LARGE_SMB_OFF_T */
5131 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5132 fsp->fsp_name, (double)position_information ));
5133 fsp->fh->position_information = position_information;
5134 return NT_STATUS_OK;
5137 /****************************************************************************
5138 Deal with SMB_FILE_MODE_INFORMATION.
5139 ****************************************************************************/
5141 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5142 const char *pdata,
5143 int total_data)
5145 uint32 mode;
5147 if (total_data < 4) {
5148 return NT_STATUS_INVALID_PARAMETER;
5150 mode = IVAL(pdata,0);
5151 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5152 return NT_STATUS_INVALID_PARAMETER;
5154 return NT_STATUS_OK;
5157 /****************************************************************************
5158 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5159 ****************************************************************************/
5161 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5162 struct smb_request *req,
5163 const char *pdata,
5164 int total_data,
5165 const char *fname)
5167 char *link_target = NULL;
5168 const char *newname = fname;
5169 NTSTATUS status = NT_STATUS_OK;
5170 TALLOC_CTX *ctx = talloc_tos();
5172 /* Set a symbolic link. */
5173 /* Don't allow this if follow links is false. */
5175 if (total_data == 0) {
5176 return NT_STATUS_INVALID_PARAMETER;
5179 if (!lp_symlinks(SNUM(conn))) {
5180 return NT_STATUS_ACCESS_DENIED;
5183 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5184 total_data, STR_TERMINATE);
5186 if (!link_target) {
5187 return NT_STATUS_INVALID_PARAMETER;
5190 /* !widelinks forces the target path to be within the share. */
5191 /* This means we can interpret the target as a pathname. */
5192 if (!lp_widelinks(SNUM(conn))) {
5193 char *rel_name = NULL;
5194 char *last_dirp = NULL;
5196 if (*link_target == '/') {
5197 /* No absolute paths allowed. */
5198 return NT_STATUS_ACCESS_DENIED;
5200 rel_name = talloc_strdup(ctx,newname);
5201 if (!rel_name) {
5202 return NT_STATUS_NO_MEMORY;
5204 last_dirp = strrchr_m(rel_name, '/');
5205 if (last_dirp) {
5206 last_dirp[1] = '\0';
5207 } else {
5208 rel_name = talloc_strdup(ctx,"./");
5209 if (!rel_name) {
5210 return NT_STATUS_NO_MEMORY;
5213 rel_name = talloc_asprintf_append(rel_name,
5214 "%s",
5215 link_target);
5216 if (!rel_name) {
5217 return NT_STATUS_NO_MEMORY;
5220 status = check_name(conn, rel_name);
5221 if (!NT_STATUS_IS_OK(status)) {
5222 return status;
5226 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5227 newname, link_target ));
5229 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5230 return map_nt_error_from_unix(errno);
5233 return NT_STATUS_OK;
5236 /****************************************************************************
5237 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5238 ****************************************************************************/
5240 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5241 struct smb_request *req,
5242 const char *pdata, int total_data,
5243 const char *fname)
5245 char *oldname = NULL;
5246 TALLOC_CTX *ctx = talloc_tos();
5247 NTSTATUS status = NT_STATUS_OK;
5249 /* Set a hard link. */
5250 if (total_data == 0) {
5251 return NT_STATUS_INVALID_PARAMETER;
5254 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5255 total_data, STR_TERMINATE, &status);
5256 if (!NT_STATUS_IS_OK(status)) {
5257 return status;
5260 status = resolve_dfspath(ctx, conn,
5261 req->flags2 & FLAGS2_DFS_PATHNAMES,
5262 oldname,
5263 &oldname);
5264 if (!NT_STATUS_IS_OK(status)) {
5265 return status;
5268 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5269 fname, oldname));
5271 return hardlink_internals(ctx, conn, oldname, fname);
5274 /****************************************************************************
5275 Deal with SMB_FILE_RENAME_INFORMATION.
5276 ****************************************************************************/
5278 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5279 struct smb_request *req,
5280 const char *pdata,
5281 int total_data,
5282 files_struct *fsp,
5283 const char *fname)
5285 bool overwrite;
5286 uint32 root_fid;
5287 uint32 len;
5288 char *newname = NULL;
5289 char *base_name = NULL;
5290 bool dest_has_wcard = False;
5291 NTSTATUS status = NT_STATUS_OK;
5292 char *p;
5293 TALLOC_CTX *ctx = talloc_tos();
5295 if (total_data < 13) {
5296 return NT_STATUS_INVALID_PARAMETER;
5299 overwrite = (CVAL(pdata,0) ? True : False);
5300 root_fid = IVAL(pdata,4);
5301 len = IVAL(pdata,8);
5303 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5304 return NT_STATUS_INVALID_PARAMETER;
5307 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5308 len, 0, &status,
5309 &dest_has_wcard);
5310 if (!NT_STATUS_IS_OK(status)) {
5311 return status;
5314 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5315 newname));
5317 status = resolve_dfspath_wcard(ctx, conn,
5318 req->flags2 & FLAGS2_DFS_PATHNAMES,
5319 newname,
5320 &newname,
5321 &dest_has_wcard);
5322 if (!NT_STATUS_IS_OK(status)) {
5323 return status;
5326 /* Check the new name has no '/' characters. */
5327 if (strchr_m(newname, '/')) {
5328 return NT_STATUS_NOT_SUPPORTED;
5331 /* Create the base directory. */
5332 base_name = talloc_strdup(ctx, fname);
5333 if (!base_name) {
5334 return NT_STATUS_NO_MEMORY;
5336 p = strrchr_m(base_name, '/');
5337 if (p) {
5338 p[1] = '\0';
5339 } else {
5340 base_name = talloc_strdup(ctx, "./");
5341 if (!base_name) {
5342 return NT_STATUS_NO_MEMORY;
5345 /* Append the new name. */
5346 base_name = talloc_asprintf_append(base_name,
5347 "%s",
5348 newname);
5349 if (!base_name) {
5350 return NT_STATUS_NO_MEMORY;
5353 if (fsp) {
5354 SMB_STRUCT_STAT sbuf;
5355 char *newname_last_component = NULL;
5357 ZERO_STRUCT(sbuf);
5359 status = unix_convert(ctx, conn, newname, False,
5360 &newname,
5361 &newname_last_component,
5362 &sbuf);
5364 /* If an error we expect this to be
5365 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5367 if (!NT_STATUS_IS_OK(status)
5368 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5369 status)) {
5370 return status;
5373 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5374 fsp->fnum, fsp->fsp_name, base_name ));
5375 status = rename_internals_fsp(conn, fsp, base_name,
5376 newname_last_component, 0,
5377 overwrite);
5378 } else {
5379 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5380 fname, base_name ));
5381 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5382 overwrite, False, dest_has_wcard,
5383 FILE_WRITE_ATTRIBUTES);
5386 return status;
5389 /****************************************************************************
5390 Deal with SMB_SET_POSIX_ACL.
5391 ****************************************************************************/
5393 #if defined(HAVE_POSIX_ACLS)
5394 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5395 const char *pdata,
5396 int total_data,
5397 files_struct *fsp,
5398 const char *fname,
5399 SMB_STRUCT_STAT *psbuf)
5401 uint16 posix_acl_version;
5402 uint16 num_file_acls;
5403 uint16 num_def_acls;
5404 bool valid_file_acls = True;
5405 bool valid_def_acls = True;
5407 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5408 return NT_STATUS_INVALID_PARAMETER;
5410 posix_acl_version = SVAL(pdata,0);
5411 num_file_acls = SVAL(pdata,2);
5412 num_def_acls = SVAL(pdata,4);
5414 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5415 valid_file_acls = False;
5416 num_file_acls = 0;
5419 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5420 valid_def_acls = False;
5421 num_def_acls = 0;
5424 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5425 return NT_STATUS_INVALID_PARAMETER;
5428 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5429 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5430 return NT_STATUS_INVALID_PARAMETER;
5433 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5434 fname ? fname : fsp->fsp_name,
5435 (unsigned int)num_file_acls,
5436 (unsigned int)num_def_acls));
5438 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5439 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5440 return map_nt_error_from_unix(errno);
5443 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5444 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5445 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5446 return map_nt_error_from_unix(errno);
5448 return NT_STATUS_OK;
5450 #endif
5452 /****************************************************************************
5453 Deal with SMB_SET_POSIX_LOCK.
5454 ****************************************************************************/
5456 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5457 const struct smb_request *req,
5458 const char *pdata,
5459 int total_data,
5460 files_struct *fsp)
5462 SMB_BIG_UINT count;
5463 SMB_BIG_UINT offset;
5464 uint32 lock_pid;
5465 bool blocking_lock = False;
5466 enum brl_type lock_type;
5468 NTSTATUS status = NT_STATUS_OK;
5470 if (fsp == NULL || fsp->fh->fd == -1) {
5471 return NT_STATUS_INVALID_HANDLE;
5474 if (total_data != POSIX_LOCK_DATA_SIZE) {
5475 return NT_STATUS_INVALID_PARAMETER;
5478 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5479 case POSIX_LOCK_TYPE_READ:
5480 lock_type = READ_LOCK;
5481 break;
5482 case POSIX_LOCK_TYPE_WRITE:
5483 /* Return the right POSIX-mappable error code for files opened read-only. */
5484 if (!fsp->can_write) {
5485 return NT_STATUS_INVALID_HANDLE;
5487 lock_type = WRITE_LOCK;
5488 break;
5489 case POSIX_LOCK_TYPE_UNLOCK:
5490 lock_type = UNLOCK_LOCK;
5491 break;
5492 default:
5493 return NT_STATUS_INVALID_PARAMETER;
5496 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5497 blocking_lock = False;
5498 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5499 blocking_lock = True;
5500 } else {
5501 return NT_STATUS_INVALID_PARAMETER;
5504 if (!lp_blocking_locks(SNUM(conn))) {
5505 blocking_lock = False;
5508 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5509 #if defined(HAVE_LONGLONG)
5510 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5511 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5512 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5513 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5514 #else /* HAVE_LONGLONG */
5515 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5516 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5517 #endif /* HAVE_LONGLONG */
5519 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5520 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5521 fsp->fsp_name,
5522 (unsigned int)lock_type,
5523 (unsigned int)lock_pid,
5524 (double)count,
5525 (double)offset ));
5527 if (lock_type == UNLOCK_LOCK) {
5528 status = do_unlock(smbd_messaging_context(),
5529 fsp,
5530 lock_pid,
5531 count,
5532 offset,
5533 POSIX_LOCK);
5534 } else {
5535 uint32 block_smbpid;
5537 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5538 fsp,
5539 lock_pid,
5540 count,
5541 offset,
5542 lock_type,
5543 POSIX_LOCK,
5544 blocking_lock,
5545 &status,
5546 &block_smbpid);
5548 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5550 * A blocking lock was requested. Package up
5551 * this smb into a queued request and push it
5552 * onto the blocking lock queue.
5554 if(push_blocking_lock_request(br_lck,
5555 req,
5556 fsp,
5557 -1, /* infinite timeout. */
5559 lock_pid,
5560 lock_type,
5561 POSIX_LOCK,
5562 offset,
5563 count,
5564 block_smbpid)) {
5565 TALLOC_FREE(br_lck);
5566 return status;
5569 TALLOC_FREE(br_lck);
5572 return status;
5575 /****************************************************************************
5576 Deal with SMB_INFO_STANDARD.
5577 ****************************************************************************/
5579 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5580 const char *pdata,
5581 int total_data,
5582 files_struct *fsp,
5583 const char *fname,
5584 const SMB_STRUCT_STAT *psbuf)
5586 struct timespec ts[2];
5588 if (total_data < 12) {
5589 return NT_STATUS_INVALID_PARAMETER;
5592 /* access time */
5593 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5594 /* write time */
5595 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5597 DEBUG(10,("smb_set_info_standard: file %s\n",
5598 fname ? fname : fsp->fsp_name ));
5600 return smb_set_file_time(conn,
5601 fsp,
5602 fname,
5603 psbuf,
5605 true);
5608 /****************************************************************************
5609 Deal with SMB_SET_FILE_BASIC_INFO.
5610 ****************************************************************************/
5612 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5613 const char *pdata,
5614 int total_data,
5615 files_struct *fsp,
5616 const char *fname,
5617 SMB_STRUCT_STAT *psbuf)
5619 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5620 struct timespec write_time;
5621 struct timespec changed_time;
5622 uint32 dosmode = 0;
5623 struct timespec ts[2];
5624 NTSTATUS status = NT_STATUS_OK;
5625 bool setting_write_time = true;
5627 if (total_data < 36) {
5628 return NT_STATUS_INVALID_PARAMETER;
5631 /* Set the attributes */
5632 dosmode = IVAL(pdata,32);
5633 status = smb_set_file_dosmode(conn,
5634 fname,
5635 psbuf,
5636 dosmode);
5637 if (!NT_STATUS_IS_OK(status)) {
5638 return status;
5641 /* Ignore create time at offset pdata. */
5643 /* access time */
5644 ts[0] = interpret_long_date(pdata+8);
5646 write_time = interpret_long_date(pdata+16);
5647 changed_time = interpret_long_date(pdata+24);
5649 /* mtime */
5650 ts[1] = timespec_min(&write_time, &changed_time);
5652 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5653 ts[1] = write_time;
5656 /* Prefer a defined time to an undefined one. */
5657 if (null_timespec(ts[1])) {
5658 if (null_timespec(write_time)) {
5659 ts[1] = changed_time;
5660 setting_write_time = false;
5661 } else {
5662 ts[1] = write_time;
5666 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5667 fname ? fname : fsp->fsp_name ));
5669 return smb_set_file_time(conn,
5670 fsp,
5671 fname,
5672 psbuf,
5674 setting_write_time);
5677 /****************************************************************************
5678 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5679 ****************************************************************************/
5681 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5682 struct smb_request *req,
5683 const char *pdata,
5684 int total_data,
5685 files_struct *fsp,
5686 const char *fname,
5687 SMB_STRUCT_STAT *psbuf)
5689 SMB_BIG_UINT allocation_size = 0;
5690 NTSTATUS status = NT_STATUS_OK;
5691 files_struct *new_fsp = NULL;
5693 if (!VALID_STAT(*psbuf)) {
5694 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5697 if (total_data < 8) {
5698 return NT_STATUS_INVALID_PARAMETER;
5701 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5702 #ifdef LARGE_SMB_OFF_T
5703 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5704 #else /* LARGE_SMB_OFF_T */
5705 if (IVAL(pdata,4) != 0) {
5706 /* more than 32 bits? */
5707 return NT_STATUS_INVALID_PARAMETER;
5709 #endif /* LARGE_SMB_OFF_T */
5711 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5712 fname, (double)allocation_size ));
5714 if (allocation_size) {
5715 allocation_size = smb_roundup(conn, allocation_size);
5718 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5719 fname, (double)allocation_size ));
5721 if (fsp && fsp->fh->fd != -1) {
5722 /* Open file handle. */
5723 /* Only change if needed. */
5724 if (allocation_size != get_file_size(*psbuf)) {
5725 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5726 return map_nt_error_from_unix(errno);
5729 /* But always update the time. */
5731 * This is equivalent to a write. Ensure it's seen immediately
5732 * if there are no pending writes.
5734 trigger_write_time_update(fsp);
5735 return NT_STATUS_OK;
5738 /* Pathname or stat or directory file. */
5740 status = open_file_ntcreate(conn, req, fname, psbuf,
5741 FILE_WRITE_DATA,
5742 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5743 FILE_OPEN,
5745 FILE_ATTRIBUTE_NORMAL,
5746 FORCE_OPLOCK_BREAK_TO_NONE,
5747 NULL, &new_fsp);
5749 if (!NT_STATUS_IS_OK(status)) {
5750 /* NB. We check for open_was_deferred in the caller. */
5751 return status;
5754 /* Only change if needed. */
5755 if (allocation_size != get_file_size(*psbuf)) {
5756 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5757 status = map_nt_error_from_unix(errno);
5758 close_file(new_fsp,NORMAL_CLOSE);
5759 return status;
5763 /* Changing the allocation size should set the last mod time. */
5765 * This is equivalent to a write. Ensure it's seen immediately
5766 * if there are no pending writes.
5768 trigger_write_time_update(new_fsp);
5770 close_file(new_fsp,NORMAL_CLOSE);
5771 return NT_STATUS_OK;
5774 /****************************************************************************
5775 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5776 ****************************************************************************/
5778 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5779 struct smb_request *req,
5780 const char *pdata,
5781 int total_data,
5782 files_struct *fsp,
5783 const char *fname,
5784 SMB_STRUCT_STAT *psbuf)
5786 SMB_OFF_T size;
5788 if (total_data < 8) {
5789 return NT_STATUS_INVALID_PARAMETER;
5792 size = IVAL(pdata,0);
5793 #ifdef LARGE_SMB_OFF_T
5794 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5795 #else /* LARGE_SMB_OFF_T */
5796 if (IVAL(pdata,4) != 0) {
5797 /* more than 32 bits? */
5798 return NT_STATUS_INVALID_PARAMETER;
5800 #endif /* LARGE_SMB_OFF_T */
5801 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5802 "file %s to %.0f\n", fname, (double)size ));
5804 return smb_set_file_size(conn, req,
5805 fsp,
5806 fname,
5807 psbuf,
5808 size);
5811 /****************************************************************************
5812 Allow a UNIX info mknod.
5813 ****************************************************************************/
5815 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5816 const char *pdata,
5817 int total_data,
5818 const char *fname,
5819 SMB_STRUCT_STAT *psbuf)
5821 uint32 file_type = IVAL(pdata,56);
5822 #if defined(HAVE_MAKEDEV)
5823 uint32 dev_major = IVAL(pdata,60);
5824 uint32 dev_minor = IVAL(pdata,68);
5825 #endif
5826 SMB_DEV_T dev = (SMB_DEV_T)0;
5827 uint32 raw_unixmode = IVAL(pdata,84);
5828 NTSTATUS status;
5829 mode_t unixmode;
5831 if (total_data < 100) {
5832 return NT_STATUS_INVALID_PARAMETER;
5835 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5836 if (!NT_STATUS_IS_OK(status)) {
5837 return status;
5840 #if defined(HAVE_MAKEDEV)
5841 dev = makedev(dev_major, dev_minor);
5842 #endif
5844 switch (file_type) {
5845 #if defined(S_IFIFO)
5846 case UNIX_TYPE_FIFO:
5847 unixmode |= S_IFIFO;
5848 break;
5849 #endif
5850 #if defined(S_IFSOCK)
5851 case UNIX_TYPE_SOCKET:
5852 unixmode |= S_IFSOCK;
5853 break;
5854 #endif
5855 #if defined(S_IFCHR)
5856 case UNIX_TYPE_CHARDEV:
5857 unixmode |= S_IFCHR;
5858 break;
5859 #endif
5860 #if defined(S_IFBLK)
5861 case UNIX_TYPE_BLKDEV:
5862 unixmode |= S_IFBLK;
5863 break;
5864 #endif
5865 default:
5866 return NT_STATUS_INVALID_PARAMETER;
5869 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5870 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5872 /* Ok - do the mknod. */
5873 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5874 return map_nt_error_from_unix(errno);
5877 /* If any of the other "set" calls fail we
5878 * don't want to end up with a half-constructed mknod.
5881 if (lp_inherit_perms(SNUM(conn))) {
5882 inherit_access_posix_acl(
5883 conn, parent_dirname(fname),
5884 fname, unixmode);
5887 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5888 status = map_nt_error_from_unix(errno);
5889 SMB_VFS_UNLINK(conn,fname);
5890 return status;
5892 return NT_STATUS_OK;
5895 /****************************************************************************
5896 Deal with SMB_SET_FILE_UNIX_BASIC.
5897 ****************************************************************************/
5899 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5900 struct smb_request *req,
5901 const char *pdata,
5902 int total_data,
5903 files_struct *fsp,
5904 const char *fname,
5905 SMB_STRUCT_STAT *psbuf)
5907 struct timespec ts[2];
5908 uint32 raw_unixmode;
5909 mode_t unixmode;
5910 SMB_OFF_T size = 0;
5911 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5912 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5913 NTSTATUS status = NT_STATUS_OK;
5914 bool delete_on_fail = False;
5915 enum perm_type ptype;
5917 if (total_data < 100) {
5918 return NT_STATUS_INVALID_PARAMETER;
5921 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5922 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5923 size=IVAL(pdata,0); /* first 8 Bytes are size */
5924 #ifdef LARGE_SMB_OFF_T
5925 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5926 #else /* LARGE_SMB_OFF_T */
5927 if (IVAL(pdata,4) != 0) {
5928 /* more than 32 bits? */
5929 return NT_STATUS_INVALID_PARAMETER;
5931 #endif /* LARGE_SMB_OFF_T */
5934 ts[0] = interpret_long_date(pdata+24); /* access_time */
5935 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5936 set_owner = (uid_t)IVAL(pdata,40);
5937 set_grp = (gid_t)IVAL(pdata,48);
5938 raw_unixmode = IVAL(pdata,84);
5940 if (VALID_STAT(*psbuf)) {
5941 if (S_ISDIR(psbuf->st_mode)) {
5942 ptype = PERM_EXISTING_DIR;
5943 } else {
5944 ptype = PERM_EXISTING_FILE;
5946 } else {
5947 ptype = PERM_NEW_FILE;
5950 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5951 if (!NT_STATUS_IS_OK(status)) {
5952 return status;
5955 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5956 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5957 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5959 if (!VALID_STAT(*psbuf)) {
5961 * The only valid use of this is to create character and block
5962 * devices, and named pipes. This is deprecated (IMHO) and
5963 * a new info level should be used for mknod. JRA.
5966 status = smb_unix_mknod(conn,
5967 pdata,
5968 total_data,
5969 fname,
5970 psbuf);
5971 if (!NT_STATUS_IS_OK(status)) {
5972 return status;
5975 /* Ensure we don't try and change anything else. */
5976 raw_unixmode = SMB_MODE_NO_CHANGE;
5977 size = get_file_size(*psbuf);
5978 ts[0] = get_atimespec(psbuf);
5979 ts[1] = get_mtimespec(psbuf);
5981 * We continue here as we might want to change the
5982 * owner uid/gid.
5984 delete_on_fail = True;
5987 #if 1
5988 /* Horrible backwards compatibility hack as an old server bug
5989 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5990 * */
5992 if (!size) {
5993 size = get_file_size(*psbuf);
5995 #endif
5998 * Deal with the UNIX specific mode set.
6001 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6002 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6003 (unsigned int)unixmode, fname ));
6004 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6005 return map_nt_error_from_unix(errno);
6010 * Deal with the UNIX specific uid set.
6013 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6014 int ret;
6016 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6017 (unsigned int)set_owner, fname ));
6019 if (S_ISLNK(psbuf->st_mode)) {
6020 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6021 } else {
6022 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6025 if (ret != 0) {
6026 status = map_nt_error_from_unix(errno);
6027 if (delete_on_fail) {
6028 SMB_VFS_UNLINK(conn,fname);
6030 return status;
6035 * Deal with the UNIX specific gid set.
6038 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6039 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6040 (unsigned int)set_owner, fname ));
6041 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6042 status = map_nt_error_from_unix(errno);
6043 if (delete_on_fail) {
6044 SMB_VFS_UNLINK(conn,fname);
6046 return status;
6050 /* Deal with any size changes. */
6052 status = smb_set_file_size(conn, req,
6053 fsp,
6054 fname,
6055 psbuf,
6056 size);
6057 if (!NT_STATUS_IS_OK(status)) {
6058 return status;
6061 /* Deal with any time changes. */
6063 return smb_set_file_time(conn,
6064 fsp,
6065 fname,
6066 psbuf,
6068 true);
6071 /****************************************************************************
6072 Deal with SMB_SET_FILE_UNIX_INFO2.
6073 ****************************************************************************/
6075 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6076 struct smb_request *req,
6077 const char *pdata,
6078 int total_data,
6079 files_struct *fsp,
6080 const char *fname,
6081 SMB_STRUCT_STAT *psbuf)
6083 NTSTATUS status;
6084 uint32 smb_fflags;
6085 uint32 smb_fmask;
6087 if (total_data < 116) {
6088 return NT_STATUS_INVALID_PARAMETER;
6091 /* Start by setting all the fields that are common between UNIX_BASIC
6092 * and UNIX_INFO2.
6094 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6095 fsp, fname, psbuf);
6096 if (!NT_STATUS_IS_OK(status)) {
6097 return status;
6100 smb_fflags = IVAL(pdata, 108);
6101 smb_fmask = IVAL(pdata, 112);
6103 /* NB: We should only attempt to alter the file flags if the client
6104 * sends a non-zero mask.
6106 if (smb_fmask != 0) {
6107 int stat_fflags = 0;
6109 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6110 &stat_fflags)) {
6111 /* Client asked to alter a flag we don't understand. */
6112 return NT_STATUS_INVALID_PARAMETER;
6115 if (fsp && fsp->fh->fd != -1) {
6116 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6117 return NT_STATUS_NOT_SUPPORTED;
6118 } else {
6119 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6120 return map_nt_error_from_unix(errno);
6125 /* XXX: need to add support for changing the create_time here. You
6126 * can do this for paths on Darwin with setattrlist(2). The right way
6127 * to hook this up is probably by extending the VFS utimes interface.
6130 return NT_STATUS_OK;
6133 /****************************************************************************
6134 Create a directory with POSIX semantics.
6135 ****************************************************************************/
6137 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6138 struct smb_request *req,
6139 char **ppdata,
6140 int total_data,
6141 const char *fname,
6142 SMB_STRUCT_STAT *psbuf,
6143 int *pdata_return_size)
6145 NTSTATUS status = NT_STATUS_OK;
6146 uint32 raw_unixmode = 0;
6147 uint32 mod_unixmode = 0;
6148 mode_t unixmode = (mode_t)0;
6149 files_struct *fsp = NULL;
6150 uint16 info_level_return = 0;
6151 int info;
6152 char *pdata = *ppdata;
6154 if (total_data < 18) {
6155 return NT_STATUS_INVALID_PARAMETER;
6158 raw_unixmode = IVAL(pdata,8);
6159 /* Next 4 bytes are not yet defined. */
6161 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6162 if (!NT_STATUS_IS_OK(status)) {
6163 return status;
6166 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6168 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6169 fname, (unsigned int)unixmode ));
6171 status = open_directory(conn, req,
6172 fname,
6173 psbuf,
6174 FILE_READ_ATTRIBUTES, /* Just a stat open */
6175 FILE_SHARE_NONE, /* Ignored for stat opens */
6176 FILE_CREATE,
6178 mod_unixmode,
6179 &info,
6180 &fsp);
6182 if (NT_STATUS_IS_OK(status)) {
6183 close_file(fsp, NORMAL_CLOSE);
6186 info_level_return = SVAL(pdata,16);
6188 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6189 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6190 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6191 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6192 } else {
6193 *pdata_return_size = 12;
6196 /* Realloc the data size */
6197 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6198 if (*ppdata == NULL) {
6199 *pdata_return_size = 0;
6200 return NT_STATUS_NO_MEMORY;
6202 pdata = *ppdata;
6204 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6205 SSVAL(pdata,2,0); /* No fnum. */
6206 SIVAL(pdata,4,info); /* Was directory created. */
6208 switch (info_level_return) {
6209 case SMB_QUERY_FILE_UNIX_BASIC:
6210 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6211 SSVAL(pdata,10,0); /* Padding. */
6212 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6213 break;
6214 case SMB_QUERY_FILE_UNIX_INFO2:
6215 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6216 SSVAL(pdata,10,0); /* Padding. */
6217 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6218 break;
6219 default:
6220 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6221 SSVAL(pdata,10,0); /* Padding. */
6222 break;
6225 return status;
6228 /****************************************************************************
6229 Open/Create a file with POSIX semantics.
6230 ****************************************************************************/
6232 static NTSTATUS smb_posix_open(connection_struct *conn,
6233 struct smb_request *req,
6234 char **ppdata,
6235 int total_data,
6236 const char *fname,
6237 SMB_STRUCT_STAT *psbuf,
6238 int *pdata_return_size)
6240 bool extended_oplock_granted = False;
6241 char *pdata = *ppdata;
6242 uint32 flags = 0;
6243 uint32 wire_open_mode = 0;
6244 uint32 raw_unixmode = 0;
6245 uint32 mod_unixmode = 0;
6246 uint32 create_disp = 0;
6247 uint32 access_mask = 0;
6248 uint32 create_options = 0;
6249 NTSTATUS status = NT_STATUS_OK;
6250 mode_t unixmode = (mode_t)0;
6251 files_struct *fsp = NULL;
6252 int oplock_request = 0;
6253 int info = 0;
6254 uint16 info_level_return = 0;
6256 if (total_data < 18) {
6257 return NT_STATUS_INVALID_PARAMETER;
6260 flags = IVAL(pdata,0);
6261 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6262 if (oplock_request) {
6263 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6266 wire_open_mode = IVAL(pdata,4);
6268 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6269 return smb_posix_mkdir(conn, req,
6270 ppdata,
6271 total_data,
6272 fname,
6273 psbuf,
6274 pdata_return_size);
6277 switch (wire_open_mode & SMB_ACCMODE) {
6278 case SMB_O_RDONLY:
6279 access_mask = FILE_READ_DATA;
6280 break;
6281 case SMB_O_WRONLY:
6282 access_mask = FILE_WRITE_DATA;
6283 break;
6284 case SMB_O_RDWR:
6285 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6286 break;
6287 default:
6288 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6289 (unsigned int)wire_open_mode ));
6290 return NT_STATUS_INVALID_PARAMETER;
6293 wire_open_mode &= ~SMB_ACCMODE;
6295 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6296 create_disp = FILE_CREATE;
6297 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6298 create_disp = FILE_OVERWRITE_IF;
6299 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6300 create_disp = FILE_OPEN_IF;
6301 } else {
6302 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6303 (unsigned int)wire_open_mode ));
6304 return NT_STATUS_INVALID_PARAMETER;
6307 raw_unixmode = IVAL(pdata,8);
6308 /* Next 4 bytes are not yet defined. */
6310 status = unix_perms_from_wire(conn,
6311 psbuf,
6312 raw_unixmode,
6313 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6314 &unixmode);
6316 if (!NT_STATUS_IS_OK(status)) {
6317 return status;
6320 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6322 if (wire_open_mode & SMB_O_SYNC) {
6323 create_options |= FILE_WRITE_THROUGH;
6325 if (wire_open_mode & SMB_O_APPEND) {
6326 access_mask |= FILE_APPEND_DATA;
6328 if (wire_open_mode & SMB_O_DIRECT) {
6329 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6332 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6333 fname,
6334 (unsigned int)wire_open_mode,
6335 (unsigned int)unixmode ));
6337 status = open_file_ntcreate(conn, req,
6338 fname,
6339 psbuf,
6340 access_mask,
6341 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6342 create_disp,
6343 0, /* no create options yet. */
6344 mod_unixmode,
6345 oplock_request,
6346 &info,
6347 &fsp);
6349 if (!NT_STATUS_IS_OK(status)) {
6350 return status;
6353 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6354 extended_oplock_granted = True;
6357 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6358 extended_oplock_granted = True;
6361 info_level_return = SVAL(pdata,16);
6363 /* Allocate the correct return size. */
6365 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6366 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6367 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6368 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6369 } else {
6370 *pdata_return_size = 12;
6373 /* Realloc the data size */
6374 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6375 if (*ppdata == NULL) {
6376 close_file(fsp,ERROR_CLOSE);
6377 *pdata_return_size = 0;
6378 return NT_STATUS_NO_MEMORY;
6380 pdata = *ppdata;
6382 if (extended_oplock_granted) {
6383 if (flags & REQUEST_BATCH_OPLOCK) {
6384 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6385 } else {
6386 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6388 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6389 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6390 } else {
6391 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6394 SSVAL(pdata,2,fsp->fnum);
6395 SIVAL(pdata,4,info); /* Was file created etc. */
6397 switch (info_level_return) {
6398 case SMB_QUERY_FILE_UNIX_BASIC:
6399 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6400 SSVAL(pdata,10,0); /* padding. */
6401 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6402 break;
6403 case SMB_QUERY_FILE_UNIX_INFO2:
6404 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6405 SSVAL(pdata,10,0); /* padding. */
6406 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6407 break;
6408 default:
6409 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6410 SSVAL(pdata,10,0); /* padding. */
6411 break;
6413 return NT_STATUS_OK;
6416 /****************************************************************************
6417 Delete a file with POSIX semantics.
6418 ****************************************************************************/
6420 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6421 struct smb_request *req,
6422 const char *pdata,
6423 int total_data,
6424 const char *fname,
6425 SMB_STRUCT_STAT *psbuf)
6427 NTSTATUS status = NT_STATUS_OK;
6428 files_struct *fsp = NULL;
6429 uint16 flags = 0;
6430 char del = 1;
6431 int info = 0;
6432 int i;
6433 struct share_mode_lock *lck = NULL;
6435 if (total_data < 2) {
6436 return NT_STATUS_INVALID_PARAMETER;
6439 flags = SVAL(pdata,0);
6441 if (!VALID_STAT(*psbuf)) {
6442 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6445 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6446 !VALID_STAT_OF_DIR(*psbuf)) {
6447 return NT_STATUS_NOT_A_DIRECTORY;
6450 DEBUG(10,("smb_posix_unlink: %s %s\n",
6451 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6452 fname));
6454 if (VALID_STAT_OF_DIR(*psbuf)) {
6455 status = open_directory(conn, req,
6456 fname,
6457 psbuf,
6458 DELETE_ACCESS,
6459 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6460 FILE_OPEN,
6462 FILE_FLAG_POSIX_SEMANTICS|0777,
6463 &info,
6464 &fsp);
6465 } else {
6467 status = open_file_ntcreate(conn, req,
6468 fname,
6469 psbuf,
6470 DELETE_ACCESS,
6471 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6472 FILE_OPEN,
6474 FILE_FLAG_POSIX_SEMANTICS|0777,
6475 0, /* No oplock, but break existing ones. */
6476 &info,
6477 &fsp);
6480 if (!NT_STATUS_IS_OK(status)) {
6481 return status;
6485 * Don't lie to client. If we can't really delete due to
6486 * non-POSIX opens return SHARING_VIOLATION.
6489 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6490 NULL);
6491 if (lck == NULL) {
6492 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6493 "lock for file %s\n", fsp->fsp_name));
6494 close_file(fsp, NORMAL_CLOSE);
6495 return NT_STATUS_INVALID_PARAMETER;
6499 * See if others still have the file open. If this is the case, then
6500 * don't delete. If all opens are POSIX delete we can set the delete
6501 * on close disposition.
6503 for (i=0; i<lck->num_share_modes; i++) {
6504 struct share_mode_entry *e = &lck->share_modes[i];
6505 if (is_valid_share_mode_entry(e)) {
6506 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6507 continue;
6509 /* Fail with sharing violation. */
6510 close_file(fsp, NORMAL_CLOSE);
6511 TALLOC_FREE(lck);
6512 return NT_STATUS_SHARING_VIOLATION;
6517 * Set the delete on close.
6519 status = smb_set_file_disposition_info(conn,
6520 &del,
6522 fsp,
6523 fname,
6524 psbuf);
6526 if (!NT_STATUS_IS_OK(status)) {
6527 close_file(fsp, NORMAL_CLOSE);
6528 TALLOC_FREE(lck);
6529 return status;
6531 TALLOC_FREE(lck);
6532 return close_file(fsp, NORMAL_CLOSE);
6535 /****************************************************************************
6536 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6537 ****************************************************************************/
6539 static void call_trans2setfilepathinfo(connection_struct *conn,
6540 struct smb_request *req,
6541 unsigned int tran_call,
6542 char **pparams, int total_params,
6543 char **ppdata, int total_data,
6544 unsigned int max_data_bytes)
6546 char *params = *pparams;
6547 char *pdata = *ppdata;
6548 uint16 info_level;
6549 SMB_STRUCT_STAT sbuf;
6550 char *fname = NULL;
6551 files_struct *fsp = NULL;
6552 NTSTATUS status = NT_STATUS_OK;
6553 int data_return_size = 0;
6554 TALLOC_CTX *ctx = talloc_tos();
6556 if (!params) {
6557 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6558 return;
6561 ZERO_STRUCT(sbuf);
6563 if (tran_call == TRANSACT2_SETFILEINFO) {
6564 if (total_params < 4) {
6565 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6566 return;
6569 fsp = file_fsp(SVAL(params,0));
6570 /* Basic check for non-null fsp. */
6571 if (!check_fsp_open(conn, req, fsp, &current_user)) {
6572 return;
6574 info_level = SVAL(params,2);
6576 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6577 if (!fname) {
6578 reply_nterror(req, NT_STATUS_NO_MEMORY);
6579 return;
6582 if(fsp->is_directory || fsp->fh->fd == -1) {
6584 * This is actually a SETFILEINFO on a directory
6585 * handle (returned from an NT SMB). NT5.0 seems
6586 * to do this call. JRA.
6588 if (INFO_LEVEL_IS_UNIX(info_level)) {
6589 /* Always do lstat for UNIX calls. */
6590 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6591 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6592 reply_unixerror(req,ERRDOS,ERRbadpath);
6593 return;
6595 } else {
6596 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6597 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6598 reply_unixerror(req,ERRDOS,ERRbadpath);
6599 return;
6602 } else if (fsp->print_file) {
6604 * Doing a DELETE_ON_CLOSE should cancel a print job.
6606 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6607 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6609 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6611 SSVAL(params,0,0);
6612 send_trans2_replies(conn, req, params, 2,
6613 *ppdata, 0,
6614 max_data_bytes);
6615 return;
6616 } else {
6617 reply_unixerror(req, ERRDOS, ERRbadpath);
6618 return;
6620 } else {
6622 * Original code - this is an open file.
6624 if (!check_fsp(conn, req, fsp, &current_user)) {
6625 return;
6628 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6629 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6630 reply_unixerror(req, ERRDOS, ERRbadfid);
6631 return;
6634 } else {
6635 /* set path info */
6636 if (total_params < 7) {
6637 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6638 return;
6641 info_level = SVAL(params,0);
6642 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6643 total_params - 6, STR_TERMINATE,
6644 &status);
6645 if (!NT_STATUS_IS_OK(status)) {
6646 reply_nterror(req, status);
6647 return;
6650 status = resolve_dfspath(ctx, conn,
6651 req->flags2 & FLAGS2_DFS_PATHNAMES,
6652 fname,
6653 &fname);
6654 if (!NT_STATUS_IS_OK(status)) {
6655 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6656 reply_botherror(req,
6657 NT_STATUS_PATH_NOT_COVERED,
6658 ERRSRV, ERRbadpath);
6659 return;
6661 reply_nterror(req, status);
6662 return;
6665 status = unix_convert(ctx, conn, fname, False,
6666 &fname, NULL, &sbuf);
6667 if (!NT_STATUS_IS_OK(status)) {
6668 reply_nterror(req, status);
6669 return;
6672 status = check_name(conn, fname);
6673 if (!NT_STATUS_IS_OK(status)) {
6674 reply_nterror(req, status);
6675 return;
6678 if (INFO_LEVEL_IS_UNIX(info_level)) {
6680 * For CIFS UNIX extensions the target name may not exist.
6683 /* Always do lstat for UNIX calls. */
6684 SMB_VFS_LSTAT(conn,fname,&sbuf);
6686 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6687 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6688 reply_unixerror(req, ERRDOS, ERRbadpath);
6689 return;
6693 if (!CAN_WRITE(conn)) {
6694 reply_doserror(req, ERRSRV, ERRaccess);
6695 return;
6698 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6699 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6700 return;
6703 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6704 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6706 /* Realloc the parameter size */
6707 *pparams = (char *)SMB_REALLOC(*pparams,2);
6708 if (*pparams == NULL) {
6709 reply_nterror(req, NT_STATUS_NO_MEMORY);
6710 return;
6712 params = *pparams;
6714 SSVAL(params,0,0);
6716 switch (info_level) {
6718 case SMB_INFO_STANDARD:
6720 status = smb_set_info_standard(conn,
6721 pdata,
6722 total_data,
6723 fsp,
6724 fname,
6725 &sbuf);
6726 break;
6729 case SMB_INFO_SET_EA:
6731 status = smb_info_set_ea(conn,
6732 pdata,
6733 total_data,
6734 fsp,
6735 fname);
6736 break;
6739 case SMB_SET_FILE_BASIC_INFO:
6740 case SMB_FILE_BASIC_INFORMATION:
6742 status = smb_set_file_basic_info(conn,
6743 pdata,
6744 total_data,
6745 fsp,
6746 fname,
6747 &sbuf);
6748 break;
6751 case SMB_FILE_ALLOCATION_INFORMATION:
6752 case SMB_SET_FILE_ALLOCATION_INFO:
6754 status = smb_set_file_allocation_info(conn, req,
6755 pdata,
6756 total_data,
6757 fsp,
6758 fname,
6759 &sbuf);
6760 break;
6763 case SMB_FILE_END_OF_FILE_INFORMATION:
6764 case SMB_SET_FILE_END_OF_FILE_INFO:
6766 status = smb_set_file_end_of_file_info(conn, req,
6767 pdata,
6768 total_data,
6769 fsp,
6770 fname,
6771 &sbuf);
6772 break;
6775 case SMB_FILE_DISPOSITION_INFORMATION:
6776 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6778 #if 0
6779 /* JRA - We used to just ignore this on a path ?
6780 * Shouldn't this be invalid level on a pathname
6781 * based call ?
6783 if (tran_call != TRANSACT2_SETFILEINFO) {
6784 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6786 #endif
6787 status = smb_set_file_disposition_info(conn,
6788 pdata,
6789 total_data,
6790 fsp,
6791 fname,
6792 &sbuf);
6793 break;
6796 case SMB_FILE_POSITION_INFORMATION:
6798 status = smb_file_position_information(conn,
6799 pdata,
6800 total_data,
6801 fsp);
6802 break;
6805 /* From tridge Samba4 :
6806 * MODE_INFORMATION in setfileinfo (I have no
6807 * idea what "mode information" on a file is - it takes a value of 0,
6808 * 2, 4 or 6. What could it be?).
6811 case SMB_FILE_MODE_INFORMATION:
6813 status = smb_file_mode_information(conn,
6814 pdata,
6815 total_data);
6816 break;
6820 * CIFS UNIX extensions.
6823 case SMB_SET_FILE_UNIX_BASIC:
6825 status = smb_set_file_unix_basic(conn, req,
6826 pdata,
6827 total_data,
6828 fsp,
6829 fname,
6830 &sbuf);
6831 break;
6834 case SMB_SET_FILE_UNIX_INFO2:
6836 status = smb_set_file_unix_info2(conn, req,
6837 pdata,
6838 total_data,
6839 fsp,
6840 fname,
6841 &sbuf);
6842 break;
6845 case SMB_SET_FILE_UNIX_LINK:
6847 if (tran_call != TRANSACT2_SETPATHINFO) {
6848 /* We must have a pathname for this. */
6849 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6850 return;
6852 status = smb_set_file_unix_link(conn, req, pdata,
6853 total_data, fname);
6854 break;
6857 case SMB_SET_FILE_UNIX_HLINK:
6859 if (tran_call != TRANSACT2_SETPATHINFO) {
6860 /* We must have a pathname for this. */
6861 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6862 return;
6864 status = smb_set_file_unix_hlink(conn, req,
6865 pdata, total_data,
6866 fname);
6867 break;
6870 case SMB_FILE_RENAME_INFORMATION:
6872 status = smb_file_rename_information(conn, req,
6873 pdata, total_data,
6874 fsp, fname);
6875 break;
6878 #if defined(HAVE_POSIX_ACLS)
6879 case SMB_SET_POSIX_ACL:
6881 status = smb_set_posix_acl(conn,
6882 pdata,
6883 total_data,
6884 fsp,
6885 fname,
6886 &sbuf);
6887 break;
6889 #endif
6891 case SMB_SET_POSIX_LOCK:
6893 if (tran_call != TRANSACT2_SETFILEINFO) {
6894 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6895 return;
6897 status = smb_set_posix_lock(conn, req,
6898 pdata, total_data, fsp);
6899 break;
6902 case SMB_POSIX_PATH_OPEN:
6904 if (tran_call != TRANSACT2_SETPATHINFO) {
6905 /* We must have a pathname for this. */
6906 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6907 return;
6910 status = smb_posix_open(conn, req,
6911 ppdata,
6912 total_data,
6913 fname,
6914 &sbuf,
6915 &data_return_size);
6916 break;
6919 case SMB_POSIX_PATH_UNLINK:
6921 if (tran_call != TRANSACT2_SETPATHINFO) {
6922 /* We must have a pathname for this. */
6923 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6924 return;
6927 status = smb_posix_unlink(conn, req,
6928 pdata,
6929 total_data,
6930 fname,
6931 &sbuf);
6932 break;
6935 default:
6936 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6937 return;
6941 if (!NT_STATUS_IS_OK(status)) {
6942 if (open_was_deferred(req->mid)) {
6943 /* We have re-scheduled this call. */
6944 return;
6946 if (blocking_lock_was_deferred(req->mid)) {
6947 /* We have re-scheduled this call. */
6948 return;
6950 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6951 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6952 ERRSRV, ERRbadpath);
6953 return;
6955 if (info_level == SMB_POSIX_PATH_OPEN) {
6956 reply_openerror(req, status);
6957 return;
6960 reply_nterror(req, status);
6961 return;
6964 SSVAL(params,0,0);
6965 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
6966 max_data_bytes);
6968 return;
6971 /****************************************************************************
6972 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6973 ****************************************************************************/
6975 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6976 char **pparams, int total_params,
6977 char **ppdata, int total_data,
6978 unsigned int max_data_bytes)
6980 char *params = *pparams;
6981 char *pdata = *ppdata;
6982 char *directory = NULL;
6983 SMB_STRUCT_STAT sbuf;
6984 NTSTATUS status = NT_STATUS_OK;
6985 struct ea_list *ea_list = NULL;
6986 TALLOC_CTX *ctx = talloc_tos();
6988 if (!CAN_WRITE(conn)) {
6989 reply_doserror(req, ERRSRV, ERRaccess);
6990 return;
6993 if (total_params < 5) {
6994 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6995 return;
6998 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
6999 total_params - 4, STR_TERMINATE,
7000 &status);
7001 if (!NT_STATUS_IS_OK(status)) {
7002 reply_nterror(req, status);
7003 return;
7006 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7008 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7009 if (!NT_STATUS_IS_OK(status)) {
7010 reply_nterror(req, status);
7011 return;
7014 status = check_name(conn, directory);
7015 if (!NT_STATUS_IS_OK(status)) {
7016 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7017 reply_nterror(req, status);
7018 return;
7021 /* Any data in this call is an EA list. */
7022 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7023 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7024 return;
7028 * OS/2 workplace shell seems to send SET_EA requests of "null"
7029 * length (4 bytes containing IVAL 4).
7030 * They seem to have no effect. Bug #3212. JRA.
7033 if (total_data != 4) {
7034 if (total_data < 10) {
7035 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7036 return;
7039 if (IVAL(pdata,0) > total_data) {
7040 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7041 IVAL(pdata,0), (unsigned int)total_data));
7042 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7043 return;
7046 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7047 total_data - 4);
7048 if (!ea_list) {
7049 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7050 return;
7052 } else if (IVAL(pdata,0) != 4) {
7053 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7054 return;
7057 status = create_directory(conn, req, directory);
7059 if (!NT_STATUS_IS_OK(status)) {
7060 reply_nterror(req, status);
7061 return;
7064 /* Try and set any given EA. */
7065 if (ea_list) {
7066 status = set_ea(conn, NULL, directory, ea_list);
7067 if (!NT_STATUS_IS_OK(status)) {
7068 reply_nterror(req, status);
7069 return;
7073 /* Realloc the parameter and data sizes */
7074 *pparams = (char *)SMB_REALLOC(*pparams,2);
7075 if(*pparams == NULL) {
7076 reply_nterror(req, NT_STATUS_NO_MEMORY);
7077 return;
7079 params = *pparams;
7081 SSVAL(params,0,0);
7083 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7085 return;
7088 /****************************************************************************
7089 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7090 We don't actually do this - we just send a null response.
7091 ****************************************************************************/
7093 static void call_trans2findnotifyfirst(connection_struct *conn,
7094 struct smb_request *req,
7095 char **pparams, int total_params,
7096 char **ppdata, int total_data,
7097 unsigned int max_data_bytes)
7099 static uint16 fnf_handle = 257;
7100 char *params = *pparams;
7101 uint16 info_level;
7103 if (total_params < 6) {
7104 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7105 return;
7108 info_level = SVAL(params,4);
7109 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7111 switch (info_level) {
7112 case 1:
7113 case 2:
7114 break;
7115 default:
7116 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7117 return;
7120 /* Realloc the parameter and data sizes */
7121 *pparams = (char *)SMB_REALLOC(*pparams,6);
7122 if (*pparams == NULL) {
7123 reply_nterror(req, NT_STATUS_NO_MEMORY);
7124 return;
7126 params = *pparams;
7128 SSVAL(params,0,fnf_handle);
7129 SSVAL(params,2,0); /* No changes */
7130 SSVAL(params,4,0); /* No EA errors */
7132 fnf_handle++;
7134 if(fnf_handle == 0)
7135 fnf_handle = 257;
7137 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7139 return;
7142 /****************************************************************************
7143 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7144 changes). Currently this does nothing.
7145 ****************************************************************************/
7147 static void call_trans2findnotifynext(connection_struct *conn,
7148 struct smb_request *req,
7149 char **pparams, int total_params,
7150 char **ppdata, int total_data,
7151 unsigned int max_data_bytes)
7153 char *params = *pparams;
7155 DEBUG(3,("call_trans2findnotifynext\n"));
7157 /* Realloc the parameter and data sizes */
7158 *pparams = (char *)SMB_REALLOC(*pparams,4);
7159 if (*pparams == NULL) {
7160 reply_nterror(req, NT_STATUS_NO_MEMORY);
7161 return;
7163 params = *pparams;
7165 SSVAL(params,0,0); /* No changes */
7166 SSVAL(params,2,0); /* No EA errors */
7168 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7170 return;
7173 /****************************************************************************
7174 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7175 ****************************************************************************/
7177 static void call_trans2getdfsreferral(connection_struct *conn,
7178 struct smb_request *req,
7179 char **pparams, int total_params,
7180 char **ppdata, int total_data,
7181 unsigned int max_data_bytes)
7183 char *params = *pparams;
7184 char *pathname = NULL;
7185 int reply_size = 0;
7186 int max_referral_level;
7187 NTSTATUS status = NT_STATUS_OK;
7188 TALLOC_CTX *ctx = talloc_tos();
7190 DEBUG(10,("call_trans2getdfsreferral\n"));
7192 if (total_params < 3) {
7193 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7194 return;
7197 max_referral_level = SVAL(params,0);
7199 if(!lp_host_msdfs()) {
7200 reply_doserror(req, ERRDOS, ERRbadfunc);
7201 return;
7204 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7205 total_params - 2, STR_TERMINATE);
7206 if (!pathname) {
7207 reply_nterror(req, NT_STATUS_NOT_FOUND);
7208 return;
7210 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7211 ppdata,&status)) < 0) {
7212 reply_nterror(req, status);
7213 return;
7216 SSVAL(req->inbuf, smb_flg2,
7217 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7218 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7220 return;
7223 #define LMCAT_SPL 0x53
7224 #define LMFUNC_GETJOBID 0x60
7226 /****************************************************************************
7227 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7228 ****************************************************************************/
7230 static void call_trans2ioctl(connection_struct *conn,
7231 struct smb_request *req,
7232 char **pparams, int total_params,
7233 char **ppdata, int total_data,
7234 unsigned int max_data_bytes)
7236 char *pdata = *ppdata;
7237 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7239 /* check for an invalid fid before proceeding */
7241 if (!fsp) {
7242 reply_doserror(req, ERRDOS, ERRbadfid);
7243 return;
7246 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7247 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7248 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7249 if (*ppdata == NULL) {
7250 reply_nterror(req, NT_STATUS_NO_MEMORY);
7251 return;
7253 pdata = *ppdata;
7255 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7256 CAN ACCEPT THIS IN UNICODE. JRA. */
7258 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7259 srvstr_push(pdata, req->flags2, pdata + 2,
7260 global_myname(), 15,
7261 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7262 srvstr_push(pdata, req->flags2, pdata+18,
7263 lp_servicename(SNUM(conn)), 13,
7264 STR_ASCII|STR_TERMINATE); /* Service name */
7265 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7266 max_data_bytes);
7267 return;
7270 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7271 reply_doserror(req, ERRSRV, ERRerror);
7274 /****************************************************************************
7275 Reply to a SMBfindclose (stop trans2 directory search).
7276 ****************************************************************************/
7278 void reply_findclose(struct smb_request *req)
7280 int dptr_num;
7282 START_PROFILE(SMBfindclose);
7284 if (req->wct < 1) {
7285 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7286 END_PROFILE(SMBfindclose);
7287 return;
7290 dptr_num = SVALS(req->inbuf,smb_vwv0);
7292 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7294 dptr_close(&dptr_num);
7296 reply_outbuf(req, 0, 0);
7298 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7300 END_PROFILE(SMBfindclose);
7301 return;
7304 /****************************************************************************
7305 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7306 ****************************************************************************/
7308 void reply_findnclose(struct smb_request *req)
7310 int dptr_num;
7312 START_PROFILE(SMBfindnclose);
7314 if (req->wct < 1) {
7315 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7316 END_PROFILE(SMBfindnclose);
7317 return;
7320 dptr_num = SVAL(req->inbuf,smb_vwv0);
7322 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7324 /* We never give out valid handles for a
7325 findnotifyfirst - so any dptr_num is ok here.
7326 Just ignore it. */
7328 reply_outbuf(req, 0, 0);
7330 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7332 END_PROFILE(SMBfindnclose);
7333 return;
7336 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7337 struct trans_state *state)
7339 if (Protocol >= PROTOCOL_NT1) {
7340 req->flags2 |= 0x40; /* IS_LONG_NAME */
7341 SSVAL(req->inbuf,smb_flg2,req->flags2);
7344 if (conn->encrypt_level == Required && !req->encrypted) {
7345 if (state->call != TRANSACT2_QFSINFO &&
7346 state->call != TRANSACT2_SETFSINFO) {
7347 DEBUG(0,("handle_trans2: encryption required "
7348 "with call 0x%x\n",
7349 (unsigned int)state->call));
7350 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7351 return;
7355 /* Now we must call the relevant TRANS2 function */
7356 switch(state->call) {
7357 case TRANSACT2_OPEN:
7359 START_PROFILE(Trans2_open);
7360 call_trans2open(conn, req,
7361 &state->param, state->total_param,
7362 &state->data, state->total_data,
7363 state->max_data_return);
7364 END_PROFILE(Trans2_open);
7365 break;
7368 case TRANSACT2_FINDFIRST:
7370 START_PROFILE(Trans2_findfirst);
7371 call_trans2findfirst(conn, req,
7372 &state->param, state->total_param,
7373 &state->data, state->total_data,
7374 state->max_data_return);
7375 END_PROFILE(Trans2_findfirst);
7376 break;
7379 case TRANSACT2_FINDNEXT:
7381 START_PROFILE(Trans2_findnext);
7382 call_trans2findnext(conn, req,
7383 &state->param, state->total_param,
7384 &state->data, state->total_data,
7385 state->max_data_return);
7386 END_PROFILE(Trans2_findnext);
7387 break;
7390 case TRANSACT2_QFSINFO:
7392 START_PROFILE(Trans2_qfsinfo);
7393 call_trans2qfsinfo(conn, req,
7394 &state->param, state->total_param,
7395 &state->data, state->total_data,
7396 state->max_data_return);
7397 END_PROFILE(Trans2_qfsinfo);
7398 break;
7401 case TRANSACT2_SETFSINFO:
7403 START_PROFILE(Trans2_setfsinfo);
7404 call_trans2setfsinfo(conn, req,
7405 &state->param, state->total_param,
7406 &state->data, state->total_data,
7407 state->max_data_return);
7408 END_PROFILE(Trans2_setfsinfo);
7409 break;
7412 case TRANSACT2_QPATHINFO:
7413 case TRANSACT2_QFILEINFO:
7415 START_PROFILE(Trans2_qpathinfo);
7416 call_trans2qfilepathinfo(conn, req, state->call,
7417 &state->param, state->total_param,
7418 &state->data, state->total_data,
7419 state->max_data_return);
7420 END_PROFILE(Trans2_qpathinfo);
7421 break;
7424 case TRANSACT2_SETPATHINFO:
7425 case TRANSACT2_SETFILEINFO:
7427 START_PROFILE(Trans2_setpathinfo);
7428 call_trans2setfilepathinfo(conn, req, state->call,
7429 &state->param, state->total_param,
7430 &state->data, state->total_data,
7431 state->max_data_return);
7432 END_PROFILE(Trans2_setpathinfo);
7433 break;
7436 case TRANSACT2_FINDNOTIFYFIRST:
7438 START_PROFILE(Trans2_findnotifyfirst);
7439 call_trans2findnotifyfirst(conn, req,
7440 &state->param, state->total_param,
7441 &state->data, state->total_data,
7442 state->max_data_return);
7443 END_PROFILE(Trans2_findnotifyfirst);
7444 break;
7447 case TRANSACT2_FINDNOTIFYNEXT:
7449 START_PROFILE(Trans2_findnotifynext);
7450 call_trans2findnotifynext(conn, req,
7451 &state->param, state->total_param,
7452 &state->data, state->total_data,
7453 state->max_data_return);
7454 END_PROFILE(Trans2_findnotifynext);
7455 break;
7458 case TRANSACT2_MKDIR:
7460 START_PROFILE(Trans2_mkdir);
7461 call_trans2mkdir(conn, req,
7462 &state->param, state->total_param,
7463 &state->data, state->total_data,
7464 state->max_data_return);
7465 END_PROFILE(Trans2_mkdir);
7466 break;
7469 case TRANSACT2_GET_DFS_REFERRAL:
7471 START_PROFILE(Trans2_get_dfs_referral);
7472 call_trans2getdfsreferral(conn, req,
7473 &state->param, state->total_param,
7474 &state->data, state->total_data,
7475 state->max_data_return);
7476 END_PROFILE(Trans2_get_dfs_referral);
7477 break;
7480 case TRANSACT2_IOCTL:
7482 START_PROFILE(Trans2_ioctl);
7483 call_trans2ioctl(conn, req,
7484 &state->param, state->total_param,
7485 &state->data, state->total_data,
7486 state->max_data_return);
7487 END_PROFILE(Trans2_ioctl);
7488 break;
7491 default:
7492 /* Error in request */
7493 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7494 reply_doserror(req, ERRSRV,ERRerror);
7498 /****************************************************************************
7499 Reply to a SMBtrans2.
7500 ****************************************************************************/
7502 void reply_trans2(struct smb_request *req)
7504 connection_struct *conn = req->conn;
7505 unsigned int dsoff;
7506 unsigned int dscnt;
7507 unsigned int psoff;
7508 unsigned int pscnt;
7509 unsigned int tran_call;
7510 unsigned int size;
7511 unsigned int av_size;
7512 struct trans_state *state;
7513 NTSTATUS result;
7515 START_PROFILE(SMBtrans2);
7517 if (req->wct < 14) {
7518 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7519 END_PROFILE(SMBtrans2);
7520 return;
7523 dsoff = SVAL(req->inbuf, smb_dsoff);
7524 dscnt = SVAL(req->inbuf, smb_dscnt);
7525 psoff = SVAL(req->inbuf, smb_psoff);
7526 pscnt = SVAL(req->inbuf, smb_pscnt);
7527 tran_call = SVAL(req->inbuf, smb_setup0);
7528 size = smb_len(req->inbuf) + 4;
7529 av_size = smb_len(req->inbuf);
7531 result = allow_new_trans(conn->pending_trans, req->mid);
7532 if (!NT_STATUS_IS_OK(result)) {
7533 DEBUG(2, ("Got invalid trans2 request: %s\n",
7534 nt_errstr(result)));
7535 reply_nterror(req, result);
7536 END_PROFILE(SMBtrans2);
7537 return;
7540 if (IS_IPC(conn)) {
7541 switch (tran_call) {
7542 /* List the allowed trans2 calls on IPC$ */
7543 case TRANSACT2_OPEN:
7544 case TRANSACT2_GET_DFS_REFERRAL:
7545 case TRANSACT2_QFILEINFO:
7546 case TRANSACT2_QFSINFO:
7547 case TRANSACT2_SETFSINFO:
7548 break;
7549 default:
7550 reply_doserror(req, ERRSRV, ERRaccess);
7551 END_PROFILE(SMBtrans2);
7552 return;
7556 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7557 DEBUG(0, ("talloc failed\n"));
7558 reply_nterror(req, NT_STATUS_NO_MEMORY);
7559 END_PROFILE(SMBtrans2);
7560 return;
7563 state->cmd = SMBtrans2;
7565 state->mid = req->mid;
7566 state->vuid = req->vuid;
7567 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7568 state->setup = NULL;
7569 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7570 state->param = NULL;
7571 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7572 state->data = NULL;
7573 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7574 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7575 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7576 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7577 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7579 state->call = tran_call;
7581 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7582 is so as a sanity check */
7583 if (state->setup_count != 1) {
7585 * Need to have rc=0 for ioctl to get job id for OS/2.
7586 * Network printing will fail if function is not successful.
7587 * Similar function in reply.c will be used if protocol
7588 * is LANMAN1.0 instead of LM1.2X002.
7589 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7590 * outbuf doesn't have to be set(only job id is used).
7592 if ( (state->setup_count == 4)
7593 && (tran_call == TRANSACT2_IOCTL)
7594 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7595 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7596 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7597 } else {
7598 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7599 DEBUG(2,("Transaction is %d\n",tran_call));
7600 TALLOC_FREE(state);
7601 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7602 END_PROFILE(SMBtrans2);
7603 return;
7607 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7608 goto bad_param;
7610 if (state->total_data) {
7611 /* Can't use talloc here, the core routines do realloc on the
7612 * params and data. */
7613 state->data = (char *)SMB_MALLOC(state->total_data);
7614 if (state->data == NULL) {
7615 DEBUG(0,("reply_trans2: data malloc fail for %u "
7616 "bytes !\n", (unsigned int)state->total_data));
7617 TALLOC_FREE(state);
7618 reply_nterror(req, NT_STATUS_NO_MEMORY);
7619 END_PROFILE(SMBtrans2);
7620 return;
7623 if (dscnt > state->total_data ||
7624 dsoff+dscnt < dsoff) {
7625 goto bad_param;
7628 if (dsoff > av_size ||
7629 dscnt > av_size ||
7630 dsoff+dscnt > av_size) {
7631 goto bad_param;
7634 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7637 if (state->total_param) {
7638 /* Can't use talloc here, the core routines do realloc on the
7639 * params and data. */
7640 state->param = (char *)SMB_MALLOC(state->total_param);
7641 if (state->param == NULL) {
7642 DEBUG(0,("reply_trans: param malloc fail for %u "
7643 "bytes !\n", (unsigned int)state->total_param));
7644 SAFE_FREE(state->data);
7645 TALLOC_FREE(state);
7646 reply_nterror(req, NT_STATUS_NO_MEMORY);
7647 END_PROFILE(SMBtrans2);
7648 return;
7651 if (pscnt > state->total_param ||
7652 psoff+pscnt < psoff) {
7653 goto bad_param;
7656 if (psoff > av_size ||
7657 pscnt > av_size ||
7658 psoff+pscnt > av_size) {
7659 goto bad_param;
7662 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7665 state->received_data = dscnt;
7666 state->received_param = pscnt;
7668 if ((state->received_param == state->total_param) &&
7669 (state->received_data == state->total_data)) {
7671 handle_trans2(conn, req, state);
7673 SAFE_FREE(state->data);
7674 SAFE_FREE(state->param);
7675 TALLOC_FREE(state);
7676 END_PROFILE(SMBtrans2);
7677 return;
7680 DLIST_ADD(conn->pending_trans, state);
7682 /* We need to send an interim response then receive the rest
7683 of the parameter/data bytes */
7684 reply_outbuf(req, 0, 0);
7685 show_msg((char *)req->outbuf);
7686 END_PROFILE(SMBtrans2);
7687 return;
7689 bad_param:
7691 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7692 SAFE_FREE(state->data);
7693 SAFE_FREE(state->param);
7694 TALLOC_FREE(state);
7695 END_PROFILE(SMBtrans2);
7696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7700 /****************************************************************************
7701 Reply to a SMBtranss2
7702 ****************************************************************************/
7704 void reply_transs2(struct smb_request *req)
7706 connection_struct *conn = req->conn;
7707 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7708 struct trans_state *state;
7709 unsigned int size;
7710 unsigned int av_size;
7712 START_PROFILE(SMBtranss2);
7714 show_msg((char *)req->inbuf);
7716 if (req->wct < 8) {
7717 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7718 END_PROFILE(SMBtranss2);
7719 return;
7722 size = smb_len(req->inbuf)+4;
7723 av_size = smb_len(req->inbuf);
7725 for (state = conn->pending_trans; state != NULL;
7726 state = state->next) {
7727 if (state->mid == req->mid) {
7728 break;
7732 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7733 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7734 END_PROFILE(SMBtranss2);
7735 return;
7738 /* Revise state->total_param and state->total_data in case they have
7739 changed downwards */
7741 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7742 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7743 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7744 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7746 pcnt = SVAL(req->inbuf, smb_spscnt);
7747 poff = SVAL(req->inbuf, smb_spsoff);
7748 pdisp = SVAL(req->inbuf, smb_spsdisp);
7750 dcnt = SVAL(req->inbuf, smb_sdscnt);
7751 doff = SVAL(req->inbuf, smb_sdsoff);
7752 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7754 state->received_param += pcnt;
7755 state->received_data += dcnt;
7757 if ((state->received_data > state->total_data) ||
7758 (state->received_param > state->total_param))
7759 goto bad_param;
7761 if (pcnt) {
7762 if (pdisp > state->total_param ||
7763 pcnt > state->total_param ||
7764 pdisp+pcnt > state->total_param ||
7765 pdisp+pcnt < pdisp) {
7766 goto bad_param;
7769 if (poff > av_size ||
7770 pcnt > av_size ||
7771 poff+pcnt > av_size ||
7772 poff+pcnt < poff) {
7773 goto bad_param;
7776 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7777 pcnt);
7780 if (dcnt) {
7781 if (ddisp > state->total_data ||
7782 dcnt > state->total_data ||
7783 ddisp+dcnt > state->total_data ||
7784 ddisp+dcnt < ddisp) {
7785 goto bad_param;
7788 if (ddisp > av_size ||
7789 dcnt > av_size ||
7790 ddisp+dcnt > av_size ||
7791 ddisp+dcnt < ddisp) {
7792 goto bad_param;
7795 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7796 dcnt);
7799 if ((state->received_param < state->total_param) ||
7800 (state->received_data < state->total_data)) {
7801 END_PROFILE(SMBtranss2);
7802 return;
7806 * construct_reply_common will copy smb_com from inbuf to
7807 * outbuf. SMBtranss2 is wrong here.
7809 SCVAL(req->inbuf,smb_com,SMBtrans2);
7811 handle_trans2(conn, req, state);
7813 DLIST_REMOVE(conn->pending_trans, state);
7814 SAFE_FREE(state->data);
7815 SAFE_FREE(state->param);
7816 TALLOC_FREE(state);
7818 END_PROFILE(SMBtranss2);
7819 return;
7821 bad_param:
7823 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7824 DLIST_REMOVE(conn->pending_trans, state);
7825 SAFE_FREE(state->data);
7826 SAFE_FREE(state->param);
7827 TALLOC_FREE(state);
7828 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7829 END_PROFILE(SMBtranss2);
7830 return;