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 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/>.
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,
39 const SMB_STRUCT_STAT *psbuf);
41 static char *store_file_unix_basic_info2(connection_struct *conn,
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);
63 /********************************************************************
64 Given a stat buffer return the allocated size on disk, taking into
66 ********************************************************************/
68 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
72 if(S_ISDIR(sbuf->st_mode)) {
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;
79 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
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,
106 for (i = 0; prohibited_ea_names[i]; i++) {
107 if (strequal( prohibited_ea_names[i], unix_ea_name))
113 /****************************************************************************
114 Get one EA value. Fill in a struct ea_struct.
115 ****************************************************************************/
117 static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
118 const char *fname, char *ea_name, struct ea_struct *pea)
120 /* Get the value of this xattr. Max size is 64k. */
121 size_t attr_size = 256;
127 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
132 if (fsp && fsp->fh->fd != -1) {
133 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
135 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
138 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
147 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
148 dump_data(10, (uint8 *)val, sizeret);
151 if (strnequal(ea_name, "user.", 5)) {
152 pea->name = &ea_name[5];
156 pea->value.data = (unsigned char *)val;
157 pea->value.length = (size_t)sizeret;
161 /****************************************************************************
162 Return a linked list of the total EA's. Plus the total size
163 ****************************************************************************/
165 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
166 const char *fname, size_t *pea_total_len)
168 /* Get a list of all xattrs. Max namesize is 64k. */
169 size_t ea_namelist_size = 1024;
174 struct ea_list *ea_list_head = NULL;
178 if (!lp_ea_support(SNUM(conn))) {
182 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
183 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
189 if (fsp && fsp->fh->fd != -1) {
190 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
192 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
195 if (sizeret == -1 && errno == ERANGE) {
196 ea_namelist_size *= 2;
205 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
208 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
209 struct ea_list *listp;
211 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
214 listp = TALLOC_P(mem_ctx, struct ea_list);
218 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
224 push_ascii_fstring(dos_ea_name, listp->ea.name);
225 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
226 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
227 (unsigned int)*pea_total_len, dos_ea_name,
228 (unsigned int)listp->ea.value.length ));
230 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
232 /* Add on 4 for total length. */
233 if (*pea_total_len) {
238 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
242 /****************************************************************************
243 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
245 ****************************************************************************/
247 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
248 connection_struct *conn, struct ea_list *ea_list)
250 unsigned int ret_data_size = 4;
253 SMB_ASSERT(total_data_size >= 4);
255 if (!lp_ea_support(SNUM(conn))) {
260 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
263 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
264 dos_namelen = strlen(dos_ea_name);
265 if (dos_namelen > 255 || dos_namelen == 0) {
268 if (ea_list->ea.value.length > 65535) {
271 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
275 /* We know we have room. */
276 SCVAL(p,0,ea_list->ea.flags);
277 SCVAL(p,1,dos_namelen);
278 SSVAL(p,2,ea_list->ea.value.length);
279 fstrcpy(p+4, dos_ea_name);
280 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
282 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
283 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
286 ret_data_size = PTR_DIFF(p, pdata);
287 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
288 SIVAL(pdata,0,ret_data_size);
289 return ret_data_size;
292 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
294 size_t total_ea_len = 0;
295 TALLOC_CTX *mem_ctx = NULL;
297 if (!lp_ea_support(SNUM(conn))) {
300 mem_ctx = talloc_init("estimate_ea_size");
301 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
302 talloc_destroy(mem_ctx);
306 /****************************************************************************
307 Ensure the EA name is case insensitive by matching any existing EA name.
308 ****************************************************************************/
310 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
313 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
314 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
316 for (; ea_list; ea_list = ea_list->next) {
317 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
318 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
319 &unix_ea_name[5], ea_list->ea.name));
320 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
324 talloc_destroy(mem_ctx);
327 /****************************************************************************
328 Set or delete an extended attribute.
329 ****************************************************************************/
331 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
333 if (!lp_ea_support(SNUM(conn))) {
334 return NT_STATUS_EAS_NOT_SUPPORTED;
337 for (;ea_list; ea_list = ea_list->next) {
339 fstring unix_ea_name;
341 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
342 fstrcat(unix_ea_name, ea_list->ea.name);
344 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
346 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
348 if (samba_private_attr_name(unix_ea_name)) {
349 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
350 return NT_STATUS_ACCESS_DENIED;
353 if (ea_list->ea.value.length == 0) {
354 /* Remove the attribute. */
355 if (fsp && (fsp->fh->fd != -1)) {
356 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
357 unix_ea_name, fsp->fsp_name));
358 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
360 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
361 unix_ea_name, fname));
362 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
365 /* Removing a non existent attribute always succeeds. */
366 if (ret == -1 && errno == ENOATTR) {
367 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
373 if (fsp && (fsp->fh->fd != -1)) {
374 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
375 unix_ea_name, fsp->fsp_name));
376 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
377 ea_list->ea.value.data, ea_list->ea.value.length, 0);
379 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
380 unix_ea_name, fname));
381 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
382 ea_list->ea.value.data, ea_list->ea.value.length, 0);
388 if (errno == ENOTSUP) {
389 return NT_STATUS_EAS_NOT_SUPPORTED;
392 return map_nt_error_from_unix(errno);
398 /****************************************************************************
399 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
400 ****************************************************************************/
402 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
404 struct ea_list *ea_list_head = NULL;
407 while (offset + 2 < data_size) {
408 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
409 unsigned int namelen = CVAL(pdata,offset);
411 offset++; /* Go past the namelen byte. */
413 /* integer wrap paranioa. */
414 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
415 (offset > data_size) || (namelen > data_size) ||
416 (offset + namelen >= data_size)) {
419 /* Ensure the name is null terminated. */
420 if (pdata[offset + namelen] != '\0') {
423 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
428 offset += (namelen + 1); /* Go past the name + terminating zero. */
429 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
430 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
436 /****************************************************************************
437 Read one EA list entry from the buffer.
438 ****************************************************************************/
440 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
442 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
444 unsigned int namelen;
454 eal->ea.flags = CVAL(pdata,0);
455 namelen = CVAL(pdata,1);
456 val_len = SVAL(pdata,2);
458 if (4 + namelen + 1 + val_len > data_size) {
462 /* Ensure the name is null terminated. */
463 if (pdata[namelen + 4] != '\0') {
466 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
471 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
472 if (!eal->ea.value.data) {
476 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
478 /* Ensure we're null terminated just in case we print the value. */
479 eal->ea.value.data[val_len] = '\0';
480 /* But don't count the null. */
481 eal->ea.value.length--;
484 *pbytes_used = 4 + namelen + 1 + val_len;
487 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
488 dump_data(10, eal->ea.value.data, eal->ea.value.length);
493 /****************************************************************************
494 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
495 ****************************************************************************/
497 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
499 struct ea_list *ea_list_head = NULL;
501 size_t bytes_used = 0;
503 while (offset < data_size) {
504 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
510 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
511 offset += bytes_used;
517 /****************************************************************************
518 Count the total EA size needed.
519 ****************************************************************************/
521 static size_t ea_list_size(struct ea_list *ealist)
524 struct ea_list *listp;
527 for (listp = ealist; listp; listp = listp->next) {
528 push_ascii_fstring(dos_ea_name, listp->ea.name);
529 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
531 /* Add on 4 for total length. */
539 /****************************************************************************
540 Return a union of EA's from a file list and a list of names.
541 The TALLOC context for the two lists *MUST* be identical as we steal
542 memory from one list to add to another. JRA.
543 ****************************************************************************/
545 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
547 struct ea_list *nlistp, *flistp;
549 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
550 for (flistp = file_list; flistp; flistp = flistp->next) {
551 if (strequal(nlistp->ea.name, flistp->ea.name)) {
557 /* Copy the data from this entry. */
558 nlistp->ea.flags = flistp->ea.flags;
559 nlistp->ea.value = flistp->ea.value;
562 nlistp->ea.flags = 0;
563 ZERO_STRUCT(nlistp->ea.value);
567 *total_ea_len = ea_list_size(name_list);
571 /****************************************************************************
572 Send the required number of replies back.
573 We assume all fields other than the data fields are
574 set correctly for the type of call.
575 HACK ! Always assumes smb_setup field is zero.
576 ****************************************************************************/
578 void send_trans2_replies(struct smb_request *req,
585 /* As we are using a protocol > LANMAN1 then the max_send
586 variable must have been set in the sessetupX call.
587 This takes precedence over the max_xmit field in the
588 global struct. These different max_xmit variables should
589 be merged as this is now too confusing */
591 int data_to_send = datasize;
592 int params_to_send = paramsize;
594 const char *pp = params;
595 const char *pd = pdata;
596 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
597 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
598 int data_alignment_offset = 0;
599 bool overflow = False;
601 /* Modify the data_to_send and datasize and set the error if
602 we're trying to send more than max_data_bytes. We still send
603 the part of the packet(s) that fit. Strange, but needed
606 if (max_data_bytes > 0 && datasize > max_data_bytes) {
607 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
608 max_data_bytes, datasize ));
609 datasize = data_to_send = max_data_bytes;
613 /* If there genuinely are no parameters or data to send just send the empty packet */
615 if(params_to_send == 0 && data_to_send == 0) {
616 reply_outbuf(req, 10, 0);
617 show_msg((char *)req->outbuf);
621 /* When sending params and data ensure that both are nicely aligned */
622 /* Only do this alignment when there is also data to send - else
623 can cause NT redirector problems. */
625 if (((params_to_send % 4) != 0) && (data_to_send != 0))
626 data_alignment_offset = 4 - (params_to_send % 4);
628 /* Space is bufsize minus Netbios over TCP header minus SMB header */
629 /* The alignment_offset is to align the param bytes on an even byte
630 boundary. NT 4.0 Beta needs this to work correctly. */
632 useable_space = max_send - (smb_size
635 + data_alignment_offset);
637 /* useable_space can never be more than max_send minus the alignment offset. */
639 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
641 while (params_to_send || data_to_send) {
642 /* Calculate whether we will totally or partially fill this packet */
644 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
646 /* We can never send more than useable_space */
648 * Note that 'useable_space' does not include the alignment offsets,
649 * but we must include the alignment offsets in the calculation of
650 * the length of the data we send over the wire, as the alignment offsets
651 * are sent here. Fix from Marc_Jacobsen@hp.com.
654 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
656 reply_outbuf(req, 10, total_sent_thistime);
658 /* Set total params and data to be sent */
659 SSVAL(req->outbuf,smb_tprcnt,paramsize);
660 SSVAL(req->outbuf,smb_tdrcnt,datasize);
662 /* Calculate how many parameters and data we can fit into
663 * this packet. Parameters get precedence
666 params_sent_thistime = MIN(params_to_send,useable_space);
667 data_sent_thistime = useable_space - params_sent_thistime;
668 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
670 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
672 /* smb_proff is the offset from the start of the SMB header to the
673 parameter bytes, however the first 4 bytes of outbuf are
674 the Netbios over TCP header. Thus use smb_base() to subtract
675 them from the calculation */
677 SSVAL(req->outbuf,smb_proff,
678 ((smb_buf(req->outbuf)+alignment_offset)
679 - smb_base(req->outbuf)));
681 if(params_sent_thistime == 0)
682 SSVAL(req->outbuf,smb_prdisp,0);
684 /* Absolute displacement of param bytes sent in this packet */
685 SSVAL(req->outbuf,smb_prdisp,pp - params);
687 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
688 if(data_sent_thistime == 0) {
689 SSVAL(req->outbuf,smb_droff,0);
690 SSVAL(req->outbuf,smb_drdisp, 0);
692 /* The offset of the data bytes is the offset of the
693 parameter bytes plus the number of parameters being sent this time */
694 SSVAL(req->outbuf, smb_droff,
695 ((smb_buf(req->outbuf)+alignment_offset)
696 - smb_base(req->outbuf))
697 + params_sent_thistime + data_alignment_offset);
698 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
701 /* Initialize the padding for alignment */
703 if (alignment_offset != 0) {
704 memset(smb_buf(req->outbuf), 0, alignment_offset);
707 /* Copy the param bytes into the packet */
709 if(params_sent_thistime) {
710 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
711 params_sent_thistime);
714 /* Copy in the data bytes */
715 if(data_sent_thistime) {
716 if (data_alignment_offset != 0) {
717 memset((smb_buf(req->outbuf)+alignment_offset+
718 params_sent_thistime), 0,
719 data_alignment_offset);
721 memcpy(smb_buf(req->outbuf)+alignment_offset
722 +params_sent_thistime+data_alignment_offset,
723 pd,data_sent_thistime);
726 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
727 params_sent_thistime, data_sent_thistime, useable_space));
728 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
729 params_to_send, data_to_send, paramsize, datasize));
732 error_packet_set((char *)req->outbuf,
733 ERRDOS,ERRbufferoverflow,
734 STATUS_BUFFER_OVERFLOW,
738 /* Send the packet */
739 show_msg((char *)req->outbuf);
740 if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
741 exit_server_cleanly("send_trans2_replies: send_smb failed.");
743 TALLOC_FREE(req->outbuf);
745 pp += params_sent_thistime;
746 pd += data_sent_thistime;
748 params_to_send -= params_sent_thistime;
749 data_to_send -= data_sent_thistime;
752 if(params_to_send < 0 || data_to_send < 0) {
753 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
754 params_to_send, data_to_send));
762 /****************************************************************************
763 Reply to a TRANSACT2_OPEN.
764 ****************************************************************************/
766 static void call_trans2open(connection_struct *conn,
767 struct smb_request *req,
768 char **pparams, int total_params,
769 char **ppdata, int total_data,
770 unsigned int max_data_bytes)
772 char *params = *pparams;
773 char *pdata = *ppdata;
778 bool return_additional_info;
789 SMB_STRUCT_STAT sbuf;
792 struct ea_list *ea_list = NULL;
797 uint32 create_disposition;
798 uint32 create_options = 0;
799 TALLOC_CTX *ctx = talloc_tos();
802 * Ensure we have enough parameters to perform the operation.
805 if (total_params < 29) {
806 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
810 flags = SVAL(params, 0);
811 deny_mode = SVAL(params, 2);
812 open_attr = SVAL(params,6);
813 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
814 if (oplock_request) {
815 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
819 return_additional_info = BITSETW(params,0);
820 open_sattr = SVAL(params, 4);
821 open_time = make_unix_date3(params+8);
823 open_ofun = SVAL(params,12);
824 open_size = IVAL(params,14);
828 reply_doserror(req, ERRSRV, ERRaccess);
832 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
833 total_params - 28, STR_TERMINATE,
835 if (!NT_STATUS_IS_OK(status)) {
836 reply_nterror(req, status);
840 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
841 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
842 (unsigned int)open_ofun, open_size));
844 /* XXXX we need to handle passed times, sattr and flags */
846 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
847 if (!NT_STATUS_IS_OK(status)) {
848 reply_nterror(req, status);
852 status = check_name(conn, fname);
853 if (!NT_STATUS_IS_OK(status)) {
854 reply_nterror(req, status);
858 if (open_ofun == 0) {
859 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
863 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
868 reply_doserror(req, ERRDOS, ERRbadaccess);
872 /* Any data in this call is an EA list. */
873 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
874 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
878 if (total_data != 4) {
879 if (total_data < 10) {
880 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
884 if (IVAL(pdata,0) > total_data) {
885 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
886 IVAL(pdata,0), (unsigned int)total_data));
887 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
891 ea_list = read_ea_list(talloc_tos(), pdata + 4,
894 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
897 } else if (IVAL(pdata,0) != 4) {
898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
902 status = open_file_ntcreate(conn, req, fname, &sbuf,
911 if (!NT_STATUS_IS_OK(status)) {
912 if (open_was_deferred(req->mid)) {
913 /* We have re-scheduled this call. */
916 reply_openerror(req, status);
920 size = get_file_size(sbuf);
921 fattr = dos_mode(conn,fname,&sbuf);
922 mtime = sbuf.st_mtime;
925 close_file(fsp,ERROR_CLOSE);
926 reply_doserror(req, ERRDOS,ERRnoaccess);
930 /* Save the requested allocation size. */
931 /* Allocate space for the file if a size hint is supplied */
932 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
933 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
934 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
935 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
936 if (fsp->is_directory) {
937 close_file(fsp,ERROR_CLOSE);
938 /* Can't set allocation size on a directory. */
939 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
942 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
943 close_file(fsp,ERROR_CLOSE);
944 reply_nterror(req, NT_STATUS_DISK_FULL);
948 /* Adjust size here to return the right size in the reply.
949 Windows does it this way. */
950 size = fsp->initial_allocation_size;
952 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
956 if (ea_list && smb_action == FILE_WAS_CREATED) {
957 status = set_ea(conn, fsp, fname, ea_list);
958 if (!NT_STATUS_IS_OK(status)) {
959 close_file(fsp,ERROR_CLOSE);
960 reply_nterror(req, status);
965 /* Realloc the size of parameters and data we will return */
966 *pparams = (char *)SMB_REALLOC(*pparams, 30);
967 if(*pparams == NULL ) {
968 reply_nterror(req, NT_STATUS_NO_MEMORY);
973 SSVAL(params,0,fsp->fnum);
974 SSVAL(params,2,fattr);
975 srv_put_dos_date2(params,4, mtime);
976 SIVAL(params,8, (uint32)size);
977 SSVAL(params,12,deny_mode);
978 SSVAL(params,14,0); /* open_type - file or directory. */
979 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
981 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
982 smb_action |= EXTENDED_OPLOCK_GRANTED;
985 SSVAL(params,18,smb_action);
988 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
990 SIVAL(params,20,inode);
991 SSVAL(params,24,0); /* Padding. */
993 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
994 SIVAL(params, 26, ea_size);
996 SIVAL(params, 26, 0);
999 /* Send the required number of replies */
1000 send_trans2_replies(req, params, 30, *ppdata, 0, max_data_bytes);
1003 /*********************************************************
1004 Routine to check if a given string matches exactly.
1005 as a special case a mask of "." does NOT match. That
1006 is required for correct wildcard semantics
1007 Case can be significant or not.
1008 **********************************************************/
1010 static bool exact_match(connection_struct *conn,
1014 if (mask[0] == '.' && mask[1] == 0)
1016 if (conn->case_sensitive)
1017 return strcmp(str,mask)==0;
1018 if (StrCaseCmp(str,mask) != 0) {
1021 if (dptr_has_wild(conn->dirptr)) {
1027 /****************************************************************************
1028 Return the filetype for UNIX extensions.
1029 ****************************************************************************/
1031 static uint32 unix_filetype(mode_t mode)
1034 return UNIX_TYPE_FILE;
1035 else if(S_ISDIR(mode))
1036 return UNIX_TYPE_DIR;
1038 else if(S_ISLNK(mode))
1039 return UNIX_TYPE_SYMLINK;
1042 else if(S_ISCHR(mode))
1043 return UNIX_TYPE_CHARDEV;
1046 else if(S_ISBLK(mode))
1047 return UNIX_TYPE_BLKDEV;
1050 else if(S_ISFIFO(mode))
1051 return UNIX_TYPE_FIFO;
1054 else if(S_ISSOCK(mode))
1055 return UNIX_TYPE_SOCKET;
1058 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1059 return UNIX_TYPE_UNKNOWN;
1062 /****************************************************************************
1063 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1064 ****************************************************************************/
1066 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1068 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1069 SMB_STRUCT_STAT *psbuf,
1071 enum perm_type ptype,
1076 if (perms == SMB_MODE_NO_CHANGE) {
1077 if (!VALID_STAT(*psbuf)) {
1078 return NT_STATUS_INVALID_PARAMETER;
1080 *ret_perms = psbuf->st_mode;
1081 return NT_STATUS_OK;
1085 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1086 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1087 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1088 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1089 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1090 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1091 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1092 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1093 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1095 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1098 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1101 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1106 /* Apply mode mask */
1107 ret &= lp_create_mask(SNUM(conn));
1108 /* Add in force bits */
1109 ret |= lp_force_create_mode(SNUM(conn));
1112 ret &= lp_dir_mask(SNUM(conn));
1113 /* Add in force bits */
1114 ret |= lp_force_dir_mode(SNUM(conn));
1116 case PERM_EXISTING_FILE:
1117 /* Apply mode mask */
1118 ret &= lp_security_mask(SNUM(conn));
1119 /* Add in force bits */
1120 ret |= lp_force_security_mode(SNUM(conn));
1122 case PERM_EXISTING_DIR:
1123 /* Apply mode mask */
1124 ret &= lp_dir_security_mask(SNUM(conn));
1125 /* Add in force bits */
1126 ret |= lp_force_dir_security_mode(SNUM(conn));
1131 return NT_STATUS_OK;
1134 /****************************************************************************
1135 Get a level dependent lanman2 dir entry.
1136 ****************************************************************************/
1138 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1139 connection_struct *conn,
1141 const char *path_mask,
1144 int requires_resume_key,
1149 int space_remaining,
1151 bool *got_exact_match,
1152 int *last_entry_off,
1153 struct ea_list *name_list)
1157 SMB_STRUCT_STAT sbuf;
1158 const char *mask = NULL;
1159 char *pathreal = NULL;
1160 const char *fname = NULL;
1161 char *p, *q, *pdata = *ppdata;
1165 SMB_OFF_T file_size = 0;
1166 SMB_BIG_UINT allocation_size = 0;
1168 struct timespec mdate_ts, adate_ts, create_date_ts;
1169 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1171 char *last_entry_ptr;
1173 uint32 nt_extmode; /* Used for NT connections instead of mode */
1174 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1175 bool check_mangled_names = lp_manglednames(conn->params);
1176 char mangled_name[13]; /* mangled 8.3 name. */
1178 *out_of_space = False;
1179 *got_exact_match = False;
1181 ZERO_STRUCT(mdate_ts);
1182 ZERO_STRUCT(adate_ts);
1183 ZERO_STRUCT(create_date_ts);
1185 if (!conn->dirptr) {
1189 p = strrchr_m(path_mask,'/');
1192 mask = talloc_strdup(ctx,"*.*");
1202 bool ms_dfs_link = False;
1204 /* Needed if we run out of space */
1205 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1206 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1209 * Due to bugs in NT client redirectors we are not using
1210 * resume keys any more - set them to zero.
1211 * Check out the related comments in findfirst/findnext.
1217 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1218 (long)conn->dirptr,curr_dirpos));
1225 * fname may get mangled, dname is never mangled.
1226 * Whenever we're accessing the filesystem we use
1227 * pathreal which is composed from dname.
1233 /* Mangle fname if it's an illegal name. */
1234 if (mangle_must_mangle(dname,conn->params)) {
1235 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1236 continue; /* Error - couldn't mangle. */
1238 fname = mangled_name;
1241 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1242 got_match = mask_match(fname, mask, conn->case_sensitive);
1245 if(!got_match && check_mangled_names &&
1246 !mangle_is_8_3(fname, False, conn->params)) {
1248 * It turns out that NT matches wildcards against
1249 * both long *and* short names. This may explain some
1250 * of the wildcard wierdness from old DOS clients
1251 * that some people have been seeing.... JRA.
1253 /* Force the mangling into 8.3. */
1254 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1255 continue; /* Error - couldn't mangle. */
1258 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1259 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1264 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1266 if (dont_descend && !isdots) {
1272 pathreal = talloc_asprintf(ctx,
1277 pathreal = talloc_asprintf(ctx,
1287 if (INFO_LEVEL_IS_UNIX(info_level)) {
1288 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1289 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1290 pathreal,strerror(errno)));
1291 TALLOC_FREE(pathreal);
1294 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1295 /* Needed to show the msdfs symlinks as
1298 if(lp_host_msdfs() &&
1299 lp_msdfs_root(SNUM(conn)) &&
1300 ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) {
1301 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1304 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1308 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1309 pathreal,strerror(errno)));
1310 TALLOC_FREE(pathreal);
1316 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1318 mode = dos_mode(conn,pathreal,&sbuf);
1321 if (!dir_check_ftype(conn,mode,dirtype)) {
1322 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1323 TALLOC_FREE(pathreal);
1327 if (!(mode & aDIR)) {
1328 file_size = get_file_size(sbuf);
1330 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1332 mdate_ts = get_mtimespec(&sbuf);
1333 adate_ts = get_atimespec(&sbuf);
1334 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1336 if (lp_dos_filetime_resolution(SNUM(conn))) {
1337 dos_filetime_timespec(&create_date_ts);
1338 dos_filetime_timespec(&mdate_ts);
1339 dos_filetime_timespec(&adate_ts);
1342 create_date = convert_timespec_to_time_t(create_date_ts);
1343 mdate = convert_timespec_to_time_t(mdate_ts);
1344 adate = convert_timespec_to_time_t(adate_ts);
1346 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1350 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1357 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1359 switch (info_level) {
1360 case SMB_FIND_INFO_STANDARD:
1361 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1362 if(requires_resume_key) {
1366 srv_put_dos_date2(p,0,create_date);
1367 srv_put_dos_date2(p,4,adate);
1368 srv_put_dos_date2(p,8,mdate);
1369 SIVAL(p,12,(uint32)file_size);
1370 SIVAL(p,16,(uint32)allocation_size);
1374 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1375 p += ucs2_align(base_data, p, 0);
1377 len = srvstr_push(base_data, flags2, p,
1378 fname, PTR_DIFF(end_data, p),
1380 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1382 SCVAL(nameptr, -1, len - 2);
1384 SCVAL(nameptr, -1, 0);
1388 SCVAL(nameptr, -1, len - 1);
1390 SCVAL(nameptr, -1, 0);
1396 case SMB_FIND_EA_SIZE:
1397 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1398 if(requires_resume_key) {
1402 srv_put_dos_date2(p,0,create_date);
1403 srv_put_dos_date2(p,4,adate);
1404 srv_put_dos_date2(p,8,mdate);
1405 SIVAL(p,12,(uint32)file_size);
1406 SIVAL(p,16,(uint32)allocation_size);
1409 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1410 SIVAL(p,22,ea_size); /* Extended attributes */
1414 len = srvstr_push(base_data, flags2,
1415 p, fname, PTR_DIFF(end_data, p),
1416 STR_TERMINATE | STR_NOALIGN);
1417 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1430 SCVAL(nameptr,0,len);
1432 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1435 case SMB_FIND_EA_LIST:
1437 struct ea_list *file_list = NULL;
1440 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1444 if(requires_resume_key) {
1448 srv_put_dos_date2(p,0,create_date);
1449 srv_put_dos_date2(p,4,adate);
1450 srv_put_dos_date2(p,8,mdate);
1451 SIVAL(p,12,(uint32)file_size);
1452 SIVAL(p,16,(uint32)allocation_size);
1454 p += 22; /* p now points to the EA area. */
1456 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1457 name_list = ea_list_union(name_list, file_list, &ea_len);
1459 /* We need to determine if this entry will fit in the space available. */
1460 /* Max string size is 255 bytes. */
1461 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1462 /* Move the dirptr back to prev_dirpos */
1463 dptr_SeekDir(conn->dirptr, prev_dirpos);
1464 *out_of_space = True;
1465 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1466 return False; /* Not finished - just out of space */
1469 /* Push the ea_data followed by the name. */
1470 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1472 len = srvstr_push(base_data, flags2,
1473 p + 1, fname, PTR_DIFF(end_data, p+1),
1474 STR_TERMINATE | STR_NOALIGN);
1475 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1488 SCVAL(nameptr,0,len);
1490 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1494 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1495 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1496 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1498 SIVAL(p,0,reskey); p += 4;
1499 put_long_date_timespec(p,create_date_ts); p += 8;
1500 put_long_date_timespec(p,adate_ts); p += 8;
1501 put_long_date_timespec(p,mdate_ts); p += 8;
1502 put_long_date_timespec(p,mdate_ts); p += 8;
1503 SOFF_T(p,0,file_size); p += 8;
1504 SOFF_T(p,0,allocation_size); p += 8;
1505 SIVAL(p,0,nt_extmode); p += 4;
1506 q = p; p += 4; /* q is placeholder for name length. */
1508 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1509 SIVAL(p,0,ea_size); /* Extended attributes */
1512 /* Clear the short name buffer. This is
1513 * IMPORTANT as not doing so will trigger
1514 * a Win2k client bug. JRA.
1516 if (!was_8_3 && check_mangled_names) {
1517 if (!name_to_8_3(fname,mangled_name,True,
1519 /* Error - mangle failed ! */
1520 memset(mangled_name,'\0',12);
1522 mangled_name[12] = 0;
1523 len = srvstr_push(base_data, flags2,
1524 p+2, mangled_name, 24,
1525 STR_UPPER|STR_UNICODE);
1527 memset(p + 2 + len,'\0',24 - len);
1534 len = srvstr_push(base_data, flags2, p,
1535 fname, PTR_DIFF(end_data, p),
1536 STR_TERMINATE_ASCII);
1539 SIVAL(p,0,0); /* Ensure any padding is null. */
1540 len = PTR_DIFF(p, pdata);
1541 len = (len + 3) & ~3;
1546 case SMB_FIND_FILE_DIRECTORY_INFO:
1547 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1549 SIVAL(p,0,reskey); p += 4;
1550 put_long_date_timespec(p,create_date_ts); p += 8;
1551 put_long_date_timespec(p,adate_ts); p += 8;
1552 put_long_date_timespec(p,mdate_ts); p += 8;
1553 put_long_date_timespec(p,mdate_ts); p += 8;
1554 SOFF_T(p,0,file_size); p += 8;
1555 SOFF_T(p,0,allocation_size); p += 8;
1556 SIVAL(p,0,nt_extmode); p += 4;
1557 len = srvstr_push(base_data, flags2,
1558 p + 4, fname, PTR_DIFF(end_data, p+4),
1559 STR_TERMINATE_ASCII);
1562 SIVAL(p,0,0); /* Ensure any padding is null. */
1563 len = PTR_DIFF(p, pdata);
1564 len = (len + 3) & ~3;
1569 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1570 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1572 SIVAL(p,0,reskey); p += 4;
1573 put_long_date_timespec(p,create_date_ts); p += 8;
1574 put_long_date_timespec(p,adate_ts); p += 8;
1575 put_long_date_timespec(p,mdate_ts); p += 8;
1576 put_long_date_timespec(p,mdate_ts); p += 8;
1577 SOFF_T(p,0,file_size); p += 8;
1578 SOFF_T(p,0,allocation_size); p += 8;
1579 SIVAL(p,0,nt_extmode); p += 4;
1580 q = p; p += 4; /* q is placeholder for name length. */
1582 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1583 SIVAL(p,0,ea_size); /* Extended attributes */
1586 len = srvstr_push(base_data, flags2, p,
1587 fname, PTR_DIFF(end_data, p),
1588 STR_TERMINATE_ASCII);
1592 SIVAL(p,0,0); /* Ensure any padding is null. */
1593 len = PTR_DIFF(p, pdata);
1594 len = (len + 3) & ~3;
1599 case SMB_FIND_FILE_NAMES_INFO:
1600 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1602 SIVAL(p,0,reskey); p += 4;
1604 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1605 acl on a dir (tridge) */
1606 len = srvstr_push(base_data, flags2, p,
1607 fname, PTR_DIFF(end_data, p),
1608 STR_TERMINATE_ASCII);
1611 SIVAL(p,0,0); /* Ensure any padding is null. */
1612 len = PTR_DIFF(p, pdata);
1613 len = (len + 3) & ~3;
1618 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1619 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1621 SIVAL(p,0,reskey); p += 4;
1622 put_long_date_timespec(p,create_date_ts); p += 8;
1623 put_long_date_timespec(p,adate_ts); p += 8;
1624 put_long_date_timespec(p,mdate_ts); p += 8;
1625 put_long_date_timespec(p,mdate_ts); p += 8;
1626 SOFF_T(p,0,file_size); p += 8;
1627 SOFF_T(p,0,allocation_size); p += 8;
1628 SIVAL(p,0,nt_extmode); p += 4;
1629 q = p; p += 4; /* q is placeholder for name length. */
1631 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1632 SIVAL(p,0,ea_size); /* Extended attributes */
1635 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1636 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1637 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1638 len = srvstr_push(base_data, flags2, p,
1639 fname, PTR_DIFF(end_data, p),
1640 STR_TERMINATE_ASCII);
1643 SIVAL(p,0,0); /* Ensure any padding is null. */
1644 len = PTR_DIFF(p, pdata);
1645 len = (len + 3) & ~3;
1650 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1651 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1652 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1654 SIVAL(p,0,reskey); p += 4;
1655 put_long_date_timespec(p,create_date_ts); p += 8;
1656 put_long_date_timespec(p,adate_ts); p += 8;
1657 put_long_date_timespec(p,mdate_ts); p += 8;
1658 put_long_date_timespec(p,mdate_ts); p += 8;
1659 SOFF_T(p,0,file_size); p += 8;
1660 SOFF_T(p,0,allocation_size); p += 8;
1661 SIVAL(p,0,nt_extmode); p += 4;
1662 q = p; p += 4; /* q is placeholder for name length */
1664 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1665 SIVAL(p,0,ea_size); /* Extended attributes */
1668 /* Clear the short name buffer. This is
1669 * IMPORTANT as not doing so will trigger
1670 * a Win2k client bug. JRA.
1672 if (!was_8_3 && check_mangled_names) {
1673 if (!name_to_8_3(fname,mangled_name,True,
1675 /* Error - mangle failed ! */
1676 memset(mangled_name,'\0',12);
1678 mangled_name[12] = 0;
1679 len = srvstr_push(base_data, flags2,
1680 p+2, mangled_name, 24,
1681 STR_UPPER|STR_UNICODE);
1684 memset(p + 2 + len,'\0',24 - len);
1691 SSVAL(p,0,0); p += 2; /* Reserved ? */
1692 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1693 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1694 len = srvstr_push(base_data, flags2, p,
1695 fname, PTR_DIFF(end_data, p),
1696 STR_TERMINATE_ASCII);
1699 SIVAL(p,0,0); /* Ensure any padding is null. */
1700 len = PTR_DIFF(p, pdata);
1701 len = (len + 3) & ~3;
1706 /* CIFS UNIX Extension. */
1708 case SMB_FIND_FILE_UNIX:
1709 case SMB_FIND_FILE_UNIX_INFO2:
1711 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1713 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1715 if (info_level == SMB_FIND_FILE_UNIX) {
1716 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1717 p = store_file_unix_basic(conn, p,
1719 len = srvstr_push(base_data, flags2, p,
1720 fname, PTR_DIFF(end_data, p),
1723 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1724 p = store_file_unix_basic_info2(conn, p,
1728 len = srvstr_push(base_data, flags2, p, fname,
1729 PTR_DIFF(end_data, p), 0);
1730 SIVAL(nameptr, 0, len);
1734 SIVAL(p,0,0); /* Ensure any padding is null. */
1736 len = PTR_DIFF(p, pdata);
1737 len = (len + 3) & ~3;
1738 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1740 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1749 if (PTR_DIFF(p,pdata) > space_remaining) {
1750 /* Move the dirptr back to prev_dirpos */
1751 dptr_SeekDir(conn->dirptr, prev_dirpos);
1752 *out_of_space = True;
1753 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1754 return False; /* Not finished - just out of space */
1757 /* Setup the last entry pointer, as an offset from base_data */
1758 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1759 /* Advance the data pointer to the next slot */
1765 /****************************************************************************
1766 Reply to a TRANS2_FINDFIRST.
1767 ****************************************************************************/
1769 static void call_trans2findfirst(connection_struct *conn,
1770 struct smb_request *req,
1771 char **pparams, int total_params,
1772 char **ppdata, int total_data,
1773 unsigned int max_data_bytes)
1775 /* We must be careful here that we don't return more than the
1776 allowed number of data bytes. If this means returning fewer than
1777 maxentries then so be it. We assume that the redirector has
1778 enough room for the fixed number of parameter bytes it has
1780 char *params = *pparams;
1781 char *pdata = *ppdata;
1785 uint16 findfirst_flags;
1786 bool close_after_first;
1788 bool requires_resume_key;
1790 char *directory = NULL;
1791 const char *mask = NULL;
1793 int last_entry_off=0;
1797 bool finished = False;
1798 bool dont_descend = False;
1799 bool out_of_space = False;
1800 int space_remaining;
1801 bool mask_contains_wcard = False;
1802 SMB_STRUCT_STAT sbuf;
1803 struct ea_list *ea_list = NULL;
1804 NTSTATUS ntstatus = NT_STATUS_OK;
1805 TALLOC_CTX *ctx = talloc_tos();
1807 if (total_params < 13) {
1808 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1812 dirtype = SVAL(params,0);
1813 maxentries = SVAL(params,2);
1814 findfirst_flags = SVAL(params,4);
1815 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1816 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1817 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1818 info_level = SVAL(params,6);
1820 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1821 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1822 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1823 info_level, max_data_bytes));
1826 /* W2K3 seems to treat zero as 1. */
1830 switch (info_level) {
1831 case SMB_FIND_INFO_STANDARD:
1832 case SMB_FIND_EA_SIZE:
1833 case SMB_FIND_EA_LIST:
1834 case SMB_FIND_FILE_DIRECTORY_INFO:
1835 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1836 case SMB_FIND_FILE_NAMES_INFO:
1837 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1838 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1839 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1841 case SMB_FIND_FILE_UNIX:
1842 case SMB_FIND_FILE_UNIX_INFO2:
1843 if (!lp_unix_extensions()) {
1844 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1849 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1853 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1854 params+12, total_params - 12,
1855 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1856 if (!NT_STATUS_IS_OK(ntstatus)) {
1857 reply_nterror(req, ntstatus);
1861 ntstatus = resolve_dfspath_wcard(ctx, conn,
1862 req->flags2 & FLAGS2_DFS_PATHNAMES,
1865 &mask_contains_wcard);
1866 if (!NT_STATUS_IS_OK(ntstatus)) {
1867 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1868 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1869 ERRSRV, ERRbadpath);
1872 reply_nterror(req, ntstatus);
1876 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1877 if (!NT_STATUS_IS_OK(ntstatus)) {
1878 reply_nterror(req, ntstatus);
1882 ntstatus = check_name(conn, directory);
1883 if (!NT_STATUS_IS_OK(ntstatus)) {
1884 reply_nterror(req, ntstatus);
1888 p = strrchr_m(directory,'/');
1890 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1891 if((directory[0] == '.') && (directory[1] == '\0')) {
1893 mask_contains_wcard = True;
1897 directory = talloc_strdup(talloc_tos(), "./");
1899 reply_nterror(req, NT_STATUS_NO_MEMORY);
1907 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1909 if (info_level == SMB_FIND_EA_LIST) {
1912 if (total_data < 4) {
1913 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1917 ea_size = IVAL(pdata,0);
1918 if (ea_size != total_data) {
1919 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1920 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1921 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1925 if (!lp_ea_support(SNUM(conn))) {
1926 reply_doserror(req, ERRDOS, ERReasnotsupported);
1930 /* Pull out the list of names. */
1931 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1933 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1938 *ppdata = (char *)SMB_REALLOC(
1939 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1940 if(*ppdata == NULL ) {
1941 reply_nterror(req, NT_STATUS_NO_MEMORY);
1945 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1947 /* Realloc the params space */
1948 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1949 if (*pparams == NULL) {
1950 reply_nterror(req, NT_STATUS_NO_MEMORY);
1955 /* Save the wildcard match and attribs we are using on this directory -
1956 needed as lanman2 assumes these are being saved between calls */
1958 ntstatus = dptr_create(conn,
1964 mask_contains_wcard,
1968 if (!NT_STATUS_IS_OK(ntstatus)) {
1969 reply_nterror(req, ntstatus);
1973 dptr_num = dptr_dnum(conn->dirptr);
1974 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1976 /* We don't need to check for VOL here as this is returned by
1977 a different TRANS2 call. */
1979 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1980 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1981 dont_descend = True;
1984 space_remaining = max_data_bytes;
1985 out_of_space = False;
1987 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1988 bool got_exact_match = False;
1990 /* this is a heuristic to avoid seeking the dirptr except when
1991 absolutely necessary. It allows for a filename of about 40 chars */
1992 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1993 out_of_space = True;
1996 TALLOC_CTX *sub_ctx = talloc_stackframe();
1998 finished = !get_lanman2_dir_entry(sub_ctx,
2001 mask,dirtype,info_level,
2002 requires_resume_key,dont_descend,
2004 space_remaining, &out_of_space,
2006 &last_entry_off, ea_list);
2008 TALLOC_FREE(sub_ctx);
2011 if (finished && out_of_space)
2014 if (!finished && !out_of_space)
2018 * As an optimisation if we know we aren't looking
2019 * for a wildcard name (ie. the name matches the wildcard exactly)
2020 * then we can finish on any (first) match.
2021 * This speeds up large directory searches. JRA.
2027 /* Ensure space_remaining never goes -ve. */
2028 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2029 space_remaining = 0;
2030 out_of_space = true;
2032 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2036 /* Check if we can close the dirptr */
2037 if(close_after_first || (finished && close_if_end)) {
2038 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2039 dptr_close(&dptr_num);
2043 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2044 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2045 * the protocol level is less than NT1. Tested with smbclient. JRA.
2046 * This should fix the OS/2 client bug #2335.
2049 if(numentries == 0) {
2050 dptr_close(&dptr_num);
2051 if (Protocol < PROTOCOL_NT1) {
2052 reply_doserror(req, ERRDOS, ERRnofiles);
2055 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2056 ERRDOS, ERRbadfile);
2061 /* At this point pdata points to numentries directory entries. */
2063 /* Set up the return parameter block */
2064 SSVAL(params,0,dptr_num);
2065 SSVAL(params,2,numentries);
2066 SSVAL(params,4,finished);
2067 SSVAL(params,6,0); /* Never an EA error */
2068 SSVAL(params,8,last_entry_off);
2070 send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
2073 if ((! *directory) && dptr_path(dptr_num)) {
2074 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2076 reply_nterror(req, NT_STATUS_NO_MEMORY);
2080 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2081 smb_fn_name(CVAL(req->inbuf,smb_com)),
2082 mask, directory, dirtype, numentries ) );
2085 * Force a name mangle here to ensure that the
2086 * mask as an 8.3 name is top of the mangled cache.
2087 * The reasons for this are subtle. Don't remove
2088 * this code unless you know what you are doing
2089 * (see PR#13758). JRA.
2092 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2093 char mangled_name[13];
2094 name_to_8_3(mask, mangled_name, True, conn->params);
2100 /****************************************************************************
2101 Reply to a TRANS2_FINDNEXT.
2102 ****************************************************************************/
2104 static void call_trans2findnext(connection_struct *conn,
2105 struct smb_request *req,
2106 char **pparams, int total_params,
2107 char **ppdata, int total_data,
2108 unsigned int max_data_bytes)
2110 /* We must be careful here that we don't return more than the
2111 allowed number of data bytes. If this means returning fewer than
2112 maxentries then so be it. We assume that the redirector has
2113 enough room for the fixed number of parameter bytes it has
2115 char *params = *pparams;
2116 char *pdata = *ppdata;
2122 uint16 findnext_flags;
2123 bool close_after_request;
2125 bool requires_resume_key;
2127 bool mask_contains_wcard = False;
2128 char *resume_name = NULL;
2129 const char *mask = NULL;
2130 const char *directory = NULL;
2134 int i, last_entry_off=0;
2135 bool finished = False;
2136 bool dont_descend = False;
2137 bool out_of_space = False;
2138 int space_remaining;
2139 struct ea_list *ea_list = NULL;
2140 NTSTATUS ntstatus = NT_STATUS_OK;
2141 TALLOC_CTX *ctx = talloc_tos();
2143 if (total_params < 13) {
2144 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2148 dptr_num = SVAL(params,0);
2149 maxentries = SVAL(params,2);
2150 info_level = SVAL(params,4);
2151 resume_key = IVAL(params,6);
2152 findnext_flags = SVAL(params,10);
2153 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2154 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2155 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2156 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2158 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2160 total_params - 12, STR_TERMINATE, &ntstatus,
2161 &mask_contains_wcard);
2162 if (!NT_STATUS_IS_OK(ntstatus)) {
2163 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2164 complain (it thinks we're asking for the directory above the shared
2165 path or an invalid name). Catch this as the resume name is only compared, never used in
2166 a file access. JRA. */
2167 srvstr_pull_talloc(ctx, params, req->flags2,
2168 &resume_name, params+12,
2172 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2173 reply_nterror(req, ntstatus);
2178 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2179 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2180 resume_key = %d resume name = %s continue=%d level = %d\n",
2181 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2182 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2185 /* W2K3 seems to treat zero as 1. */
2189 switch (info_level) {
2190 case SMB_FIND_INFO_STANDARD:
2191 case SMB_FIND_EA_SIZE:
2192 case SMB_FIND_EA_LIST:
2193 case SMB_FIND_FILE_DIRECTORY_INFO:
2194 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2195 case SMB_FIND_FILE_NAMES_INFO:
2196 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2197 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2198 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2200 case SMB_FIND_FILE_UNIX:
2201 case SMB_FIND_FILE_UNIX_INFO2:
2202 if (!lp_unix_extensions()) {
2203 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2208 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2212 if (info_level == SMB_FIND_EA_LIST) {
2215 if (total_data < 4) {
2216 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2220 ea_size = IVAL(pdata,0);
2221 if (ea_size != total_data) {
2222 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2223 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2224 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2228 if (!lp_ea_support(SNUM(conn))) {
2229 reply_doserror(req, ERRDOS, ERReasnotsupported);
2233 /* Pull out the list of names. */
2234 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2236 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2241 *ppdata = (char *)SMB_REALLOC(
2242 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2243 if(*ppdata == NULL) {
2244 reply_nterror(req, NT_STATUS_NO_MEMORY);
2249 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2251 /* Realloc the params space */
2252 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2253 if(*pparams == NULL ) {
2254 reply_nterror(req, NT_STATUS_NO_MEMORY);
2260 /* Check that the dptr is valid */
2261 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2262 reply_doserror(req, ERRDOS, ERRnofiles);
2266 string_set(&conn->dirpath,dptr_path(dptr_num));
2268 /* Get the wildcard mask from the dptr */
2269 if((p = dptr_wcard(dptr_num))== NULL) {
2270 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2271 reply_doserror(req, ERRDOS, ERRnofiles);
2276 directory = conn->dirpath;
2278 /* Get the attr mask from the dptr */
2279 dirtype = dptr_attr(dptr_num);
2281 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2282 dptr_num, mask, dirtype,
2284 dptr_TellDir(conn->dirptr)));
2286 /* We don't need to check for VOL here as this is returned by
2287 a different TRANS2 call. */
2289 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2290 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2291 dont_descend = True;
2294 space_remaining = max_data_bytes;
2295 out_of_space = False;
2298 * Seek to the correct position. We no longer use the resume key but
2299 * depend on the last file name instead.
2302 if(*resume_name && !continue_bit) {
2305 long current_pos = 0;
2307 * Remember, name_to_8_3 is called by
2308 * get_lanman2_dir_entry(), so the resume name
2309 * could be mangled. Ensure we check the unmangled name.
2312 if (mangle_is_mangled(resume_name, conn->params)) {
2313 char *new_resume_name = NULL;
2314 mangle_lookup_name_from_8_3(ctx,
2318 if (new_resume_name) {
2319 resume_name = new_resume_name;
2324 * Fix for NT redirector problem triggered by resume key indexes
2325 * changing between directory scans. We now return a resume key of 0
2326 * and instead look for the filename to continue from (also given
2327 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2328 * findfirst/findnext (as is usual) then the directory pointer
2329 * should already be at the correct place.
2332 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2333 } /* end if resume_name && !continue_bit */
2335 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2336 bool got_exact_match = False;
2338 /* this is a heuristic to avoid seeking the dirptr except when
2339 absolutely necessary. It allows for a filename of about 40 chars */
2340 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2341 out_of_space = True;
2344 TALLOC_CTX *sub_ctx = talloc_stackframe();
2346 finished = !get_lanman2_dir_entry(sub_ctx,
2349 mask,dirtype,info_level,
2350 requires_resume_key,dont_descend,
2352 space_remaining, &out_of_space,
2354 &last_entry_off, ea_list);
2356 TALLOC_FREE(sub_ctx);
2359 if (finished && out_of_space)
2362 if (!finished && !out_of_space)
2366 * As an optimisation if we know we aren't looking
2367 * for a wildcard name (ie. the name matches the wildcard exactly)
2368 * then we can finish on any (first) match.
2369 * This speeds up large directory searches. JRA.
2375 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2378 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2379 smb_fn_name(CVAL(req->inbuf,smb_com)),
2380 mask, directory, dirtype, numentries ) );
2382 /* Check if we can close the dirptr */
2383 if(close_after_request || (finished && close_if_end)) {
2384 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2385 dptr_close(&dptr_num); /* This frees up the saved mask */
2388 /* Set up the return parameter block */
2389 SSVAL(params,0,numentries);
2390 SSVAL(params,2,finished);
2391 SSVAL(params,4,0); /* Never an EA error */
2392 SSVAL(params,6,last_entry_off);
2394 send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata),
2400 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2402 E_md4hash(lp_servicename(SNUM(conn)),objid);
2406 /****************************************************************************
2407 Reply to a TRANS2_QFSINFO (query filesystem info).
2408 ****************************************************************************/
2410 static void call_trans2qfsinfo(connection_struct *conn,
2411 struct smb_request *req,
2412 char **pparams, int total_params,
2413 char **ppdata, int total_data,
2414 unsigned int max_data_bytes)
2416 char *pdata, *end_data;
2417 char *params = *pparams;
2421 const char *vname = volume_label(SNUM(conn));
2422 int snum = SNUM(conn);
2423 char *fstype = lp_fstype(SNUM(conn));
2426 if (total_params < 2) {
2427 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2431 info_level = SVAL(params,0);
2433 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2435 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2436 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2437 reply_doserror(req, ERRSRV, ERRinvdevice);
2441 *ppdata = (char *)SMB_REALLOC(
2442 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2443 if (*ppdata == NULL ) {
2444 reply_nterror(req, NT_STATUS_NO_MEMORY);
2449 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2450 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2452 switch (info_level) {
2453 case SMB_INFO_ALLOCATION:
2455 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2457 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2458 reply_unixerror(req, ERRHRD, ERRgeneral);
2462 block_size = lp_block_size(snum);
2463 if (bsize < block_size) {
2464 SMB_BIG_UINT factor = block_size/bsize;
2469 if (bsize > block_size) {
2470 SMB_BIG_UINT factor = bsize/block_size;
2475 bytes_per_sector = 512;
2476 sectors_per_unit = bsize/bytes_per_sector;
2478 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2479 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2480 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2482 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2483 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2484 SIVAL(pdata,l1_cUnit,dsize);
2485 SIVAL(pdata,l1_cUnitAvail,dfree);
2486 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2490 case SMB_INFO_VOLUME:
2491 /* Return volume name */
2493 * Add volume serial number - hash of a combination of
2494 * the called hostname and the service name.
2496 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2498 * Win2k3 and previous mess this up by sending a name length
2499 * one byte short. I believe only older clients (OS/2 Win9x) use
2500 * this call so try fixing this by adding a terminating null to
2501 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2505 pdata+l2_vol_szVolLabel, vname,
2506 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2507 STR_NOALIGN|STR_TERMINATE);
2508 SCVAL(pdata,l2_vol_cch,len);
2509 data_len = l2_vol_szVolLabel + len;
2510 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2511 (unsigned)st.st_ctime, len, vname));
2514 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2515 case SMB_FS_ATTRIBUTE_INFORMATION:
2518 #if defined(HAVE_SYS_QUOTAS)
2519 quota_flag = FILE_VOLUME_QUOTAS;
2522 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2523 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2524 FILE_SUPPORTS_OBJECT_IDS|
2525 FILE_UNICODE_ON_DISK|
2526 quota_flag); /* FS ATTRIBUTES */
2528 SIVAL(pdata,4,255); /* Max filename component length */
2529 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2530 and will think we can't do long filenames */
2531 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2532 PTR_DIFF(end_data, pdata+12),
2535 data_len = 12 + len;
2538 case SMB_QUERY_FS_LABEL_INFO:
2539 case SMB_FS_LABEL_INFORMATION:
2540 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2541 PTR_DIFF(end_data, pdata+4), 0);
2546 case SMB_QUERY_FS_VOLUME_INFO:
2547 case SMB_FS_VOLUME_INFORMATION:
2550 * Add volume serial number - hash of a combination of
2551 * the called hostname and the service name.
2553 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2554 (str_checksum(get_local_machine_name())<<16));
2556 /* Max label len is 32 characters. */
2557 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2558 PTR_DIFF(end_data, pdata+18),
2560 SIVAL(pdata,12,len);
2563 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2564 (int)strlen(vname),vname, lp_servicename(snum)));
2567 case SMB_QUERY_FS_SIZE_INFO:
2568 case SMB_FS_SIZE_INFORMATION:
2570 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2572 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2573 reply_unixerror(req, ERRHRD, ERRgeneral);
2576 block_size = lp_block_size(snum);
2577 if (bsize < block_size) {
2578 SMB_BIG_UINT factor = block_size/bsize;
2583 if (bsize > block_size) {
2584 SMB_BIG_UINT factor = bsize/block_size;
2589 bytes_per_sector = 512;
2590 sectors_per_unit = bsize/bytes_per_sector;
2591 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2592 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2593 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2594 SBIG_UINT(pdata,0,dsize);
2595 SBIG_UINT(pdata,8,dfree);
2596 SIVAL(pdata,16,sectors_per_unit);
2597 SIVAL(pdata,20,bytes_per_sector);
2601 case SMB_FS_FULL_SIZE_INFORMATION:
2603 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2605 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2606 reply_unixerror(req, ERRHRD, ERRgeneral);
2609 block_size = lp_block_size(snum);
2610 if (bsize < block_size) {
2611 SMB_BIG_UINT factor = block_size/bsize;
2616 if (bsize > block_size) {
2617 SMB_BIG_UINT factor = bsize/block_size;
2622 bytes_per_sector = 512;
2623 sectors_per_unit = bsize/bytes_per_sector;
2624 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2625 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2626 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2627 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2628 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2629 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2630 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2631 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2635 case SMB_QUERY_FS_DEVICE_INFO:
2636 case SMB_FS_DEVICE_INFORMATION:
2638 SIVAL(pdata,0,0); /* dev type */
2639 SIVAL(pdata,4,0); /* characteristics */
2642 #ifdef HAVE_SYS_QUOTAS
2643 case SMB_FS_QUOTA_INFORMATION:
2645 * what we have to send --metze:
2647 * Unknown1: 24 NULL bytes
2648 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2649 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2650 * Quota Flags: 2 byte :
2651 * Unknown3: 6 NULL bytes
2655 * details for Quota Flags:
2657 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2658 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2659 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2660 * 0x0001 Enable Quotas: enable quota for this fs
2664 /* we need to fake up a fsp here,
2665 * because its not send in this call
2668 SMB_NTQUOTA_STRUCT quotas;
2671 ZERO_STRUCT(quotas);
2677 if (current_user.ut.uid != 0) {
2678 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2679 lp_servicename(SNUM(conn)),conn->user));
2680 reply_doserror(req, ERRDOS, ERRnoaccess);
2684 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2685 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2686 reply_doserror(req, ERRSRV, ERRerror);
2692 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2694 /* Unknown1 24 NULL bytes*/
2695 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2696 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2697 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2699 /* Default Soft Quota 8 bytes */
2700 SBIG_UINT(pdata,24,quotas.softlim);
2702 /* Default Hard Quota 8 bytes */
2703 SBIG_UINT(pdata,32,quotas.hardlim);
2705 /* Quota flag 2 bytes */
2706 SSVAL(pdata,40,quotas.qflags);
2708 /* Unknown3 6 NULL bytes */
2714 #endif /* HAVE_SYS_QUOTAS */
2715 case SMB_FS_OBJECTID_INFORMATION:
2717 unsigned char objid[16];
2718 memcpy(pdata,create_volume_objectid(conn, objid),16);
2724 * Query the version and capabilities of the CIFS UNIX extensions
2728 case SMB_QUERY_CIFS_UNIX_INFO:
2730 bool large_write = lp_min_receive_file_size() &&
2731 !srv_is_signing_active();
2733 if (!lp_unix_extensions()) {
2734 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2738 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2739 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2740 /* We have POSIX ACLs, pathname and locking capability. */
2741 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2742 CIFS_UNIX_POSIX_ACLS_CAP|
2743 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2744 CIFS_UNIX_FCNTL_LOCKS_CAP|
2745 CIFS_UNIX_EXTATTR_CAP|
2746 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2747 CIFS_UNIX_LARGE_READ_CAP|
2749 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2753 case SMB_QUERY_POSIX_FS_INFO:
2756 vfs_statvfs_struct svfs;
2758 if (!lp_unix_extensions()) {
2759 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2763 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2767 SIVAL(pdata,0,svfs.OptimalTransferSize);
2768 SIVAL(pdata,4,svfs.BlockSize);
2769 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2770 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2771 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2772 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2773 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2774 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2775 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2777 } else if (rc == EOPNOTSUPP) {
2778 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2780 #endif /* EOPNOTSUPP */
2782 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2783 reply_doserror(req, ERRSRV, ERRerror);
2789 case SMB_QUERY_POSIX_WHOAMI:
2795 if (!lp_unix_extensions()) {
2796 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2800 if (max_data_bytes < 40) {
2801 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2805 /* We ARE guest if global_sid_Builtin_Guests is
2806 * in our list of SIDs.
2808 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2809 current_user.nt_user_token)) {
2810 flags |= SMB_WHOAMI_GUEST;
2813 /* We are NOT guest if global_sid_Authenticated_Users
2814 * is in our list of SIDs.
2816 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2817 current_user.nt_user_token)) {
2818 flags &= ~SMB_WHOAMI_GUEST;
2821 /* NOTE: 8 bytes for UID/GID, irrespective of native
2822 * platform size. This matches
2823 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2825 data_len = 4 /* flags */
2832 + 4 /* pad/reserved */
2833 + (current_user.ut.ngroups * 8)
2835 + (current_user.nt_user_token->num_sids *
2839 SIVAL(pdata, 0, flags);
2840 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2841 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2842 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2845 if (data_len >= max_data_bytes) {
2846 /* Potential overflow, skip the GIDs and SIDs. */
2848 SIVAL(pdata, 24, 0); /* num_groups */
2849 SIVAL(pdata, 28, 0); /* num_sids */
2850 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2851 SIVAL(pdata, 36, 0); /* reserved */
2857 SIVAL(pdata, 24, current_user.ut.ngroups);
2859 current_user.nt_user_token->num_sids);
2861 /* We walk the SID list twice, but this call is fairly
2862 * infrequent, and I don't expect that it's performance
2863 * sensitive -- jpeach
2865 for (i = 0, sid_bytes = 0;
2866 i < current_user.nt_user_token->num_sids; ++i) {
2868 sid_size(¤t_user.nt_user_token->user_sids[i]);
2871 /* SID list byte count */
2872 SIVAL(pdata, 32, sid_bytes);
2874 /* 4 bytes pad/reserved - must be zero */
2875 SIVAL(pdata, 36, 0);
2879 for (i = 0; i < current_user.ut.ngroups; ++i) {
2880 SBIG_UINT(pdata, data_len,
2881 (SMB_BIG_UINT)current_user.ut.groups[i]);
2887 i < current_user.nt_user_token->num_sids; ++i) {
2889 sid_size(¤t_user.nt_user_token->user_sids[i]);
2891 sid_linearize(pdata + data_len, sid_len,
2892 ¤t_user.nt_user_token->user_sids[i]);
2893 data_len += sid_len;
2899 case SMB_MAC_QUERY_FS_INFO:
2901 * Thursby MAC extension... ONLY on NTFS filesystems
2902 * once we do streams then we don't need this
2904 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2906 SIVAL(pdata,84,0x100); /* Don't support mac... */
2911 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2916 send_trans2_replies(req, params, 0, pdata, data_len,
2919 DEBUG( 4, ( "%s info_level = %d\n",
2920 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2925 /****************************************************************************
2926 Reply to a TRANS2_SETFSINFO (set filesystem info).
2927 ****************************************************************************/
2929 static void call_trans2setfsinfo(connection_struct *conn,
2930 struct smb_request *req,
2931 char **pparams, int total_params,
2932 char **ppdata, int total_data,
2933 unsigned int max_data_bytes)
2935 char *pdata = *ppdata;
2936 char *params = *pparams;
2939 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2942 if (total_params < 4) {
2943 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2945 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2949 info_level = SVAL(params,2);
2951 switch(info_level) {
2952 case SMB_SET_CIFS_UNIX_INFO:
2954 uint16 client_unix_major;
2955 uint16 client_unix_minor;
2956 uint32 client_unix_cap_low;
2957 uint32 client_unix_cap_high;
2959 if (!lp_unix_extensions()) {
2961 NT_STATUS_INVALID_LEVEL);
2965 /* There should be 12 bytes of capabilities set. */
2966 if (total_data < 8) {
2969 NT_STATUS_INVALID_PARAMETER);
2972 client_unix_major = SVAL(pdata,0);
2973 client_unix_minor = SVAL(pdata,2);
2974 client_unix_cap_low = IVAL(pdata,4);
2975 client_unix_cap_high = IVAL(pdata,8);
2976 /* Just print these values for now. */
2977 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2978 cap_low = 0x%x, cap_high = 0x%x\n",
2979 (unsigned int)client_unix_major,
2980 (unsigned int)client_unix_minor,
2981 (unsigned int)client_unix_cap_low,
2982 (unsigned int)client_unix_cap_high ));
2984 /* Here is where we must switch to posix pathname processing... */
2985 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2986 lp_set_posix_pathnames();
2987 mangle_change_to_posix();
2990 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2991 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2992 /* Client that knows how to do posix locks,
2993 * but not posix open/mkdir operations. Set a
2994 * default type for read/write checks. */
2996 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3001 case SMB_FS_QUOTA_INFORMATION:
3003 files_struct *fsp = NULL;
3004 SMB_NTQUOTA_STRUCT quotas;
3006 ZERO_STRUCT(quotas);
3009 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3010 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3011 lp_servicename(SNUM(conn)),conn->user));
3012 reply_doserror(req, ERRSRV, ERRaccess);
3016 /* note: normaly there're 48 bytes,
3017 * but we didn't use the last 6 bytes for now
3020 fsp = file_fsp(SVAL(params,0));
3021 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3022 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3024 req, NT_STATUS_INVALID_HANDLE);
3028 if (total_data < 42) {
3029 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3033 NT_STATUS_INVALID_PARAMETER);
3037 /* unknown_1 24 NULL bytes in pdata*/
3039 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3040 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3041 #ifdef LARGE_SMB_OFF_T
3042 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3043 #else /* LARGE_SMB_OFF_T */
3044 if ((IVAL(pdata,28) != 0)&&
3045 ((quotas.softlim != 0xFFFFFFFF)||
3046 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3047 /* more than 32 bits? */
3050 NT_STATUS_INVALID_PARAMETER);
3053 #endif /* LARGE_SMB_OFF_T */
3055 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3056 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3057 #ifdef LARGE_SMB_OFF_T
3058 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3059 #else /* LARGE_SMB_OFF_T */
3060 if ((IVAL(pdata,36) != 0)&&
3061 ((quotas.hardlim != 0xFFFFFFFF)||
3062 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3063 /* more than 32 bits? */
3066 NT_STATUS_INVALID_PARAMETER);
3069 #endif /* LARGE_SMB_OFF_T */
3071 /* quota_flags 2 bytes **/
3072 quotas.qflags = SVAL(pdata,40);
3074 /* unknown_2 6 NULL bytes follow*/
3076 /* now set the quotas */
3077 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3078 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3079 reply_doserror(req, ERRSRV, ERRerror);
3086 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3088 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3094 * sending this reply works fine,
3095 * but I'm not sure it's the same
3096 * like windows do...
3099 reply_outbuf(req, 10, 0);
3102 #if defined(HAVE_POSIX_ACLS)
3103 /****************************************************************************
3104 Utility function to count the number of entries in a POSIX acl.
3105 ****************************************************************************/
3107 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3109 unsigned int ace_count = 0;
3110 int entry_id = SMB_ACL_FIRST_ENTRY;
3111 SMB_ACL_ENTRY_T entry;
3113 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3115 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3116 entry_id = SMB_ACL_NEXT_ENTRY;
3123 /****************************************************************************
3124 Utility function to marshall a POSIX acl into wire format.
3125 ****************************************************************************/
3127 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3129 int entry_id = SMB_ACL_FIRST_ENTRY;
3130 SMB_ACL_ENTRY_T entry;
3132 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3133 SMB_ACL_TAG_T tagtype;
3134 SMB_ACL_PERMSET_T permset;
3135 unsigned char perms = 0;
3136 unsigned int own_grp;
3139 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3140 entry_id = SMB_ACL_NEXT_ENTRY;
3143 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3144 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3148 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3149 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3153 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3154 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3155 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3157 SCVAL(pdata,1,perms);
3160 case SMB_ACL_USER_OBJ:
3161 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3162 own_grp = (unsigned int)pst->st_uid;
3163 SIVAL(pdata,2,own_grp);
3168 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3170 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3173 own_grp = (unsigned int)*puid;
3174 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3175 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3176 SIVAL(pdata,2,own_grp);
3180 case SMB_ACL_GROUP_OBJ:
3181 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3182 own_grp = (unsigned int)pst->st_gid;
3183 SIVAL(pdata,2,own_grp);
3188 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3190 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3193 own_grp = (unsigned int)*pgid;
3194 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3195 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3196 SIVAL(pdata,2,own_grp);
3201 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3202 SIVAL(pdata,2,0xFFFFFFFF);
3203 SIVAL(pdata,6,0xFFFFFFFF);
3206 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3207 SIVAL(pdata,2,0xFFFFFFFF);
3208 SIVAL(pdata,6,0xFFFFFFFF);
3211 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3214 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3221 /****************************************************************************
3222 Store the FILE_UNIX_BASIC info.
3223 ****************************************************************************/
3225 static char *store_file_unix_basic(connection_struct *conn,
3228 const SMB_STRUCT_STAT *psbuf)
3230 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3231 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3233 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3236 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3239 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3240 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3241 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3244 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3248 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3252 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3255 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3259 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3263 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3266 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3270 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3277 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3278 * the chflags(2) (or equivalent) flags.
3280 * XXX: this really should be behind the VFS interface. To do this, we would
3281 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3282 * Each VFS module could then implement its own mapping as appropriate for the
3283 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3285 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3289 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3293 { UF_IMMUTABLE, EXT_IMMUTABLE },
3297 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3301 { UF_HIDDEN, EXT_HIDDEN },
3304 /* Do not remove. We need to guarantee that this array has at least one
3305 * entry to build on HP-UX.
3311 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3312 uint32 *smb_fflags, uint32 *smb_fmask)
3314 #ifdef HAVE_STAT_ST_FLAGS
3317 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3318 *smb_fmask |= info2_flags_map[i].smb_fflag;
3319 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3320 *smb_fflags |= info2_flags_map[i].smb_fflag;
3323 #endif /* HAVE_STAT_ST_FLAGS */
3326 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3327 const uint32 smb_fflags,
3328 const uint32 smb_fmask,
3331 #ifdef HAVE_STAT_ST_FLAGS
3332 uint32 max_fmask = 0;
3335 *stat_fflags = psbuf->st_flags;
3337 /* For each flags requested in smb_fmask, check the state of the
3338 * corresponding flag in smb_fflags and set or clear the matching
3342 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3343 max_fmask |= info2_flags_map[i].smb_fflag;
3344 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3345 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3346 *stat_fflags |= info2_flags_map[i].stat_fflag;
3348 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3353 /* If smb_fmask is asking to set any bits that are not supported by
3354 * our flag mappings, we should fail.
3356 if ((smb_fmask & max_fmask) != smb_fmask) {
3363 #endif /* HAVE_STAT_ST_FLAGS */
3367 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3368 * of file flags and birth (create) time.
3370 static char *store_file_unix_basic_info2(connection_struct *conn,
3373 const SMB_STRUCT_STAT *psbuf)
3375 uint32 file_flags = 0;
3376 uint32 flags_mask = 0;
3378 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3380 /* Create (birth) time 64 bit */
3381 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3384 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3385 SIVAL(pdata, 0, file_flags); /* flags */
3386 SIVAL(pdata, 4, flags_mask); /* mask */
3392 /****************************************************************************
3393 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3394 ****************************************************************************/
3396 static void call_trans2qpipeinfo(connection_struct *conn,
3397 struct smb_request *req,
3398 unsigned int tran_call,
3399 char **pparams, int total_params,
3400 char **ppdata, int total_data,
3401 unsigned int max_data_bytes)
3403 char *params = *pparams;
3404 char *pdata = *ppdata;
3405 unsigned int data_size = 0;
3406 unsigned int param_size = 2;
3408 smb_np_struct *p_pipe = NULL;
3411 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3415 if (total_params < 4) {
3416 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3420 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3421 if (p_pipe == NULL) {
3422 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3426 info_level = SVAL(params,2);
3428 *pparams = (char *)SMB_REALLOC(*pparams,2);
3429 if (*pparams == NULL) {
3430 reply_nterror(req, NT_STATUS_NO_MEMORY);
3435 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3436 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3437 if (*ppdata == NULL ) {
3438 reply_nterror(req, NT_STATUS_NO_MEMORY);
3443 switch (info_level) {
3444 case SMB_FILE_STANDARD_INFORMATION:
3446 SOFF_T(pdata,0,4096LL);
3453 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3457 send_trans2_replies(req, params, param_size, *ppdata, data_size,
3463 /****************************************************************************
3464 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3465 file name or file id).
3466 ****************************************************************************/
3468 static void call_trans2qfilepathinfo(connection_struct *conn,
3469 struct smb_request *req,
3470 unsigned int tran_call,
3471 char **pparams, int total_params,
3472 char **ppdata, int total_data,
3473 unsigned int max_data_bytes)
3475 char *params = *pparams;
3476 char *pdata = *ppdata;
3477 char *dstart, *dend;
3481 SMB_OFF_T file_size=0;
3482 SMB_BIG_UINT allocation_size=0;
3483 unsigned int data_size = 0;
3484 unsigned int param_size = 2;
3485 SMB_STRUCT_STAT sbuf;
3486 char *dos_fname = NULL;
3492 bool delete_pending = False;
3494 time_t create_time, mtime, atime;
3495 struct timespec create_time_ts, mtime_ts, atime_ts;
3496 files_struct *fsp = NULL;
3497 struct file_id fileid;
3498 struct ea_list *ea_list = NULL;
3499 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3500 char *lock_data = NULL;
3501 TALLOC_CTX *ctx = talloc_tos();
3504 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3510 if (tran_call == TRANSACT2_QFILEINFO) {
3511 if (total_params < 4) {
3512 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3517 call_trans2qpipeinfo(conn, req, tran_call,
3518 pparams, total_params,
3524 fsp = file_fsp(SVAL(params,0));
3525 info_level = SVAL(params,2);
3527 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3529 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3530 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3534 /* Initial check for valid fsp ptr. */
3535 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
3539 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3541 reply_nterror(req, NT_STATUS_NO_MEMORY);
3545 if(fsp->fake_file_handle) {
3547 * This is actually for the QUOTA_FAKE_FILE --metze
3550 /* We know this name is ok, it's already passed the checks. */
3552 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3554 * This is actually a QFILEINFO on a directory
3555 * handle (returned from an NT SMB). NT5.0 seems
3556 * to do this call. JRA.
3559 if (INFO_LEVEL_IS_UNIX(info_level)) {
3560 /* Always do lstat for UNIX calls. */
3561 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3562 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3563 reply_unixerror(req,ERRDOS,ERRbadpath);
3566 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3567 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3568 reply_unixerror(req, ERRDOS, ERRbadpath);
3572 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3573 delete_pending = get_delete_on_close_flag(fileid);
3576 * Original code - this is an open file.
3578 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3582 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3583 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3584 reply_unixerror(req, ERRDOS, ERRbadfid);
3587 pos = fsp->fh->position_information;
3588 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3589 delete_pending = get_delete_on_close_flag(fileid);
3590 access_mask = fsp->access_mask;
3594 NTSTATUS status = NT_STATUS_OK;
3597 if (total_params < 7) {
3598 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3602 info_level = SVAL(params,0);
3604 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3606 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3607 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3611 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3613 STR_TERMINATE, &status);
3614 if (!NT_STATUS_IS_OK(status)) {
3615 reply_nterror(req, status);
3619 status = resolve_dfspath(ctx,
3621 req->flags2 & FLAGS2_DFS_PATHNAMES,
3624 if (!NT_STATUS_IS_OK(status)) {
3625 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3626 reply_botherror(req,
3627 NT_STATUS_PATH_NOT_COVERED,
3628 ERRSRV, ERRbadpath);
3630 reply_nterror(req, status);
3634 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3635 if (!NT_STATUS_IS_OK(status)) {
3636 reply_nterror(req, status);
3639 status = check_name(conn, fname);
3640 if (!NT_STATUS_IS_OK(status)) {
3641 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3642 reply_nterror(req, status);
3646 if (INFO_LEVEL_IS_UNIX(info_level)) {
3647 /* Always do lstat for UNIX calls. */
3648 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3649 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3650 reply_unixerror(req, ERRDOS, ERRbadpath);
3653 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3654 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3655 reply_unixerror(req, ERRDOS, ERRbadpath);
3659 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3660 delete_pending = get_delete_on_close_flag(fileid);
3661 if (delete_pending) {
3662 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3667 nlink = sbuf.st_nlink;
3669 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3670 /* NTFS does not seem to count ".." */
3674 if ((nlink > 0) && delete_pending) {
3678 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3679 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3683 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3684 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3686 p = strrchr_m(fname,'/');
3692 mode = dos_mode(conn,fname,&sbuf);
3694 mode = FILE_ATTRIBUTE_NORMAL;
3696 fullpathname = fname;
3698 file_size = get_file_size(sbuf);
3700 /* Pull out any data sent here before we realloc. */
3701 switch (info_level) {
3702 case SMB_INFO_QUERY_EAS_FROM_LIST:
3704 /* Pull any EA list from the data portion. */
3707 if (total_data < 4) {
3709 req, NT_STATUS_INVALID_PARAMETER);
3712 ea_size = IVAL(pdata,0);
3714 if (total_data > 0 && ea_size != total_data) {
3715 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3716 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3718 req, NT_STATUS_INVALID_PARAMETER);
3722 if (!lp_ea_support(SNUM(conn))) {
3723 reply_doserror(req, ERRDOS,
3724 ERReasnotsupported);
3728 /* Pull out the list of names. */
3729 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3732 req, NT_STATUS_INVALID_PARAMETER);
3738 case SMB_QUERY_POSIX_LOCK:
3740 if (fsp == NULL || fsp->fh->fd == -1) {
3741 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3745 if (total_data != POSIX_LOCK_DATA_SIZE) {
3747 req, NT_STATUS_INVALID_PARAMETER);
3751 /* Copy the lock range data. */
3752 lock_data = (char *)TALLOC_MEMDUP(
3753 ctx, pdata, total_data);
3755 reply_nterror(req, NT_STATUS_NO_MEMORY);
3763 *pparams = (char *)SMB_REALLOC(*pparams,2);
3764 if (*pparams == NULL) {
3765 reply_nterror(req, NT_STATUS_NO_MEMORY);
3770 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3771 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3772 if (*ppdata == NULL ) {
3773 reply_nterror(req, NT_STATUS_NO_MEMORY);
3778 dend = dstart + data_size - 1;
3780 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3781 mtime_ts = get_mtimespec(&sbuf);
3782 atime_ts = get_atimespec(&sbuf);
3784 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3787 if (!null_timespec(fsp->pending_modtime)) {
3788 /* the pending modtime overrides the current modtime */
3789 mtime_ts = fsp->pending_modtime;
3793 /* Do we have this path open ? */
3794 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3795 fsp1 = file_find_di_first(fileid);
3796 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3797 /* the pending modtime overrides the current modtime */
3798 mtime_ts = fsp1->pending_modtime;
3800 if (fsp1 && fsp1->initial_allocation_size) {
3801 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3805 if (lp_dos_filetime_resolution(SNUM(conn))) {
3806 dos_filetime_timespec(&create_time_ts);
3807 dos_filetime_timespec(&mtime_ts);
3808 dos_filetime_timespec(&atime_ts);
3811 create_time = convert_timespec_to_time_t(create_time_ts);
3812 mtime = convert_timespec_to_time_t(mtime_ts);
3813 atime = convert_timespec_to_time_t(atime_ts);
3815 /* NT expects the name to be in an exact form of the *full*
3816 filename. See the trans2 torture test */
3817 if (ISDOT(base_name)) {
3818 dos_fname = talloc_strdup(ctx, "\\");
3820 reply_nterror(req, NT_STATUS_NO_MEMORY);
3824 dos_fname = talloc_asprintf(ctx,
3828 reply_nterror(req, NT_STATUS_NO_MEMORY);
3831 string_replace(dos_fname, '/', '\\');
3834 switch (info_level) {
3835 case SMB_INFO_STANDARD:
3836 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3838 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3839 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3840 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3841 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3842 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3843 SSVAL(pdata,l1_attrFile,mode);
3846 case SMB_INFO_QUERY_EA_SIZE:
3848 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3849 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3851 srv_put_dos_date2(pdata,0,create_time);
3852 srv_put_dos_date2(pdata,4,atime);
3853 srv_put_dos_date2(pdata,8,mtime); /* write time */
3854 SIVAL(pdata,12,(uint32)file_size);
3855 SIVAL(pdata,16,(uint32)allocation_size);
3856 SSVAL(pdata,20,mode);
3857 SIVAL(pdata,22,ea_size);
3861 case SMB_INFO_IS_NAME_VALID:
3862 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3863 if (tran_call == TRANSACT2_QFILEINFO) {
3864 /* os/2 needs this ? really ?*/
3865 reply_doserror(req, ERRDOS, ERRbadfunc);
3872 case SMB_INFO_QUERY_EAS_FROM_LIST:
3874 size_t total_ea_len = 0;
3875 struct ea_list *ea_file_list = NULL;
3877 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3879 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3880 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3882 if (!ea_list || (total_ea_len > data_size)) {
3884 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3888 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3892 case SMB_INFO_QUERY_ALL_EAS:
3894 /* We have data_size bytes to put EA's into. */
3895 size_t total_ea_len = 0;
3897 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3899 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3900 if (!ea_list || (total_ea_len > data_size)) {
3902 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3906 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3910 case SMB_FILE_BASIC_INFORMATION:
3911 case SMB_QUERY_FILE_BASIC_INFO:
3913 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3914 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3915 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3917 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3921 put_long_date_timespec(pdata,create_time_ts);
3922 put_long_date_timespec(pdata+8,atime_ts);
3923 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3924 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3925 SIVAL(pdata,32,mode);
3927 DEBUG(5,("SMB_QFBI - "));
3928 DEBUG(5,("create: %s ", ctime(&create_time)));
3929 DEBUG(5,("access: %s ", ctime(&atime)));
3930 DEBUG(5,("write: %s ", ctime(&mtime)));
3931 DEBUG(5,("change: %s ", ctime(&mtime)));
3932 DEBUG(5,("mode: %x\n", mode));
3935 case SMB_FILE_STANDARD_INFORMATION:
3936 case SMB_QUERY_FILE_STANDARD_INFO:
3938 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3940 SOFF_T(pdata,0,allocation_size);
3941 SOFF_T(pdata,8,file_size);
3942 SIVAL(pdata,16,nlink);
3943 SCVAL(pdata,20,delete_pending?1:0);
3944 SCVAL(pdata,21,(mode&aDIR)?1:0);
3945 SSVAL(pdata,22,0); /* Padding. */
3948 case SMB_FILE_EA_INFORMATION:
3949 case SMB_QUERY_FILE_EA_INFO:
3951 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3952 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3954 SIVAL(pdata,0,ea_size);
3958 /* Get the 8.3 name - used if NT SMB was negotiated. */
3959 case SMB_QUERY_FILE_ALT_NAME_INFO:
3960 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3962 char mangled_name[13];
3963 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3964 if (!name_to_8_3(base_name,mangled_name,
3965 True,conn->params)) {
3968 NT_STATUS_NO_MEMORY);
3970 len = srvstr_push(dstart, req->flags2,
3971 pdata+4, mangled_name,
3972 PTR_DIFF(dend, pdata+4),
3974 data_size = 4 + len;
3979 case SMB_QUERY_FILE_NAME_INFO:
3981 this must be *exactly* right for ACLs on mapped drives to work
3983 len = srvstr_push(dstart, req->flags2,
3985 PTR_DIFF(dend, pdata+4),
3987 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3988 data_size = 4 + len;
3992 case SMB_FILE_ALLOCATION_INFORMATION:
3993 case SMB_QUERY_FILE_ALLOCATION_INFO:
3994 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3996 SOFF_T(pdata,0,allocation_size);
3999 case SMB_FILE_END_OF_FILE_INFORMATION:
4000 case SMB_QUERY_FILE_END_OF_FILEINFO:
4001 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4003 SOFF_T(pdata,0,file_size);
4006 case SMB_QUERY_FILE_ALL_INFO:
4007 case SMB_FILE_ALL_INFORMATION:
4009 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4010 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4011 put_long_date_timespec(pdata,create_time_ts);
4012 put_long_date_timespec(pdata+8,atime_ts);
4013 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4014 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4015 SIVAL(pdata,32,mode);
4016 SIVAL(pdata,36,0); /* padding. */
4018 SOFF_T(pdata,0,allocation_size);
4019 SOFF_T(pdata,8,file_size);
4020 SIVAL(pdata,16,nlink);
4021 SCVAL(pdata,20,delete_pending);
4022 SCVAL(pdata,21,(mode&aDIR)?1:0);
4025 SIVAL(pdata,0,ea_size);
4026 pdata += 4; /* EA info */
4027 len = srvstr_push(dstart, req->flags2,
4029 PTR_DIFF(dend, pdata+4),
4033 data_size = PTR_DIFF(pdata,(*ppdata));
4036 case SMB_FILE_INTERNAL_INFORMATION:
4037 /* This should be an index number - looks like
4040 I think this causes us to fail the IFSKIT
4041 BasicFileInformationTest. -tpot */
4043 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4044 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4045 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4049 case SMB_FILE_ACCESS_INFORMATION:
4050 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4051 SIVAL(pdata,0,access_mask);
4055 case SMB_FILE_NAME_INFORMATION:
4056 /* Pathname with leading '\'. */
4059 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4060 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4061 SIVAL(pdata,0,byte_len);
4062 data_size = 4 + byte_len;
4066 case SMB_FILE_DISPOSITION_INFORMATION:
4067 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4069 SCVAL(pdata,0,delete_pending);
4072 case SMB_FILE_POSITION_INFORMATION:
4073 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4075 SOFF_T(pdata,0,pos);
4078 case SMB_FILE_MODE_INFORMATION:
4079 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4080 SIVAL(pdata,0,mode);
4084 case SMB_FILE_ALIGNMENT_INFORMATION:
4085 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4086 SIVAL(pdata,0,0); /* No alignment needed. */
4092 * NT4 server just returns "invalid query" to this - if we try to answer
4093 * it then NTws gets a BSOD! (tridge).
4094 * W2K seems to want this. JRA.
4096 case SMB_QUERY_FILE_STREAM_INFO:
4098 case SMB_FILE_STREAM_INFORMATION:
4099 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4103 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4104 SIVAL(pdata,0,0); /* ??? */
4105 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4106 SOFF_T(pdata,8,file_size);
4107 SOFF_T(pdata,16,allocation_size);
4108 data_size = 24 + byte_len;
4112 case SMB_QUERY_COMPRESSION_INFO:
4113 case SMB_FILE_COMPRESSION_INFORMATION:
4114 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4115 SOFF_T(pdata,0,file_size);
4116 SIVAL(pdata,8,0); /* ??? */
4117 SIVAL(pdata,12,0); /* ??? */
4121 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4122 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4123 put_long_date_timespec(pdata,create_time_ts);
4124 put_long_date_timespec(pdata+8,atime_ts);
4125 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4126 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4127 SOFF_T(pdata,32,allocation_size);
4128 SOFF_T(pdata,40,file_size);
4129 SIVAL(pdata,48,mode);
4130 SIVAL(pdata,52,0); /* ??? */
4134 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4135 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4136 SIVAL(pdata,0,mode);
4142 * CIFS UNIX Extensions.
4145 case SMB_QUERY_FILE_UNIX_BASIC:
4147 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4148 data_size = PTR_DIFF(pdata,(*ppdata));
4152 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4154 for (i=0; i<100; i++)
4155 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4161 case SMB_QUERY_FILE_UNIX_INFO2:
4163 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4164 data_size = PTR_DIFF(pdata,(*ppdata));
4168 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4170 for (i=0; i<100; i++)
4171 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4177 case SMB_QUERY_FILE_UNIX_LINK:
4179 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4182 reply_nterror(req, NT_STATUS_NO_MEMORY);
4186 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4188 if(!S_ISLNK(sbuf.st_mode)) {
4189 reply_unixerror(req, ERRSRV,
4194 reply_unixerror(req, ERRDOS, ERRbadlink);
4197 len = SMB_VFS_READLINK(conn,fullpathname,
4200 reply_unixerror(req, ERRDOS,
4205 len = srvstr_push(dstart, req->flags2,
4207 PTR_DIFF(dend, pdata),
4210 data_size = PTR_DIFF(pdata,(*ppdata));
4215 #if defined(HAVE_POSIX_ACLS)
4216 case SMB_QUERY_POSIX_ACL:
4218 SMB_ACL_T file_acl = NULL;
4219 SMB_ACL_T def_acl = NULL;
4220 uint16 num_file_acls = 0;
4221 uint16 num_def_acls = 0;
4223 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4224 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4226 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4229 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4230 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4234 NT_STATUS_NOT_IMPLEMENTED);
4238 if (S_ISDIR(sbuf.st_mode)) {
4239 if (fsp && fsp->is_directory) {
4240 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4242 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4244 def_acl = free_empty_sys_acl(conn, def_acl);
4247 num_file_acls = count_acl_entries(conn, file_acl);
4248 num_def_acls = count_acl_entries(conn, def_acl);
4250 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4251 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4253 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4254 SMB_POSIX_ACL_HEADER_SIZE) ));
4256 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4259 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4263 NT_STATUS_BUFFER_TOO_SMALL);
4267 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4268 SSVAL(pdata,2,num_file_acls);
4269 SSVAL(pdata,4,num_def_acls);
4270 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4272 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4275 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4278 req, NT_STATUS_INTERNAL_ERROR);
4281 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4283 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4286 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4290 NT_STATUS_INTERNAL_ERROR);
4295 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4298 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4300 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4306 case SMB_QUERY_POSIX_LOCK:
4308 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4310 SMB_BIG_UINT offset;
4312 enum brl_type lock_type;
4314 if (total_data != POSIX_LOCK_DATA_SIZE) {
4316 req, NT_STATUS_INVALID_PARAMETER);
4320 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4321 case POSIX_LOCK_TYPE_READ:
4322 lock_type = READ_LOCK;
4324 case POSIX_LOCK_TYPE_WRITE:
4325 lock_type = WRITE_LOCK;
4327 case POSIX_LOCK_TYPE_UNLOCK:
4329 /* There's no point in asking for an unlock... */
4332 NT_STATUS_INVALID_PARAMETER);
4336 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4337 #if defined(HAVE_LONGLONG)
4338 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4339 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4340 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4341 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4342 #else /* HAVE_LONGLONG */
4343 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4344 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4345 #endif /* HAVE_LONGLONG */
4347 status = query_lock(fsp,
4354 if (ERROR_WAS_LOCK_DENIED(status)) {
4355 /* Here we need to report who has it locked... */
4356 data_size = POSIX_LOCK_DATA_SIZE;
4358 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4359 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4360 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4361 #if defined(HAVE_LONGLONG)
4362 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4363 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4364 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4365 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4366 #else /* HAVE_LONGLONG */
4367 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4368 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4369 #endif /* HAVE_LONGLONG */
4371 } else if (NT_STATUS_IS_OK(status)) {
4372 /* For success we just return a copy of what we sent
4373 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4374 data_size = POSIX_LOCK_DATA_SIZE;
4375 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4376 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4378 reply_nterror(req, status);
4385 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4389 send_trans2_replies(req, params, param_size, *ppdata, data_size,
4395 /****************************************************************************
4396 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4398 ****************************************************************************/
4400 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4401 connection_struct *conn,
4402 const char *oldname_in,
4403 const char *newname_in)
4405 SMB_STRUCT_STAT sbuf1, sbuf2;
4406 char *last_component_oldname = NULL;
4407 char *last_component_newname = NULL;
4408 char *oldname = NULL;
4409 char *newname = NULL;
4410 NTSTATUS status = NT_STATUS_OK;
4415 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4416 &last_component_oldname, &sbuf1);
4417 if (!NT_STATUS_IS_OK(status)) {
4421 status = check_name(conn, oldname);
4422 if (!NT_STATUS_IS_OK(status)) {
4426 /* source must already exist. */
4427 if (!VALID_STAT(sbuf1)) {
4428 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4431 status = unix_convert(ctx, conn, newname_in, False, &newname,
4432 &last_component_newname, &sbuf2);
4433 if (!NT_STATUS_IS_OK(status)) {
4437 status = check_name(conn, newname);
4438 if (!NT_STATUS_IS_OK(status)) {
4442 /* Disallow if newname already exists. */
4443 if (VALID_STAT(sbuf2)) {
4444 return NT_STATUS_OBJECT_NAME_COLLISION;
4447 /* No links from a directory. */
4448 if (S_ISDIR(sbuf1.st_mode)) {
4449 return NT_STATUS_FILE_IS_A_DIRECTORY;
4452 /* Ensure this is within the share. */
4453 status = check_reduced_name(conn, oldname);
4454 if (!NT_STATUS_IS_OK(status)) {
4458 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4460 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4461 status = map_nt_error_from_unix(errno);
4462 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4463 nt_errstr(status), newname, oldname));
4469 /****************************************************************************
4470 Deal with setting the time from any of the setfilepathinfo functions.
4471 ****************************************************************************/
4473 static NTSTATUS smb_set_file_time(connection_struct *conn,
4476 const SMB_STRUCT_STAT *psbuf,
4477 struct timespec ts[2],
4478 bool setting_write_time)
4481 FILE_NOTIFY_CHANGE_LAST_ACCESS
4482 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4484 if (!VALID_STAT(*psbuf)) {
4485 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4488 /* get some defaults (no modifications) if any info is zero or -1. */
4489 if (null_timespec(ts[0])) {
4490 ts[0] = get_atimespec(psbuf);
4491 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4494 if (null_timespec(ts[1])) {
4495 ts[1] = get_mtimespec(psbuf);
4496 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4499 if (!setting_write_time) {
4500 /* ts[1] comes from change time, not write time. */
4501 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4504 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4505 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4508 * Try and set the times of this file if
4509 * they are different from the current values.
4513 struct timespec mts = get_mtimespec(psbuf);
4514 struct timespec ats = get_atimespec(psbuf);
4515 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4516 return NT_STATUS_OK;
4522 * This was a setfileinfo on an open file.
4523 * NT does this a lot. We also need to
4524 * set the time here, as it can be read by
4525 * FindFirst/FindNext and with the patch for bug #2045
4526 * in smbd/fileio.c it ensures that this timestamp is
4527 * kept sticky even after a write. We save the request
4528 * away and will set it on file close and after a write. JRA.
4531 if (!null_timespec(ts[1])) {
4532 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4533 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4534 fsp_set_pending_modtime(fsp, ts[1]);
4538 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4540 if(file_ntimes(conn, fname, ts)!=0) {
4541 return map_nt_error_from_unix(errno);
4543 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4545 return NT_STATUS_OK;
4548 /****************************************************************************
4549 Deal with setting the dosmode from any of the setfilepathinfo functions.
4550 ****************************************************************************/
4552 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4554 SMB_STRUCT_STAT *psbuf,
4557 if (!VALID_STAT(*psbuf)) {
4558 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4562 if (S_ISDIR(psbuf->st_mode)) {
4569 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4571 /* check the mode isn't different, before changing it */
4572 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4574 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4575 fname, (unsigned int)dosmode ));
4577 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4578 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4579 fname, strerror(errno)));
4580 return map_nt_error_from_unix(errno);
4583 return NT_STATUS_OK;
4586 /****************************************************************************
4587 Deal with setting the size from any of the setfilepathinfo functions.
4588 ****************************************************************************/
4590 static NTSTATUS smb_set_file_size(connection_struct *conn,
4591 struct smb_request *req,
4594 SMB_STRUCT_STAT *psbuf,
4597 NTSTATUS status = NT_STATUS_OK;
4598 files_struct *new_fsp = NULL;
4600 if (!VALID_STAT(*psbuf)) {
4601 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4604 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4606 if (size == get_file_size(*psbuf)) {
4607 return NT_STATUS_OK;
4610 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4611 fname, (double)size ));
4613 if (fsp && fsp->fh->fd != -1) {
4614 /* Handle based call. */
4615 if (vfs_set_filelen(fsp, size) == -1) {
4616 return map_nt_error_from_unix(errno);
4618 return NT_STATUS_OK;
4621 status = open_file_ntcreate(conn, req, fname, psbuf,
4623 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4626 FILE_ATTRIBUTE_NORMAL,
4627 FORCE_OPLOCK_BREAK_TO_NONE,
4630 if (!NT_STATUS_IS_OK(status)) {
4631 /* NB. We check for open_was_deferred in the caller. */
4635 if (vfs_set_filelen(new_fsp, size) == -1) {
4636 status = map_nt_error_from_unix(errno);
4637 close_file(new_fsp,NORMAL_CLOSE);
4641 close_file(new_fsp,NORMAL_CLOSE);
4642 return NT_STATUS_OK;
4645 /****************************************************************************
4646 Deal with SMB_INFO_SET_EA.
4647 ****************************************************************************/
4649 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4655 struct ea_list *ea_list = NULL;
4656 TALLOC_CTX *ctx = NULL;
4657 NTSTATUS status = NT_STATUS_OK;
4659 if (total_data < 10) {
4661 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4662 length. They seem to have no effect. Bug #3212. JRA */
4664 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4665 /* We're done. We only get EA info in this call. */
4666 return NT_STATUS_OK;
4669 return NT_STATUS_INVALID_PARAMETER;
4672 if (IVAL(pdata,0) > total_data) {
4673 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4674 IVAL(pdata,0), (unsigned int)total_data));
4675 return NT_STATUS_INVALID_PARAMETER;
4678 ctx = talloc_init("SMB_INFO_SET_EA");
4680 return NT_STATUS_NO_MEMORY;
4682 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4684 talloc_destroy(ctx);
4685 return NT_STATUS_INVALID_PARAMETER;
4687 status = set_ea(conn, fsp, fname, ea_list);
4688 talloc_destroy(ctx);
4693 /****************************************************************************
4694 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4695 ****************************************************************************/
4697 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4702 SMB_STRUCT_STAT *psbuf)
4704 NTSTATUS status = NT_STATUS_OK;
4705 bool delete_on_close;
4708 if (total_data < 1) {
4709 return NT_STATUS_INVALID_PARAMETER;
4713 return NT_STATUS_INVALID_HANDLE;
4716 delete_on_close = (CVAL(pdata,0) ? True : False);
4717 dosmode = dos_mode(conn, fname, psbuf);
4719 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4720 "delete_on_close = %u\n",
4722 (unsigned int)dosmode,
4723 (unsigned int)delete_on_close ));
4725 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4727 if (!NT_STATUS_IS_OK(status)) {
4731 /* The set is across all open files on this dev/inode pair. */
4732 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4733 return NT_STATUS_ACCESS_DENIED;
4735 return NT_STATUS_OK;
4738 /****************************************************************************
4739 Deal with SMB_FILE_POSITION_INFORMATION.
4740 ****************************************************************************/
4742 static NTSTATUS smb_file_position_information(connection_struct *conn,
4747 SMB_BIG_UINT position_information;
4749 if (total_data < 8) {
4750 return NT_STATUS_INVALID_PARAMETER;
4754 /* Ignore on pathname based set. */
4755 return NT_STATUS_OK;
4758 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4759 #ifdef LARGE_SMB_OFF_T
4760 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4761 #else /* LARGE_SMB_OFF_T */
4762 if (IVAL(pdata,4) != 0) {
4763 /* more than 32 bits? */
4764 return NT_STATUS_INVALID_PARAMETER;
4766 #endif /* LARGE_SMB_OFF_T */
4768 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4769 fsp->fsp_name, (double)position_information ));
4770 fsp->fh->position_information = position_information;
4771 return NT_STATUS_OK;
4774 /****************************************************************************
4775 Deal with SMB_FILE_MODE_INFORMATION.
4776 ****************************************************************************/
4778 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4784 if (total_data < 4) {
4785 return NT_STATUS_INVALID_PARAMETER;
4787 mode = IVAL(pdata,0);
4788 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4789 return NT_STATUS_INVALID_PARAMETER;
4791 return NT_STATUS_OK;
4794 /****************************************************************************
4795 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4796 ****************************************************************************/
4798 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4799 struct smb_request *req,
4804 char *link_target = NULL;
4805 const char *newname = fname;
4806 NTSTATUS status = NT_STATUS_OK;
4807 TALLOC_CTX *ctx = talloc_tos();
4809 /* Set a symbolic link. */
4810 /* Don't allow this if follow links is false. */
4812 if (total_data == 0) {
4813 return NT_STATUS_INVALID_PARAMETER;
4816 if (!lp_symlinks(SNUM(conn))) {
4817 return NT_STATUS_ACCESS_DENIED;
4820 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
4821 total_data, STR_TERMINATE);
4824 return NT_STATUS_INVALID_PARAMETER;
4827 /* !widelinks forces the target path to be within the share. */
4828 /* This means we can interpret the target as a pathname. */
4829 if (!lp_widelinks(SNUM(conn))) {
4830 char *rel_name = NULL;
4831 char *last_dirp = NULL;
4833 if (*link_target == '/') {
4834 /* No absolute paths allowed. */
4835 return NT_STATUS_ACCESS_DENIED;
4837 rel_name = talloc_strdup(ctx,newname);
4839 return NT_STATUS_NO_MEMORY;
4841 last_dirp = strrchr_m(rel_name, '/');
4843 last_dirp[1] = '\0';
4845 rel_name = talloc_strdup(ctx,"./");
4847 return NT_STATUS_NO_MEMORY;
4850 rel_name = talloc_asprintf_append(rel_name,
4854 return NT_STATUS_NO_MEMORY;
4857 status = check_name(conn, rel_name);
4858 if (!NT_STATUS_IS_OK(status)) {
4863 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4864 newname, link_target ));
4866 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4867 return map_nt_error_from_unix(errno);
4870 return NT_STATUS_OK;
4873 /****************************************************************************
4874 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4875 ****************************************************************************/
4877 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4878 struct smb_request *req,
4879 const char *pdata, int total_data,
4882 char *oldname = NULL;
4883 TALLOC_CTX *ctx = talloc_tos();
4884 NTSTATUS status = NT_STATUS_OK;
4886 /* Set a hard link. */
4887 if (total_data == 0) {
4888 return NT_STATUS_INVALID_PARAMETER;
4891 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
4892 total_data, STR_TERMINATE, &status);
4893 if (!NT_STATUS_IS_OK(status)) {
4897 status = resolve_dfspath(ctx, conn,
4898 req->flags2 & FLAGS2_DFS_PATHNAMES,
4901 if (!NT_STATUS_IS_OK(status)) {
4905 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4908 return hardlink_internals(ctx, conn, oldname, fname);
4911 /****************************************************************************
4912 Deal with SMB_FILE_RENAME_INFORMATION.
4913 ****************************************************************************/
4915 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4916 struct smb_request *req,
4925 char *newname = NULL;
4926 char *base_name = NULL;
4927 bool dest_has_wcard = False;
4928 NTSTATUS status = NT_STATUS_OK;
4930 TALLOC_CTX *ctx = talloc_tos();
4932 if (total_data < 13) {
4933 return NT_STATUS_INVALID_PARAMETER;
4936 overwrite = (CVAL(pdata,0) ? True : False);
4937 root_fid = IVAL(pdata,4);
4938 len = IVAL(pdata,8);
4940 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4941 return NT_STATUS_INVALID_PARAMETER;
4944 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
4947 if (!NT_STATUS_IS_OK(status)) {
4951 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4954 status = resolve_dfspath_wcard(ctx, conn,
4955 req->flags2 & FLAGS2_DFS_PATHNAMES,
4959 if (!NT_STATUS_IS_OK(status)) {
4963 /* Check the new name has no '/' characters. */
4964 if (strchr_m(newname, '/')) {
4965 return NT_STATUS_NOT_SUPPORTED;
4968 /* Create the base directory. */
4969 base_name = talloc_strdup(ctx, fname);
4971 return NT_STATUS_NO_MEMORY;
4973 p = strrchr_m(base_name, '/');
4977 base_name = talloc_strdup(ctx, "./");
4979 return NT_STATUS_NO_MEMORY;
4982 /* Append the new name. */
4983 base_name = talloc_asprintf_append(base_name,
4987 return NT_STATUS_NO_MEMORY;
4991 SMB_STRUCT_STAT sbuf;
4992 char *newname_last_component = NULL;
4996 status = unix_convert(ctx, conn, newname, False,
4998 &newname_last_component,
5001 /* If an error we expect this to be
5002 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5004 if (!NT_STATUS_IS_OK(status)
5005 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5010 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5011 fsp->fnum, fsp->fsp_name, base_name ));
5012 status = rename_internals_fsp(conn, fsp, base_name,
5013 newname_last_component, 0,
5016 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5017 fname, base_name ));
5018 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5019 overwrite, False, dest_has_wcard);
5025 /****************************************************************************
5026 Deal with SMB_SET_POSIX_ACL.
5027 ****************************************************************************/
5029 #if defined(HAVE_POSIX_ACLS)
5030 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5035 SMB_STRUCT_STAT *psbuf)
5037 uint16 posix_acl_version;
5038 uint16 num_file_acls;
5039 uint16 num_def_acls;
5040 bool valid_file_acls = True;
5041 bool valid_def_acls = True;
5043 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5044 return NT_STATUS_INVALID_PARAMETER;
5046 posix_acl_version = SVAL(pdata,0);
5047 num_file_acls = SVAL(pdata,2);
5048 num_def_acls = SVAL(pdata,4);
5050 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5051 valid_file_acls = False;
5055 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5056 valid_def_acls = False;
5060 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5061 return NT_STATUS_INVALID_PARAMETER;
5064 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5065 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5066 return NT_STATUS_INVALID_PARAMETER;
5069 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5070 fname ? fname : fsp->fsp_name,
5071 (unsigned int)num_file_acls,
5072 (unsigned int)num_def_acls));
5074 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5075 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5076 return map_nt_error_from_unix(errno);
5079 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5080 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5081 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5082 return map_nt_error_from_unix(errno);
5084 return NT_STATUS_OK;
5088 /****************************************************************************
5089 Deal with SMB_SET_POSIX_LOCK.
5090 ****************************************************************************/
5092 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5100 SMB_BIG_UINT offset;
5102 bool blocking_lock = False;
5103 enum brl_type lock_type;
5104 NTSTATUS status = NT_STATUS_OK;
5106 if (fsp == NULL || fsp->fh->fd == -1) {
5107 return NT_STATUS_INVALID_HANDLE;
5110 if (total_data != POSIX_LOCK_DATA_SIZE) {
5111 return NT_STATUS_INVALID_PARAMETER;
5114 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5115 case POSIX_LOCK_TYPE_READ:
5116 lock_type = READ_LOCK;
5118 case POSIX_LOCK_TYPE_WRITE:
5119 /* Return the right POSIX-mappable error code for files opened read-only. */
5120 if (!fsp->can_write) {
5121 return NT_STATUS_INVALID_HANDLE;
5123 lock_type = WRITE_LOCK;
5125 case POSIX_LOCK_TYPE_UNLOCK:
5126 lock_type = UNLOCK_LOCK;
5129 return NT_STATUS_INVALID_PARAMETER;
5132 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5133 blocking_lock = False;
5134 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5135 blocking_lock = True;
5137 return NT_STATUS_INVALID_PARAMETER;
5140 if (!lp_blocking_locks(SNUM(conn))) {
5141 blocking_lock = False;
5144 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5145 #if defined(HAVE_LONGLONG)
5146 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5147 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5148 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5149 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5150 #else /* HAVE_LONGLONG */
5151 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5152 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5153 #endif /* HAVE_LONGLONG */
5155 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5156 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5158 (unsigned int)lock_type,
5159 (unsigned int)lock_pid,
5163 if (lock_type == UNLOCK_LOCK) {
5164 status = do_unlock(smbd_messaging_context(),
5171 uint32 block_smbpid;
5173 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5184 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5186 * A blocking lock was requested. Package up
5187 * this smb into a queued request and push it
5188 * onto the blocking lock queue.
5190 if(push_blocking_lock_request(br_lck,
5191 (char *)inbuf, length,
5193 -1, /* infinite timeout. */
5201 TALLOC_FREE(br_lck);
5205 TALLOC_FREE(br_lck);
5211 /****************************************************************************
5212 Deal with SMB_INFO_STANDARD.
5213 ****************************************************************************/
5215 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5220 const SMB_STRUCT_STAT *psbuf)
5222 struct timespec ts[2];
5224 if (total_data < 12) {
5225 return NT_STATUS_INVALID_PARAMETER;
5229 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5231 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5233 DEBUG(10,("smb_set_info_standard: file %s\n",
5234 fname ? fname : fsp->fsp_name ));
5236 return smb_set_file_time(conn,
5244 /****************************************************************************
5245 Deal with SMB_SET_FILE_BASIC_INFO.
5246 ****************************************************************************/
5248 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5253 SMB_STRUCT_STAT *psbuf)
5255 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5256 struct timespec write_time;
5257 struct timespec changed_time;
5259 struct timespec ts[2];
5260 NTSTATUS status = NT_STATUS_OK;
5261 bool setting_write_time = true;
5263 if (total_data < 36) {
5264 return NT_STATUS_INVALID_PARAMETER;
5267 /* Set the attributes */
5268 dosmode = IVAL(pdata,32);
5269 status = smb_set_file_dosmode(conn,
5273 if (!NT_STATUS_IS_OK(status)) {
5277 /* Ignore create time at offset pdata. */
5280 ts[0] = interpret_long_date(pdata+8);
5282 write_time = interpret_long_date(pdata+16);
5283 changed_time = interpret_long_date(pdata+24);
5286 ts[1] = timespec_min(&write_time, &changed_time);
5288 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5292 /* Prefer a defined time to an undefined one. */
5293 if (null_timespec(ts[1])) {
5294 if (null_timespec(write_time)) {
5295 ts[1] = changed_time;
5296 setting_write_time = false;
5302 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5303 fname ? fname : fsp->fsp_name ));
5305 return smb_set_file_time(conn,
5310 setting_write_time);
5313 /****************************************************************************
5314 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5315 ****************************************************************************/
5317 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5318 struct smb_request *req,
5323 SMB_STRUCT_STAT *psbuf)
5325 SMB_BIG_UINT allocation_size = 0;
5326 NTSTATUS status = NT_STATUS_OK;
5327 files_struct *new_fsp = NULL;
5329 if (!VALID_STAT(*psbuf)) {
5330 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5333 if (total_data < 8) {
5334 return NT_STATUS_INVALID_PARAMETER;
5337 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5338 #ifdef LARGE_SMB_OFF_T
5339 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5340 #else /* LARGE_SMB_OFF_T */
5341 if (IVAL(pdata,4) != 0) {
5342 /* more than 32 bits? */
5343 return NT_STATUS_INVALID_PARAMETER;
5345 #endif /* LARGE_SMB_OFF_T */
5347 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5348 fname, (double)allocation_size ));
5350 if (allocation_size) {
5351 allocation_size = smb_roundup(conn, allocation_size);
5354 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5355 fname, (double)allocation_size ));
5357 if (fsp && fsp->fh->fd != -1) {
5358 /* Open file handle. */
5359 /* Only change if needed. */
5360 if (allocation_size != get_file_size(*psbuf)) {
5361 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5362 return map_nt_error_from_unix(errno);
5365 /* But always update the time. */
5366 if (null_timespec(fsp->pending_modtime)) {
5368 * This is equivalent to a write. Ensure it's seen immediately
5369 * if there are no pending writes.
5371 set_filetime(fsp->conn, fsp->fsp_name,
5372 timespec_current());
5374 return NT_STATUS_OK;
5377 /* Pathname or stat or directory file. */
5379 status = open_file_ntcreate(conn, req, fname, psbuf,
5381 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5384 FILE_ATTRIBUTE_NORMAL,
5385 FORCE_OPLOCK_BREAK_TO_NONE,
5388 if (!NT_STATUS_IS_OK(status)) {
5389 /* NB. We check for open_was_deferred in the caller. */
5393 /* Only change if needed. */
5394 if (allocation_size != get_file_size(*psbuf)) {
5395 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5396 status = map_nt_error_from_unix(errno);
5397 close_file(new_fsp,NORMAL_CLOSE);
5402 /* Changing the allocation size should set the last mod time. */
5403 /* Don't need to call set_filetime as this will be flushed on
5406 fsp_set_pending_modtime(new_fsp, timespec_current());
5408 close_file(new_fsp,NORMAL_CLOSE);
5409 return NT_STATUS_OK;
5412 /****************************************************************************
5413 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5414 ****************************************************************************/
5416 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5417 struct smb_request *req,
5422 SMB_STRUCT_STAT *psbuf)
5426 if (total_data < 8) {
5427 return NT_STATUS_INVALID_PARAMETER;
5430 size = IVAL(pdata,0);
5431 #ifdef LARGE_SMB_OFF_T
5432 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5433 #else /* LARGE_SMB_OFF_T */
5434 if (IVAL(pdata,4) != 0) {
5435 /* more than 32 bits? */
5436 return NT_STATUS_INVALID_PARAMETER;
5438 #endif /* LARGE_SMB_OFF_T */
5439 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5440 "file %s to %.0f\n", fname, (double)size ));
5442 return smb_set_file_size(conn, req,
5449 /****************************************************************************
5450 Allow a UNIX info mknod.
5451 ****************************************************************************/
5453 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5457 SMB_STRUCT_STAT *psbuf)
5459 uint32 file_type = IVAL(pdata,56);
5460 #if defined(HAVE_MAKEDEV)
5461 uint32 dev_major = IVAL(pdata,60);
5462 uint32 dev_minor = IVAL(pdata,68);
5464 SMB_DEV_T dev = (SMB_DEV_T)0;
5465 uint32 raw_unixmode = IVAL(pdata,84);
5469 if (total_data < 100) {
5470 return NT_STATUS_INVALID_PARAMETER;
5473 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5474 if (!NT_STATUS_IS_OK(status)) {
5478 #if defined(HAVE_MAKEDEV)
5479 dev = makedev(dev_major, dev_minor);
5482 switch (file_type) {
5483 #if defined(S_IFIFO)
5484 case UNIX_TYPE_FIFO:
5485 unixmode |= S_IFIFO;
5488 #if defined(S_IFSOCK)
5489 case UNIX_TYPE_SOCKET:
5490 unixmode |= S_IFSOCK;
5493 #if defined(S_IFCHR)
5494 case UNIX_TYPE_CHARDEV:
5495 unixmode |= S_IFCHR;
5498 #if defined(S_IFBLK)
5499 case UNIX_TYPE_BLKDEV:
5500 unixmode |= S_IFBLK;
5504 return NT_STATUS_INVALID_PARAMETER;
5507 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5508 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5510 /* Ok - do the mknod. */
5511 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5512 return map_nt_error_from_unix(errno);
5515 /* If any of the other "set" calls fail we
5516 * don't want to end up with a half-constructed mknod.
5519 if (lp_inherit_perms(SNUM(conn))) {
5521 conn, parent_dirname(fname),
5525 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5526 status = map_nt_error_from_unix(errno);
5527 SMB_VFS_UNLINK(conn,fname);
5530 return NT_STATUS_OK;
5533 /****************************************************************************
5534 Deal with SMB_SET_FILE_UNIX_BASIC.
5535 ****************************************************************************/
5537 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5538 struct smb_request *req,
5543 SMB_STRUCT_STAT *psbuf)
5545 struct timespec ts[2];
5546 uint32 raw_unixmode;
5549 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5550 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5551 NTSTATUS status = NT_STATUS_OK;
5552 bool delete_on_fail = False;
5553 enum perm_type ptype;
5555 if (total_data < 100) {
5556 return NT_STATUS_INVALID_PARAMETER;
5559 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5560 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5561 size=IVAL(pdata,0); /* first 8 Bytes are size */
5562 #ifdef LARGE_SMB_OFF_T
5563 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5564 #else /* LARGE_SMB_OFF_T */
5565 if (IVAL(pdata,4) != 0) {
5566 /* more than 32 bits? */
5567 return NT_STATUS_INVALID_PARAMETER;
5569 #endif /* LARGE_SMB_OFF_T */
5572 ts[0] = interpret_long_date(pdata+24); /* access_time */
5573 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5574 set_owner = (uid_t)IVAL(pdata,40);
5575 set_grp = (gid_t)IVAL(pdata,48);
5576 raw_unixmode = IVAL(pdata,84);
5578 if (VALID_STAT(*psbuf)) {
5579 if (S_ISDIR(psbuf->st_mode)) {
5580 ptype = PERM_EXISTING_DIR;
5582 ptype = PERM_EXISTING_FILE;
5585 ptype = PERM_NEW_FILE;
5588 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5589 if (!NT_STATUS_IS_OK(status)) {
5593 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5594 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5595 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5597 if (!VALID_STAT(*psbuf)) {
5599 * The only valid use of this is to create character and block
5600 * devices, and named pipes. This is deprecated (IMHO) and
5601 * a new info level should be used for mknod. JRA.
5604 status = smb_unix_mknod(conn,
5609 if (!NT_STATUS_IS_OK(status)) {
5613 /* Ensure we don't try and change anything else. */
5614 raw_unixmode = SMB_MODE_NO_CHANGE;
5615 size = get_file_size(*psbuf);
5616 ts[0] = get_atimespec(psbuf);
5617 ts[1] = get_mtimespec(psbuf);
5619 * We continue here as we might want to change the
5622 delete_on_fail = True;
5626 /* Horrible backwards compatibility hack as an old server bug
5627 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5631 size = get_file_size(*psbuf);
5636 * Deal with the UNIX specific mode set.
5639 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5640 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5641 (unsigned int)unixmode, fname ));
5642 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5643 return map_nt_error_from_unix(errno);
5648 * Deal with the UNIX specific uid set.
5651 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5654 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5655 (unsigned int)set_owner, fname ));
5657 if (S_ISLNK(psbuf->st_mode)) {
5658 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5660 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5664 status = map_nt_error_from_unix(errno);
5665 if (delete_on_fail) {
5666 SMB_VFS_UNLINK(conn,fname);
5673 * Deal with the UNIX specific gid set.
5676 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5677 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5678 (unsigned int)set_owner, fname ));
5679 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5680 status = map_nt_error_from_unix(errno);
5681 if (delete_on_fail) {
5682 SMB_VFS_UNLINK(conn,fname);
5688 /* Deal with any size changes. */
5690 status = smb_set_file_size(conn, req,
5695 if (!NT_STATUS_IS_OK(status)) {
5699 /* Deal with any time changes. */
5701 return smb_set_file_time(conn,
5709 /****************************************************************************
5710 Deal with SMB_SET_FILE_UNIX_INFO2.
5711 ****************************************************************************/
5713 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5714 struct smb_request *req,
5719 SMB_STRUCT_STAT *psbuf)
5725 if (total_data < 116) {
5726 return NT_STATUS_INVALID_PARAMETER;
5729 /* Start by setting all the fields that are common between UNIX_BASIC
5732 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5734 if (!NT_STATUS_IS_OK(status)) {
5738 smb_fflags = IVAL(pdata, 108);
5739 smb_fmask = IVAL(pdata, 112);
5741 /* NB: We should only attempt to alter the file flags if the client
5742 * sends a non-zero mask.
5744 if (smb_fmask != 0) {
5745 int stat_fflags = 0;
5747 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5749 /* Client asked to alter a flag we don't understand. */
5750 return NT_STATUS_INVALID_PARAMETER;
5753 if (fsp && fsp->fh->fd != -1) {
5754 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5755 return NT_STATUS_NOT_SUPPORTED;
5757 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5758 return map_nt_error_from_unix(errno);
5763 /* XXX: need to add support for changing the create_time here. You
5764 * can do this for paths on Darwin with setattrlist(2). The right way
5765 * to hook this up is probably by extending the VFS utimes interface.
5768 return NT_STATUS_OK;
5771 /****************************************************************************
5772 Create a directory with POSIX semantics.
5773 ****************************************************************************/
5775 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5776 struct smb_request *req,
5780 SMB_STRUCT_STAT *psbuf,
5781 int *pdata_return_size)
5783 NTSTATUS status = NT_STATUS_OK;
5784 uint32 raw_unixmode = 0;
5785 uint32 mod_unixmode = 0;
5786 mode_t unixmode = (mode_t)0;
5787 files_struct *fsp = NULL;
5788 uint16 info_level_return = 0;
5790 char *pdata = *ppdata;
5792 if (total_data < 18) {
5793 return NT_STATUS_INVALID_PARAMETER;
5796 raw_unixmode = IVAL(pdata,8);
5797 /* Next 4 bytes are not yet defined. */
5799 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5800 if (!NT_STATUS_IS_OK(status)) {
5804 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5806 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5807 fname, (unsigned int)unixmode ));
5809 status = open_directory(conn, req,
5812 FILE_READ_ATTRIBUTES, /* Just a stat open */
5813 FILE_SHARE_NONE, /* Ignored for stat opens */
5820 if (NT_STATUS_IS_OK(status)) {
5821 close_file(fsp, NORMAL_CLOSE);
5824 info_level_return = SVAL(pdata,16);
5826 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5827 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5828 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5829 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5831 *pdata_return_size = 12;
5834 /* Realloc the data size */
5835 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5836 if (*ppdata == NULL) {
5837 *pdata_return_size = 0;
5838 return NT_STATUS_NO_MEMORY;
5842 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5843 SSVAL(pdata,2,0); /* No fnum. */
5844 SIVAL(pdata,4,info); /* Was directory created. */
5846 switch (info_level_return) {
5847 case SMB_QUERY_FILE_UNIX_BASIC:
5848 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5849 SSVAL(pdata,10,0); /* Padding. */
5850 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5852 case SMB_QUERY_FILE_UNIX_INFO2:
5853 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5854 SSVAL(pdata,10,0); /* Padding. */
5855 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5858 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5859 SSVAL(pdata,10,0); /* Padding. */
5866 /****************************************************************************
5867 Open/Create a file with POSIX semantics.
5868 ****************************************************************************/
5870 static NTSTATUS smb_posix_open(connection_struct *conn,
5871 struct smb_request *req,
5875 SMB_STRUCT_STAT *psbuf,
5876 int *pdata_return_size)
5878 bool extended_oplock_granted = False;
5879 char *pdata = *ppdata;
5881 uint32 wire_open_mode = 0;
5882 uint32 raw_unixmode = 0;
5883 uint32 mod_unixmode = 0;
5884 uint32 create_disp = 0;
5885 uint32 access_mask = 0;
5886 uint32 create_options = 0;
5887 NTSTATUS status = NT_STATUS_OK;
5888 mode_t unixmode = (mode_t)0;
5889 files_struct *fsp = NULL;
5890 int oplock_request = 0;
5892 uint16 info_level_return = 0;
5894 if (total_data < 18) {
5895 return NT_STATUS_INVALID_PARAMETER;
5898 flags = IVAL(pdata,0);
5899 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5900 if (oplock_request) {
5901 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5904 wire_open_mode = IVAL(pdata,4);
5906 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5907 return smb_posix_mkdir(conn, req,
5915 switch (wire_open_mode & SMB_ACCMODE) {
5917 access_mask = FILE_READ_DATA;
5920 access_mask = FILE_WRITE_DATA;
5923 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5926 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5927 (unsigned int)wire_open_mode ));
5928 return NT_STATUS_INVALID_PARAMETER;
5931 wire_open_mode &= ~SMB_ACCMODE;
5933 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5934 create_disp = FILE_CREATE;
5935 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5936 create_disp = FILE_OVERWRITE_IF;
5937 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5938 create_disp = FILE_OPEN_IF;
5940 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5941 (unsigned int)wire_open_mode ));
5942 return NT_STATUS_INVALID_PARAMETER;
5945 raw_unixmode = IVAL(pdata,8);
5946 /* Next 4 bytes are not yet defined. */
5948 status = unix_perms_from_wire(conn,
5951 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5954 if (!NT_STATUS_IS_OK(status)) {
5958 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5960 if (wire_open_mode & SMB_O_SYNC) {
5961 create_options |= FILE_WRITE_THROUGH;
5963 if (wire_open_mode & SMB_O_APPEND) {
5964 access_mask |= FILE_APPEND_DATA;
5966 if (wire_open_mode & SMB_O_DIRECT) {
5967 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5970 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5972 (unsigned int)wire_open_mode,
5973 (unsigned int)unixmode ));
5975 status = open_file_ntcreate(conn, req,
5979 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5981 0, /* no create options yet. */
5987 if (!NT_STATUS_IS_OK(status)) {
5991 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5992 extended_oplock_granted = True;
5995 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5996 extended_oplock_granted = True;
5999 info_level_return = SVAL(pdata,16);
6001 /* Allocate the correct return size. */
6003 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6004 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6005 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6006 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6008 *pdata_return_size = 12;
6011 /* Realloc the data size */
6012 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6013 if (*ppdata == NULL) {
6014 close_file(fsp,ERROR_CLOSE);
6015 *pdata_return_size = 0;
6016 return NT_STATUS_NO_MEMORY;
6020 if (extended_oplock_granted) {
6021 if (flags & REQUEST_BATCH_OPLOCK) {
6022 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6024 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6026 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6027 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6029 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6032 SSVAL(pdata,2,fsp->fnum);
6033 SIVAL(pdata,4,info); /* Was file created etc. */
6035 switch (info_level_return) {
6036 case SMB_QUERY_FILE_UNIX_BASIC:
6037 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6038 SSVAL(pdata,10,0); /* padding. */
6039 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6041 case SMB_QUERY_FILE_UNIX_INFO2:
6042 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6043 SSVAL(pdata,10,0); /* padding. */
6044 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6047 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6048 SSVAL(pdata,10,0); /* padding. */
6051 return NT_STATUS_OK;
6054 /****************************************************************************
6055 Delete a file with POSIX semantics.
6056 ****************************************************************************/
6058 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6059 struct smb_request *req,
6063 SMB_STRUCT_STAT *psbuf)
6065 NTSTATUS status = NT_STATUS_OK;
6066 files_struct *fsp = NULL;
6071 struct share_mode_lock *lck = NULL;
6073 if (total_data < 2) {
6074 return NT_STATUS_INVALID_PARAMETER;
6077 flags = SVAL(pdata,0);
6079 if (!VALID_STAT(*psbuf)) {
6080 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6083 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6084 !VALID_STAT_OF_DIR(*psbuf)) {
6085 return NT_STATUS_NOT_A_DIRECTORY;
6088 DEBUG(10,("smb_posix_unlink: %s %s\n",
6089 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6092 if (VALID_STAT_OF_DIR(*psbuf)) {
6093 status = open_directory(conn, req,
6097 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6100 FILE_FLAG_POSIX_SEMANTICS|0777,
6105 status = open_file_ntcreate(conn, req,
6109 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6112 FILE_FLAG_POSIX_SEMANTICS|0777,
6113 0, /* No oplock, but break existing ones. */
6118 if (!NT_STATUS_IS_OK(status)) {
6123 * Don't lie to client. If we can't really delete due to
6124 * non-POSIX opens return SHARING_VIOLATION.
6127 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
6129 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6130 "lock for file %s\n", fsp->fsp_name));
6131 close_file(fsp, NORMAL_CLOSE);
6132 return NT_STATUS_INVALID_PARAMETER;
6136 * See if others still have the file open. If this is the case, then
6137 * don't delete. If all opens are POSIX delete we can set the delete
6138 * on close disposition.
6140 for (i=0; i<lck->num_share_modes; i++) {
6141 struct share_mode_entry *e = &lck->share_modes[i];
6142 if (is_valid_share_mode_entry(e)) {
6143 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6146 /* Fail with sharing violation. */
6147 close_file(fsp, NORMAL_CLOSE);
6149 return NT_STATUS_SHARING_VIOLATION;
6154 * Set the delete on close.
6156 status = smb_set_file_disposition_info(conn,
6163 if (!NT_STATUS_IS_OK(status)) {
6164 close_file(fsp, NORMAL_CLOSE);
6169 return close_file(fsp, NORMAL_CLOSE);
6172 /****************************************************************************
6173 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6174 ****************************************************************************/
6176 static void call_trans2setfilepathinfo(connection_struct *conn,
6177 struct smb_request *req,
6178 unsigned int tran_call,
6179 char **pparams, int total_params,
6180 char **ppdata, int total_data,
6181 unsigned int max_data_bytes)
6183 char *params = *pparams;
6184 char *pdata = *ppdata;
6186 SMB_STRUCT_STAT sbuf;
6188 files_struct *fsp = NULL;
6189 NTSTATUS status = NT_STATUS_OK;
6190 int data_return_size = 0;
6191 TALLOC_CTX *ctx = talloc_tos();
6194 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6200 if (tran_call == TRANSACT2_SETFILEINFO) {
6201 if (total_params < 4) {
6202 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6206 fsp = file_fsp(SVAL(params,0));
6207 /* Basic check for non-null fsp. */
6208 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
6211 info_level = SVAL(params,2);
6213 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6215 reply_nterror(req, NT_STATUS_NO_MEMORY);
6219 if(fsp->is_directory || fsp->fh->fd == -1) {
6221 * This is actually a SETFILEINFO on a directory
6222 * handle (returned from an NT SMB). NT5.0 seems
6223 * to do this call. JRA.
6225 if (INFO_LEVEL_IS_UNIX(info_level)) {
6226 /* Always do lstat for UNIX calls. */
6227 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6228 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6229 reply_unixerror(req,ERRDOS,ERRbadpath);
6233 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6234 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6235 reply_unixerror(req,ERRDOS,ERRbadpath);
6239 } else if (fsp->print_file) {
6241 * Doing a DELETE_ON_CLOSE should cancel a print job.
6243 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6244 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6246 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6249 send_trans2_replies(req, params, 2,
6254 reply_unixerror(req, ERRDOS, ERRbadpath);
6259 * Original code - this is an open file.
6261 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6265 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6266 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6267 reply_unixerror(req, ERRDOS, ERRbadfid);
6273 if (total_params < 7) {
6274 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6278 info_level = SVAL(params,0);
6279 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6280 total_params - 6, STR_TERMINATE,
6282 if (!NT_STATUS_IS_OK(status)) {
6283 reply_nterror(req, status);
6287 status = resolve_dfspath(ctx, conn,
6288 req->flags2 & FLAGS2_DFS_PATHNAMES,
6291 if (!NT_STATUS_IS_OK(status)) {
6292 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6293 reply_botherror(req,
6294 NT_STATUS_PATH_NOT_COVERED,
6295 ERRSRV, ERRbadpath);
6298 reply_nterror(req, status);
6302 status = unix_convert(ctx, conn, fname, False,
6303 &fname, NULL, &sbuf);
6304 if (!NT_STATUS_IS_OK(status)) {
6305 reply_nterror(req, status);
6309 status = check_name(conn, fname);
6310 if (!NT_STATUS_IS_OK(status)) {
6311 reply_nterror(req, status);
6315 if (INFO_LEVEL_IS_UNIX(info_level)) {
6317 * For CIFS UNIX extensions the target name may not exist.
6320 /* Always do lstat for UNIX calls. */
6321 SMB_VFS_LSTAT(conn,fname,&sbuf);
6323 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6324 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6325 reply_unixerror(req, ERRDOS, ERRbadpath);
6330 if (!CAN_WRITE(conn)) {
6331 reply_doserror(req, ERRSRV, ERRaccess);
6335 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6336 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6340 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6341 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6343 /* Realloc the parameter size */
6344 *pparams = (char *)SMB_REALLOC(*pparams,2);
6345 if (*pparams == NULL) {
6346 reply_nterror(req, NT_STATUS_NO_MEMORY);
6353 if (fsp && !null_timespec(fsp->pending_modtime)) {
6354 /* the pending modtime overrides the current modtime */
6355 set_mtimespec(&sbuf, fsp->pending_modtime);
6358 switch (info_level) {
6360 case SMB_INFO_STANDARD:
6362 status = smb_set_info_standard(conn,
6371 case SMB_INFO_SET_EA:
6373 status = smb_info_set_ea(conn,
6381 case SMB_SET_FILE_BASIC_INFO:
6382 case SMB_FILE_BASIC_INFORMATION:
6384 status = smb_set_file_basic_info(conn,
6393 case SMB_FILE_ALLOCATION_INFORMATION:
6394 case SMB_SET_FILE_ALLOCATION_INFO:
6396 status = smb_set_file_allocation_info(conn, req,
6405 case SMB_FILE_END_OF_FILE_INFORMATION:
6406 case SMB_SET_FILE_END_OF_FILE_INFO:
6408 status = smb_set_file_end_of_file_info(conn, req,
6417 case SMB_FILE_DISPOSITION_INFORMATION:
6418 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6421 /* JRA - We used to just ignore this on a path ?
6422 * Shouldn't this be invalid level on a pathname
6425 if (tran_call != TRANSACT2_SETFILEINFO) {
6426 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6429 status = smb_set_file_disposition_info(conn,
6438 case SMB_FILE_POSITION_INFORMATION:
6440 status = smb_file_position_information(conn,
6447 /* From tridge Samba4 :
6448 * MODE_INFORMATION in setfileinfo (I have no
6449 * idea what "mode information" on a file is - it takes a value of 0,
6450 * 2, 4 or 6. What could it be?).
6453 case SMB_FILE_MODE_INFORMATION:
6455 status = smb_file_mode_information(conn,
6462 * CIFS UNIX extensions.
6465 case SMB_SET_FILE_UNIX_BASIC:
6467 status = smb_set_file_unix_basic(conn, req,
6476 case SMB_SET_FILE_UNIX_INFO2:
6478 status = smb_set_file_unix_info2(conn, req,
6487 case SMB_SET_FILE_UNIX_LINK:
6489 if (tran_call != TRANSACT2_SETPATHINFO) {
6490 /* We must have a pathname for this. */
6491 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6494 status = smb_set_file_unix_link(conn, req, pdata,
6499 case SMB_SET_FILE_UNIX_HLINK:
6501 if (tran_call != TRANSACT2_SETPATHINFO) {
6502 /* We must have a pathname for this. */
6503 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6506 status = smb_set_file_unix_hlink(conn, req,
6512 case SMB_FILE_RENAME_INFORMATION:
6514 status = smb_file_rename_information(conn, req,
6520 #if defined(HAVE_POSIX_ACLS)
6521 case SMB_SET_POSIX_ACL:
6523 status = smb_set_posix_acl(conn,
6533 case SMB_SET_POSIX_LOCK:
6535 if (tran_call != TRANSACT2_SETFILEINFO) {
6536 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6539 status = smb_set_posix_lock(conn, req->inbuf,
6540 smb_len(req->inbuf) + 4,
6541 pdata, total_data, fsp);
6545 case SMB_POSIX_PATH_OPEN:
6547 if (tran_call != TRANSACT2_SETPATHINFO) {
6548 /* We must have a pathname for this. */
6549 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6553 status = smb_posix_open(conn, req,
6562 case SMB_POSIX_PATH_UNLINK:
6564 if (tran_call != TRANSACT2_SETPATHINFO) {
6565 /* We must have a pathname for this. */
6566 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6570 status = smb_posix_unlink(conn, req,
6579 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6584 if (!NT_STATUS_IS_OK(status)) {
6585 if (open_was_deferred(req->mid)) {
6586 /* We have re-scheduled this call. */
6589 if (blocking_lock_was_deferred(req->mid)) {
6590 /* We have re-scheduled this call. */
6593 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6594 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6595 ERRSRV, ERRbadpath);
6598 if (info_level == SMB_POSIX_PATH_OPEN) {
6599 reply_openerror(req, status);
6603 reply_nterror(req, status);
6608 send_trans2_replies(req, params, 2, *ppdata, data_return_size,
6614 /****************************************************************************
6615 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6616 ****************************************************************************/
6618 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6619 char **pparams, int total_params,
6620 char **ppdata, int total_data,
6621 unsigned int max_data_bytes)
6623 char *params = *pparams;
6624 char *pdata = *ppdata;
6625 char *directory = NULL;
6626 SMB_STRUCT_STAT sbuf;
6627 NTSTATUS status = NT_STATUS_OK;
6628 struct ea_list *ea_list = NULL;
6629 TALLOC_CTX *ctx = talloc_tos();
6631 if (!CAN_WRITE(conn)) {
6632 reply_doserror(req, ERRSRV, ERRaccess);
6636 if (total_params < 5) {
6637 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6641 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
6642 total_params - 4, STR_TERMINATE,
6644 if (!NT_STATUS_IS_OK(status)) {
6645 reply_nterror(req, status);
6649 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6651 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6652 if (!NT_STATUS_IS_OK(status)) {
6653 reply_nterror(req, status);
6657 status = check_name(conn, directory);
6658 if (!NT_STATUS_IS_OK(status)) {
6659 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6660 reply_nterror(req, status);
6664 /* Any data in this call is an EA list. */
6665 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6666 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6671 * OS/2 workplace shell seems to send SET_EA requests of "null"
6672 * length (4 bytes containing IVAL 4).
6673 * They seem to have no effect. Bug #3212. JRA.
6676 if (total_data != 4) {
6677 if (total_data < 10) {
6678 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6682 if (IVAL(pdata,0) > total_data) {
6683 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6684 IVAL(pdata,0), (unsigned int)total_data));
6685 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6689 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6692 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6695 } else if (IVAL(pdata,0) != 4) {
6696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6700 status = create_directory(conn, directory);
6702 if (!NT_STATUS_IS_OK(status)) {
6703 reply_nterror(req, status);
6707 /* Try and set any given EA. */
6709 status = set_ea(conn, NULL, directory, ea_list);
6710 if (!NT_STATUS_IS_OK(status)) {
6711 reply_nterror(req, status);
6716 /* Realloc the parameter and data sizes */
6717 *pparams = (char *)SMB_REALLOC(*pparams,2);
6718 if(*pparams == NULL) {
6719 reply_nterror(req, NT_STATUS_NO_MEMORY);
6726 send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
6731 /****************************************************************************
6732 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6733 We don't actually do this - we just send a null response.
6734 ****************************************************************************/
6736 static void call_trans2findnotifyfirst(connection_struct *conn,
6737 struct smb_request *req,
6738 char **pparams, int total_params,
6739 char **ppdata, int total_data,
6740 unsigned int max_data_bytes)
6742 static uint16 fnf_handle = 257;
6743 char *params = *pparams;
6746 if (total_params < 6) {
6747 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6751 info_level = SVAL(params,4);
6752 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6754 switch (info_level) {
6759 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6763 /* Realloc the parameter and data sizes */
6764 *pparams = (char *)SMB_REALLOC(*pparams,6);
6765 if (*pparams == NULL) {
6766 reply_nterror(req, NT_STATUS_NO_MEMORY);
6771 SSVAL(params,0,fnf_handle);
6772 SSVAL(params,2,0); /* No changes */
6773 SSVAL(params,4,0); /* No EA errors */
6780 send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
6785 /****************************************************************************
6786 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6787 changes). Currently this does nothing.
6788 ****************************************************************************/
6790 static void call_trans2findnotifynext(connection_struct *conn,
6791 struct smb_request *req,
6792 char **pparams, int total_params,
6793 char **ppdata, int total_data,
6794 unsigned int max_data_bytes)
6796 char *params = *pparams;
6798 DEBUG(3,("call_trans2findnotifynext\n"));
6800 /* Realloc the parameter and data sizes */
6801 *pparams = (char *)SMB_REALLOC(*pparams,4);
6802 if (*pparams == NULL) {
6803 reply_nterror(req, NT_STATUS_NO_MEMORY);
6808 SSVAL(params,0,0); /* No changes */
6809 SSVAL(params,2,0); /* No EA errors */
6811 send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes);
6816 /****************************************************************************
6817 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6818 ****************************************************************************/
6820 static void call_trans2getdfsreferral(connection_struct *conn,
6821 struct smb_request *req,
6822 char **pparams, int total_params,
6823 char **ppdata, int total_data,
6824 unsigned int max_data_bytes)
6826 char *params = *pparams;
6827 char *pathname = NULL;
6829 int max_referral_level;
6830 NTSTATUS status = NT_STATUS_OK;
6831 TALLOC_CTX *ctx = talloc_tos();
6833 DEBUG(10,("call_trans2getdfsreferral\n"));
6835 if (total_params < 3) {
6836 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6840 max_referral_level = SVAL(params,0);
6842 if(!lp_host_msdfs()) {
6843 reply_doserror(req, ERRDOS, ERRbadfunc);
6847 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
6848 total_params - 2, STR_TERMINATE);
6850 reply_nterror(req, NT_STATUS_NOT_FOUND);
6853 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6854 ppdata,&status)) < 0) {
6855 reply_nterror(req, status);
6859 SSVAL(req->inbuf, smb_flg2,
6860 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6861 send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes);
6866 #define LMCAT_SPL 0x53
6867 #define LMFUNC_GETJOBID 0x60
6869 /****************************************************************************
6870 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6871 ****************************************************************************/
6873 static void call_trans2ioctl(connection_struct *conn,
6874 struct smb_request *req,
6875 char **pparams, int total_params,
6876 char **ppdata, int total_data,
6877 unsigned int max_data_bytes)
6879 char *pdata = *ppdata;
6880 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6882 /* check for an invalid fid before proceeding */
6885 reply_doserror(req, ERRDOS, ERRbadfid);
6889 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6890 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6891 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6892 if (*ppdata == NULL) {
6893 reply_nterror(req, NT_STATUS_NO_MEMORY);
6898 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6899 CAN ACCEPT THIS IN UNICODE. JRA. */
6901 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6902 srvstr_push(pdata, req->flags2, pdata + 2,
6903 global_myname(), 15,
6904 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6905 srvstr_push(pdata, req->flags2, pdata+18,
6906 lp_servicename(SNUM(conn)), 13,
6907 STR_ASCII|STR_TERMINATE); /* Service name */
6908 send_trans2_replies(req, *pparams, 0, *ppdata, 32,
6913 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6914 reply_doserror(req, ERRSRV, ERRerror);
6917 /****************************************************************************
6918 Reply to a SMBfindclose (stop trans2 directory search).
6919 ****************************************************************************/
6921 void reply_findclose(connection_struct *conn, struct smb_request *req)
6925 START_PROFILE(SMBfindclose);
6928 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6929 END_PROFILE(SMBfindclose);
6933 dptr_num = SVALS(req->inbuf,smb_vwv0);
6935 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6937 dptr_close(&dptr_num);
6939 reply_outbuf(req, 0, 0);
6941 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6943 END_PROFILE(SMBfindclose);
6947 /****************************************************************************
6948 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6949 ****************************************************************************/
6951 void reply_findnclose(connection_struct *conn, struct smb_request *req)
6955 START_PROFILE(SMBfindnclose);
6958 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6959 END_PROFILE(SMBfindnclose);
6963 dptr_num = SVAL(req->inbuf,smb_vwv0);
6965 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6967 /* We never give out valid handles for a
6968 findnotifyfirst - so any dptr_num is ok here.
6971 reply_outbuf(req, 0, 0);
6973 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6975 END_PROFILE(SMBfindnclose);
6979 static void handle_trans2(connection_struct *conn, struct smb_request *req,
6980 struct trans_state *state)
6982 if (Protocol >= PROTOCOL_NT1) {
6983 req->flags2 |= 0x40; /* IS_LONG_NAME */
6984 SSVAL(req->inbuf,smb_flg2,req->flags2);
6987 /* Now we must call the relevant TRANS2 function */
6988 switch(state->call) {
6989 case TRANSACT2_OPEN:
6991 START_PROFILE(Trans2_open);
6992 call_trans2open(conn, req,
6993 &state->param, state->total_param,
6994 &state->data, state->total_data,
6995 state->max_data_return);
6996 END_PROFILE(Trans2_open);
7000 case TRANSACT2_FINDFIRST:
7002 START_PROFILE(Trans2_findfirst);
7003 call_trans2findfirst(conn, req,
7004 &state->param, state->total_param,
7005 &state->data, state->total_data,
7006 state->max_data_return);
7007 END_PROFILE(Trans2_findfirst);
7011 case TRANSACT2_FINDNEXT:
7013 START_PROFILE(Trans2_findnext);
7014 call_trans2findnext(conn, req,
7015 &state->param, state->total_param,
7016 &state->data, state->total_data,
7017 state->max_data_return);
7018 END_PROFILE(Trans2_findnext);
7022 case TRANSACT2_QFSINFO:
7024 START_PROFILE(Trans2_qfsinfo);
7025 call_trans2qfsinfo(conn, req,
7026 &state->param, state->total_param,
7027 &state->data, state->total_data,
7028 state->max_data_return);
7029 END_PROFILE(Trans2_qfsinfo);
7033 case TRANSACT2_SETFSINFO:
7035 START_PROFILE(Trans2_setfsinfo);
7036 call_trans2setfsinfo(conn, req,
7037 &state->param, state->total_param,
7038 &state->data, state->total_data,
7039 state->max_data_return);
7040 END_PROFILE(Trans2_setfsinfo);
7044 case TRANSACT2_QPATHINFO:
7045 case TRANSACT2_QFILEINFO:
7047 START_PROFILE(Trans2_qpathinfo);
7048 call_trans2qfilepathinfo(conn, req, state->call,
7049 &state->param, state->total_param,
7050 &state->data, state->total_data,
7051 state->max_data_return);
7052 END_PROFILE(Trans2_qpathinfo);
7056 case TRANSACT2_SETPATHINFO:
7057 case TRANSACT2_SETFILEINFO:
7059 START_PROFILE(Trans2_setpathinfo);
7060 call_trans2setfilepathinfo(conn, req, state->call,
7061 &state->param, state->total_param,
7062 &state->data, state->total_data,
7063 state->max_data_return);
7064 END_PROFILE(Trans2_setpathinfo);
7068 case TRANSACT2_FINDNOTIFYFIRST:
7070 START_PROFILE(Trans2_findnotifyfirst);
7071 call_trans2findnotifyfirst(conn, req,
7072 &state->param, state->total_param,
7073 &state->data, state->total_data,
7074 state->max_data_return);
7075 END_PROFILE(Trans2_findnotifyfirst);
7079 case TRANSACT2_FINDNOTIFYNEXT:
7081 START_PROFILE(Trans2_findnotifynext);
7082 call_trans2findnotifynext(conn, req,
7083 &state->param, state->total_param,
7084 &state->data, state->total_data,
7085 state->max_data_return);
7086 END_PROFILE(Trans2_findnotifynext);
7090 case TRANSACT2_MKDIR:
7092 START_PROFILE(Trans2_mkdir);
7093 call_trans2mkdir(conn, req,
7094 &state->param, state->total_param,
7095 &state->data, state->total_data,
7096 state->max_data_return);
7097 END_PROFILE(Trans2_mkdir);
7101 case TRANSACT2_GET_DFS_REFERRAL:
7103 START_PROFILE(Trans2_get_dfs_referral);
7104 call_trans2getdfsreferral(conn, req,
7105 &state->param, state->total_param,
7106 &state->data, state->total_data,
7107 state->max_data_return);
7108 END_PROFILE(Trans2_get_dfs_referral);
7112 case TRANSACT2_IOCTL:
7114 START_PROFILE(Trans2_ioctl);
7115 call_trans2ioctl(conn, req,
7116 &state->param, state->total_param,
7117 &state->data, state->total_data,
7118 state->max_data_return);
7119 END_PROFILE(Trans2_ioctl);
7124 /* Error in request */
7125 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7126 reply_doserror(req, ERRSRV,ERRerror);
7130 /****************************************************************************
7131 Reply to a SMBtrans2.
7132 ****************************************************************************/
7134 void reply_trans2(connection_struct *conn, struct smb_request *req)
7140 unsigned int tran_call;
7142 struct trans_state *state;
7145 START_PROFILE(SMBtrans2);
7147 if (req->wct < 14) {
7148 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7149 END_PROFILE(SMBtrans2);
7153 dsoff = SVAL(req->inbuf, smb_dsoff);
7154 dscnt = SVAL(req->inbuf, smb_dscnt);
7155 psoff = SVAL(req->inbuf, smb_psoff);
7156 pscnt = SVAL(req->inbuf, smb_pscnt);
7157 tran_call = SVAL(req->inbuf, smb_setup0);
7158 size = smb_len(req->inbuf) + 4;
7160 result = allow_new_trans(conn->pending_trans, req->mid);
7161 if (!NT_STATUS_IS_OK(result)) {
7162 DEBUG(2, ("Got invalid trans2 request: %s\n",
7163 nt_errstr(result)));
7164 reply_nterror(req, result);
7165 END_PROFILE(SMBtrans2);
7169 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
7170 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
7171 && (tran_call != TRANSACT2_QFILEINFO)) {
7172 reply_doserror(req, ERRSRV, ERRaccess);
7173 END_PROFILE(SMBtrans2);
7177 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7178 DEBUG(0, ("talloc failed\n"));
7179 reply_nterror(req, NT_STATUS_NO_MEMORY);
7180 END_PROFILE(SMBtrans2);
7184 state->cmd = SMBtrans2;
7186 state->mid = req->mid;
7187 state->vuid = req->vuid;
7188 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7189 state->setup = NULL;
7190 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7191 state->param = NULL;
7192 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7194 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7195 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7196 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7197 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7198 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7200 state->call = tran_call;
7202 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7203 is so as a sanity check */
7204 if (state->setup_count != 1) {
7206 * Need to have rc=0 for ioctl to get job id for OS/2.
7207 * Network printing will fail if function is not successful.
7208 * Similar function in reply.c will be used if protocol
7209 * is LANMAN1.0 instead of LM1.2X002.
7210 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7211 * outbuf doesn't have to be set(only job id is used).
7213 if ( (state->setup_count == 4)
7214 && (tran_call == TRANSACT2_IOCTL)
7215 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7216 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7217 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7219 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7220 DEBUG(2,("Transaction is %d\n",tran_call));
7222 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7223 END_PROFILE(SMBtrans2);
7228 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7231 if (state->total_data) {
7232 /* Can't use talloc here, the core routines do realloc on the
7233 * params and data. */
7234 state->data = (char *)SMB_MALLOC(state->total_data);
7235 if (state->data == NULL) {
7236 DEBUG(0,("reply_trans2: data malloc fail for %u "
7237 "bytes !\n", (unsigned int)state->total_data));
7239 reply_nterror(req, NT_STATUS_NO_MEMORY);
7240 END_PROFILE(SMBtrans2);
7243 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7245 if ((smb_base(req->inbuf)+dsoff+dscnt
7246 > (char *)req->inbuf + size) ||
7247 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7250 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7253 if (state->total_param) {
7254 /* Can't use talloc here, the core routines do realloc on the
7255 * params and data. */
7256 state->param = (char *)SMB_MALLOC(state->total_param);
7257 if (state->param == NULL) {
7258 DEBUG(0,("reply_trans: param malloc fail for %u "
7259 "bytes !\n", (unsigned int)state->total_param));
7260 SAFE_FREE(state->data);
7262 reply_nterror(req, NT_STATUS_NO_MEMORY);
7263 END_PROFILE(SMBtrans2);
7266 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7268 if ((smb_base(req->inbuf)+psoff+pscnt
7269 > (char *)req->inbuf + size) ||
7270 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7273 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7276 state->received_data = dscnt;
7277 state->received_param = pscnt;
7279 if ((state->received_param == state->total_param) &&
7280 (state->received_data == state->total_data)) {
7282 handle_trans2(conn, req, state);
7284 SAFE_FREE(state->data);
7285 SAFE_FREE(state->param);
7287 END_PROFILE(SMBtrans2);
7291 DLIST_ADD(conn->pending_trans, state);
7293 /* We need to send an interim response then receive the rest
7294 of the parameter/data bytes */
7295 reply_outbuf(req, 0, 0);
7296 show_msg((char *)req->outbuf);
7297 END_PROFILE(SMBtrans2);
7302 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7303 SAFE_FREE(state->data);
7304 SAFE_FREE(state->param);
7306 END_PROFILE(SMBtrans2);
7307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7311 /****************************************************************************
7312 Reply to a SMBtranss2
7313 ****************************************************************************/
7315 void reply_transs2(connection_struct *conn, struct smb_request *req)
7317 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7318 struct trans_state *state;
7321 START_PROFILE(SMBtranss2);
7323 show_msg((char *)req->inbuf);
7326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7327 END_PROFILE(SMBtranss2);
7331 size = smb_len(req->inbuf)+4;
7333 for (state = conn->pending_trans; state != NULL;
7334 state = state->next) {
7335 if (state->mid == req->mid) {
7340 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7341 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7342 END_PROFILE(SMBtranss2);
7346 /* Revise state->total_param and state->total_data in case they have
7347 changed downwards */
7349 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7350 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7351 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7352 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7354 pcnt = SVAL(req->inbuf, smb_spscnt);
7355 poff = SVAL(req->inbuf, smb_spsoff);
7356 pdisp = SVAL(req->inbuf, smb_spsdisp);
7358 dcnt = SVAL(req->inbuf, smb_sdscnt);
7359 doff = SVAL(req->inbuf, smb_sdsoff);
7360 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7362 state->received_param += pcnt;
7363 state->received_data += dcnt;
7365 if ((state->received_data > state->total_data) ||
7366 (state->received_param > state->total_param))
7370 if (pdisp+pcnt > state->total_param)
7372 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7374 if (pdisp > state->total_param)
7376 if ((smb_base(req->inbuf) + poff + pcnt
7377 > (char *)req->inbuf + size) ||
7378 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7380 if (state->param + pdisp < state->param)
7383 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7388 if (ddisp+dcnt > state->total_data)
7390 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7392 if (ddisp > state->total_data)
7394 if ((smb_base(req->inbuf) + doff + dcnt
7395 > (char *)req->inbuf + size) ||
7396 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7398 if (state->data + ddisp < state->data)
7401 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7405 if ((state->received_param < state->total_param) ||
7406 (state->received_data < state->total_data)) {
7407 END_PROFILE(SMBtranss2);
7412 * construct_reply_common will copy smb_com from inbuf to
7413 * outbuf. SMBtranss2 is wrong here.
7415 SCVAL(req->inbuf,smb_com,SMBtrans2);
7417 handle_trans2(conn, req, state);
7419 DLIST_REMOVE(conn->pending_trans, state);
7420 SAFE_FREE(state->data);
7421 SAFE_FREE(state->param);
7424 END_PROFILE(SMBtranss2);
7429 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7430 DLIST_REMOVE(conn->pending_trans, state);
7431 SAFE_FREE(state->data);
7432 SAFE_FREE(state->param);
7434 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7435 END_PROFILE(SMBtranss2);