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 p += align_string(pdata, p, 0);
1375 len = srvstr_push(base_data, flags2, p,
1376 fname, PTR_DIFF(end_data, p),
1378 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1380 SCVAL(nameptr, -1, len - 2);
1382 SCVAL(nameptr, -1, 0);
1386 SCVAL(nameptr, -1, len - 1);
1388 SCVAL(nameptr, -1, 0);
1394 case SMB_FIND_EA_SIZE:
1395 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1396 if(requires_resume_key) {
1400 srv_put_dos_date2(p,0,create_date);
1401 srv_put_dos_date2(p,4,adate);
1402 srv_put_dos_date2(p,8,mdate);
1403 SIVAL(p,12,(uint32)file_size);
1404 SIVAL(p,16,(uint32)allocation_size);
1407 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1408 SIVAL(p,22,ea_size); /* Extended attributes */
1412 len = srvstr_push(base_data, flags2,
1413 p, fname, PTR_DIFF(end_data, p),
1414 STR_TERMINATE | STR_NOALIGN);
1415 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1428 SCVAL(nameptr,0,len);
1430 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1433 case SMB_FIND_EA_LIST:
1435 struct ea_list *file_list = NULL;
1438 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1442 if(requires_resume_key) {
1446 srv_put_dos_date2(p,0,create_date);
1447 srv_put_dos_date2(p,4,adate);
1448 srv_put_dos_date2(p,8,mdate);
1449 SIVAL(p,12,(uint32)file_size);
1450 SIVAL(p,16,(uint32)allocation_size);
1452 p += 22; /* p now points to the EA area. */
1454 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1455 name_list = ea_list_union(name_list, file_list, &ea_len);
1457 /* We need to determine if this entry will fit in the space available. */
1458 /* Max string size is 255 bytes. */
1459 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1460 /* Move the dirptr back to prev_dirpos */
1461 dptr_SeekDir(conn->dirptr, prev_dirpos);
1462 *out_of_space = True;
1463 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1464 return False; /* Not finished - just out of space */
1467 /* Push the ea_data followed by the name. */
1468 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1470 len = srvstr_push(base_data, flags2,
1471 p + 1, fname, PTR_DIFF(end_data, p+1),
1472 STR_TERMINATE | STR_NOALIGN);
1473 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1486 SCVAL(nameptr,0,len);
1488 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1492 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1493 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1494 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1496 SIVAL(p,0,reskey); p += 4;
1497 put_long_date_timespec(p,create_date_ts); p += 8;
1498 put_long_date_timespec(p,adate_ts); p += 8;
1499 put_long_date_timespec(p,mdate_ts); p += 8;
1500 put_long_date_timespec(p,mdate_ts); p += 8;
1501 SOFF_T(p,0,file_size); p += 8;
1502 SOFF_T(p,0,allocation_size); p += 8;
1503 SIVAL(p,0,nt_extmode); p += 4;
1504 q = p; p += 4; /* q is placeholder for name length. */
1506 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1507 SIVAL(p,0,ea_size); /* Extended attributes */
1510 /* Clear the short name buffer. This is
1511 * IMPORTANT as not doing so will trigger
1512 * a Win2k client bug. JRA.
1514 if (!was_8_3 && check_mangled_names) {
1515 if (!name_to_8_3(fname,mangled_name,True,
1517 /* Error - mangle failed ! */
1518 memset(mangled_name,'\0',12);
1520 mangled_name[12] = 0;
1521 len = srvstr_push(base_data, flags2,
1522 p+2, mangled_name, 24,
1523 STR_UPPER|STR_UNICODE);
1525 memset(p + 2 + len,'\0',24 - len);
1532 len = srvstr_push(base_data, flags2, p,
1533 fname, PTR_DIFF(end_data, p),
1534 STR_TERMINATE_ASCII);
1537 SIVAL(p,0,0); /* Ensure any padding is null. */
1538 len = PTR_DIFF(p, pdata);
1539 len = (len + 3) & ~3;
1544 case SMB_FIND_FILE_DIRECTORY_INFO:
1545 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1547 SIVAL(p,0,reskey); p += 4;
1548 put_long_date_timespec(p,create_date_ts); p += 8;
1549 put_long_date_timespec(p,adate_ts); p += 8;
1550 put_long_date_timespec(p,mdate_ts); p += 8;
1551 put_long_date_timespec(p,mdate_ts); p += 8;
1552 SOFF_T(p,0,file_size); p += 8;
1553 SOFF_T(p,0,allocation_size); p += 8;
1554 SIVAL(p,0,nt_extmode); p += 4;
1555 len = srvstr_push(base_data, flags2,
1556 p + 4, fname, PTR_DIFF(end_data, p+4),
1557 STR_TERMINATE_ASCII);
1560 SIVAL(p,0,0); /* Ensure any padding is null. */
1561 len = PTR_DIFF(p, pdata);
1562 len = (len + 3) & ~3;
1567 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1568 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1570 SIVAL(p,0,reskey); p += 4;
1571 put_long_date_timespec(p,create_date_ts); p += 8;
1572 put_long_date_timespec(p,adate_ts); p += 8;
1573 put_long_date_timespec(p,mdate_ts); p += 8;
1574 put_long_date_timespec(p,mdate_ts); p += 8;
1575 SOFF_T(p,0,file_size); p += 8;
1576 SOFF_T(p,0,allocation_size); p += 8;
1577 SIVAL(p,0,nt_extmode); p += 4;
1578 q = p; p += 4; /* q is placeholder for name length. */
1580 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1581 SIVAL(p,0,ea_size); /* Extended attributes */
1584 len = srvstr_push(base_data, flags2, p,
1585 fname, PTR_DIFF(end_data, p),
1586 STR_TERMINATE_ASCII);
1590 SIVAL(p,0,0); /* Ensure any padding is null. */
1591 len = PTR_DIFF(p, pdata);
1592 len = (len + 3) & ~3;
1597 case SMB_FIND_FILE_NAMES_INFO:
1598 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1600 SIVAL(p,0,reskey); p += 4;
1602 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1603 acl on a dir (tridge) */
1604 len = srvstr_push(base_data, flags2, p,
1605 fname, PTR_DIFF(end_data, p),
1606 STR_TERMINATE_ASCII);
1609 SIVAL(p,0,0); /* Ensure any padding is null. */
1610 len = PTR_DIFF(p, pdata);
1611 len = (len + 3) & ~3;
1616 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1617 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1619 SIVAL(p,0,reskey); p += 4;
1620 put_long_date_timespec(p,create_date_ts); p += 8;
1621 put_long_date_timespec(p,adate_ts); p += 8;
1622 put_long_date_timespec(p,mdate_ts); p += 8;
1623 put_long_date_timespec(p,mdate_ts); p += 8;
1624 SOFF_T(p,0,file_size); p += 8;
1625 SOFF_T(p,0,allocation_size); p += 8;
1626 SIVAL(p,0,nt_extmode); p += 4;
1627 q = p; p += 4; /* q is placeholder for name length. */
1629 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1630 SIVAL(p,0,ea_size); /* Extended attributes */
1633 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1634 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1635 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1636 len = srvstr_push(base_data, flags2, p,
1637 fname, PTR_DIFF(end_data, p),
1638 STR_TERMINATE_ASCII);
1641 SIVAL(p,0,0); /* Ensure any padding is null. */
1642 len = PTR_DIFF(p, pdata);
1643 len = (len + 3) & ~3;
1648 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1649 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1650 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1652 SIVAL(p,0,reskey); p += 4;
1653 put_long_date_timespec(p,create_date_ts); p += 8;
1654 put_long_date_timespec(p,adate_ts); p += 8;
1655 put_long_date_timespec(p,mdate_ts); p += 8;
1656 put_long_date_timespec(p,mdate_ts); p += 8;
1657 SOFF_T(p,0,file_size); p += 8;
1658 SOFF_T(p,0,allocation_size); p += 8;
1659 SIVAL(p,0,nt_extmode); p += 4;
1660 q = p; p += 4; /* q is placeholder for name length */
1662 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1663 SIVAL(p,0,ea_size); /* Extended attributes */
1666 /* Clear the short name buffer. This is
1667 * IMPORTANT as not doing so will trigger
1668 * a Win2k client bug. JRA.
1670 if (!was_8_3 && check_mangled_names) {
1671 if (!name_to_8_3(fname,mangled_name,True,
1673 /* Error - mangle failed ! */
1674 memset(mangled_name,'\0',12);
1676 mangled_name[12] = 0;
1677 len = srvstr_push(base_data, flags2,
1678 p+2, mangled_name, 24,
1679 STR_UPPER|STR_UNICODE);
1682 memset(p + 2 + len,'\0',24 - len);
1689 SSVAL(p,0,0); p += 2; /* Reserved ? */
1690 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1691 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1692 len = srvstr_push(base_data, flags2, p,
1693 fname, PTR_DIFF(end_data, p),
1694 STR_TERMINATE_ASCII);
1697 SIVAL(p,0,0); /* Ensure any padding is null. */
1698 len = PTR_DIFF(p, pdata);
1699 len = (len + 3) & ~3;
1704 /* CIFS UNIX Extension. */
1706 case SMB_FIND_FILE_UNIX:
1707 case SMB_FIND_FILE_UNIX_INFO2:
1709 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1711 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1713 if (info_level == SMB_FIND_FILE_UNIX) {
1714 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1715 p = store_file_unix_basic(conn, p,
1717 len = srvstr_push(base_data, flags2, p,
1718 fname, PTR_DIFF(end_data, p),
1721 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1722 p = store_file_unix_basic_info2(conn, p,
1726 len = srvstr_push(base_data, flags2, p, fname,
1727 PTR_DIFF(end_data, p), 0);
1728 SIVAL(nameptr, 0, len);
1732 SIVAL(p,0,0); /* Ensure any padding is null. */
1734 len = PTR_DIFF(p, pdata);
1735 len = (len + 3) & ~3;
1736 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1738 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1747 if (PTR_DIFF(p,pdata) > space_remaining) {
1748 /* Move the dirptr back to prev_dirpos */
1749 dptr_SeekDir(conn->dirptr, prev_dirpos);
1750 *out_of_space = True;
1751 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1752 return False; /* Not finished - just out of space */
1755 /* Setup the last entry pointer, as an offset from base_data */
1756 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1757 /* Advance the data pointer to the next slot */
1763 /****************************************************************************
1764 Reply to a TRANS2_FINDFIRST.
1765 ****************************************************************************/
1767 static void call_trans2findfirst(connection_struct *conn,
1768 struct smb_request *req,
1769 char **pparams, int total_params,
1770 char **ppdata, int total_data,
1771 unsigned int max_data_bytes)
1773 /* We must be careful here that we don't return more than the
1774 allowed number of data bytes. If this means returning fewer than
1775 maxentries then so be it. We assume that the redirector has
1776 enough room for the fixed number of parameter bytes it has
1778 char *params = *pparams;
1779 char *pdata = *ppdata;
1783 uint16 findfirst_flags;
1784 bool close_after_first;
1786 bool requires_resume_key;
1788 char *directory = NULL;
1789 const char *mask = NULL;
1791 int last_entry_off=0;
1795 bool finished = False;
1796 bool dont_descend = False;
1797 bool out_of_space = False;
1798 int space_remaining;
1799 bool mask_contains_wcard = False;
1800 SMB_STRUCT_STAT sbuf;
1801 struct ea_list *ea_list = NULL;
1802 NTSTATUS ntstatus = NT_STATUS_OK;
1803 TALLOC_CTX *ctx = talloc_tos();
1805 if (total_params < 13) {
1806 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1810 dirtype = SVAL(params,0);
1811 maxentries = SVAL(params,2);
1812 findfirst_flags = SVAL(params,4);
1813 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1814 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1815 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1816 info_level = SVAL(params,6);
1818 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1819 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1820 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1821 info_level, max_data_bytes));
1824 /* W2K3 seems to treat zero as 1. */
1828 switch (info_level) {
1829 case SMB_FIND_INFO_STANDARD:
1830 case SMB_FIND_EA_SIZE:
1831 case SMB_FIND_EA_LIST:
1832 case SMB_FIND_FILE_DIRECTORY_INFO:
1833 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1834 case SMB_FIND_FILE_NAMES_INFO:
1835 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1836 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1837 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1839 case SMB_FIND_FILE_UNIX:
1840 case SMB_FIND_FILE_UNIX_INFO2:
1841 if (!lp_unix_extensions()) {
1842 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1847 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1851 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1852 params+12, total_params - 12,
1853 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1854 if (!NT_STATUS_IS_OK(ntstatus)) {
1855 reply_nterror(req, ntstatus);
1859 ntstatus = resolve_dfspath_wcard(ctx, conn,
1860 req->flags2 & FLAGS2_DFS_PATHNAMES,
1863 &mask_contains_wcard);
1864 if (!NT_STATUS_IS_OK(ntstatus)) {
1865 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1866 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1867 ERRSRV, ERRbadpath);
1870 reply_nterror(req, ntstatus);
1874 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1875 if (!NT_STATUS_IS_OK(ntstatus)) {
1876 reply_nterror(req, ntstatus);
1880 ntstatus = check_name(conn, directory);
1881 if (!NT_STATUS_IS_OK(ntstatus)) {
1882 reply_nterror(req, ntstatus);
1886 p = strrchr_m(directory,'/');
1888 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1889 if((directory[0] == '.') && (directory[1] == '\0')) {
1891 mask_contains_wcard = True;
1895 directory = talloc_strdup(talloc_tos(), "./");
1897 reply_nterror(req, NT_STATUS_NO_MEMORY);
1905 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1907 if (info_level == SMB_FIND_EA_LIST) {
1910 if (total_data < 4) {
1911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1915 ea_size = IVAL(pdata,0);
1916 if (ea_size != total_data) {
1917 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1918 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1919 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1923 if (!lp_ea_support(SNUM(conn))) {
1924 reply_doserror(req, ERRDOS, ERReasnotsupported);
1928 /* Pull out the list of names. */
1929 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1931 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1936 *ppdata = (char *)SMB_REALLOC(
1937 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1938 if(*ppdata == NULL ) {
1939 reply_nterror(req, NT_STATUS_NO_MEMORY);
1943 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1945 /* Realloc the params space */
1946 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1947 if (*pparams == NULL) {
1948 reply_nterror(req, NT_STATUS_NO_MEMORY);
1953 /* Save the wildcard match and attribs we are using on this directory -
1954 needed as lanman2 assumes these are being saved between calls */
1956 ntstatus = dptr_create(conn,
1962 mask_contains_wcard,
1966 if (!NT_STATUS_IS_OK(ntstatus)) {
1967 reply_nterror(req, ntstatus);
1971 dptr_num = dptr_dnum(conn->dirptr);
1972 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1974 /* We don't need to check for VOL here as this is returned by
1975 a different TRANS2 call. */
1977 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1978 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1979 dont_descend = True;
1982 space_remaining = max_data_bytes;
1983 out_of_space = False;
1985 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1986 bool got_exact_match = False;
1988 /* this is a heuristic to avoid seeking the dirptr except when
1989 absolutely necessary. It allows for a filename of about 40 chars */
1990 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1991 out_of_space = True;
1994 TALLOC_CTX *sub_ctx = talloc_stackframe();
1996 finished = !get_lanman2_dir_entry(sub_ctx,
1999 mask,dirtype,info_level,
2000 requires_resume_key,dont_descend,
2002 space_remaining, &out_of_space,
2004 &last_entry_off, ea_list);
2006 TALLOC_FREE(sub_ctx);
2009 if (finished && out_of_space)
2012 if (!finished && !out_of_space)
2016 * As an optimisation if we know we aren't looking
2017 * for a wildcard name (ie. the name matches the wildcard exactly)
2018 * then we can finish on any (first) match.
2019 * This speeds up large directory searches. JRA.
2025 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2028 /* Check if we can close the dirptr */
2029 if(close_after_first || (finished && close_if_end)) {
2030 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2031 dptr_close(&dptr_num);
2035 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2036 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2037 * the protocol level is less than NT1. Tested with smbclient. JRA.
2038 * This should fix the OS/2 client bug #2335.
2041 if(numentries == 0) {
2042 dptr_close(&dptr_num);
2043 if (Protocol < PROTOCOL_NT1) {
2044 reply_doserror(req, ERRDOS, ERRnofiles);
2047 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2048 ERRDOS, ERRbadfile);
2053 /* At this point pdata points to numentries directory entries. */
2055 /* Set up the return parameter block */
2056 SSVAL(params,0,dptr_num);
2057 SSVAL(params,2,numentries);
2058 SSVAL(params,4,finished);
2059 SSVAL(params,6,0); /* Never an EA error */
2060 SSVAL(params,8,last_entry_off);
2062 send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
2065 if ((! *directory) && dptr_path(dptr_num)) {
2066 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2068 reply_nterror(req, NT_STATUS_NO_MEMORY);
2072 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2073 smb_fn_name(CVAL(req->inbuf,smb_com)),
2074 mask, directory, dirtype, numentries ) );
2077 * Force a name mangle here to ensure that the
2078 * mask as an 8.3 name is top of the mangled cache.
2079 * The reasons for this are subtle. Don't remove
2080 * this code unless you know what you are doing
2081 * (see PR#13758). JRA.
2084 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2085 char mangled_name[13];
2086 name_to_8_3(mask, mangled_name, True, conn->params);
2092 /****************************************************************************
2093 Reply to a TRANS2_FINDNEXT.
2094 ****************************************************************************/
2096 static void call_trans2findnext(connection_struct *conn,
2097 struct smb_request *req,
2098 char **pparams, int total_params,
2099 char **ppdata, int total_data,
2100 unsigned int max_data_bytes)
2102 /* We must be careful here that we don't return more than the
2103 allowed number of data bytes. If this means returning fewer than
2104 maxentries then so be it. We assume that the redirector has
2105 enough room for the fixed number of parameter bytes it has
2107 char *params = *pparams;
2108 char *pdata = *ppdata;
2114 uint16 findnext_flags;
2115 bool close_after_request;
2117 bool requires_resume_key;
2119 bool mask_contains_wcard = False;
2120 char *resume_name = NULL;
2121 const char *mask = NULL;
2122 const char *directory = NULL;
2126 int i, last_entry_off=0;
2127 bool finished = False;
2128 bool dont_descend = False;
2129 bool out_of_space = False;
2130 int space_remaining;
2131 struct ea_list *ea_list = NULL;
2132 NTSTATUS ntstatus = NT_STATUS_OK;
2133 TALLOC_CTX *ctx = talloc_tos();
2135 if (total_params < 13) {
2136 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2140 dptr_num = SVAL(params,0);
2141 maxentries = SVAL(params,2);
2142 info_level = SVAL(params,4);
2143 resume_key = IVAL(params,6);
2144 findnext_flags = SVAL(params,10);
2145 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2146 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2147 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2148 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2150 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2152 total_params - 12, STR_TERMINATE, &ntstatus,
2153 &mask_contains_wcard);
2154 if (!NT_STATUS_IS_OK(ntstatus)) {
2155 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2156 complain (it thinks we're asking for the directory above the shared
2157 path or an invalid name). Catch this as the resume name is only compared, never used in
2158 a file access. JRA. */
2159 srvstr_pull_talloc(ctx, params, req->flags2,
2160 &resume_name, params+12,
2164 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2165 reply_nterror(req, ntstatus);
2170 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2171 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2172 resume_key = %d resume name = %s continue=%d level = %d\n",
2173 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2174 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2177 /* W2K3 seems to treat zero as 1. */
2181 switch (info_level) {
2182 case SMB_FIND_INFO_STANDARD:
2183 case SMB_FIND_EA_SIZE:
2184 case SMB_FIND_EA_LIST:
2185 case SMB_FIND_FILE_DIRECTORY_INFO:
2186 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2187 case SMB_FIND_FILE_NAMES_INFO:
2188 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2189 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2190 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2192 case SMB_FIND_FILE_UNIX:
2193 case SMB_FIND_FILE_UNIX_INFO2:
2194 if (!lp_unix_extensions()) {
2195 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2200 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2204 if (info_level == SMB_FIND_EA_LIST) {
2207 if (total_data < 4) {
2208 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2212 ea_size = IVAL(pdata,0);
2213 if (ea_size != total_data) {
2214 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2215 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2216 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2220 if (!lp_ea_support(SNUM(conn))) {
2221 reply_doserror(req, ERRDOS, ERReasnotsupported);
2225 /* Pull out the list of names. */
2226 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2228 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2233 *ppdata = (char *)SMB_REALLOC(
2234 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2235 if(*ppdata == NULL) {
2236 reply_nterror(req, NT_STATUS_NO_MEMORY);
2241 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2243 /* Realloc the params space */
2244 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2245 if(*pparams == NULL ) {
2246 reply_nterror(req, NT_STATUS_NO_MEMORY);
2252 /* Check that the dptr is valid */
2253 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2254 reply_doserror(req, ERRDOS, ERRnofiles);
2258 string_set(&conn->dirpath,dptr_path(dptr_num));
2260 /* Get the wildcard mask from the dptr */
2261 if((p = dptr_wcard(dptr_num))== NULL) {
2262 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2263 reply_doserror(req, ERRDOS, ERRnofiles);
2268 directory = conn->dirpath;
2270 /* Get the attr mask from the dptr */
2271 dirtype = dptr_attr(dptr_num);
2273 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2274 dptr_num, mask, dirtype,
2276 dptr_TellDir(conn->dirptr)));
2278 /* We don't need to check for VOL here as this is returned by
2279 a different TRANS2 call. */
2281 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2282 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2283 dont_descend = True;
2286 space_remaining = max_data_bytes;
2287 out_of_space = False;
2290 * Seek to the correct position. We no longer use the resume key but
2291 * depend on the last file name instead.
2294 if(*resume_name && !continue_bit) {
2297 long current_pos = 0;
2299 * Remember, name_to_8_3 is called by
2300 * get_lanman2_dir_entry(), so the resume name
2301 * could be mangled. Ensure we check the unmangled name.
2304 if (mangle_is_mangled(resume_name, conn->params)) {
2305 char *new_resume_name = NULL;
2306 mangle_lookup_name_from_8_3(ctx,
2310 if (new_resume_name) {
2311 resume_name = new_resume_name;
2316 * Fix for NT redirector problem triggered by resume key indexes
2317 * changing between directory scans. We now return a resume key of 0
2318 * and instead look for the filename to continue from (also given
2319 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2320 * findfirst/findnext (as is usual) then the directory pointer
2321 * should already be at the correct place.
2324 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2325 } /* end if resume_name && !continue_bit */
2327 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2328 bool got_exact_match = False;
2330 /* this is a heuristic to avoid seeking the dirptr except when
2331 absolutely necessary. It allows for a filename of about 40 chars */
2332 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2333 out_of_space = True;
2336 TALLOC_CTX *sub_ctx = talloc_stackframe();
2338 finished = !get_lanman2_dir_entry(sub_ctx,
2341 mask,dirtype,info_level,
2342 requires_resume_key,dont_descend,
2344 space_remaining, &out_of_space,
2346 &last_entry_off, ea_list);
2348 TALLOC_FREE(sub_ctx);
2351 if (finished && out_of_space)
2354 if (!finished && !out_of_space)
2358 * As an optimisation if we know we aren't looking
2359 * for a wildcard name (ie. the name matches the wildcard exactly)
2360 * then we can finish on any (first) match.
2361 * This speeds up large directory searches. JRA.
2367 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2370 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2371 smb_fn_name(CVAL(req->inbuf,smb_com)),
2372 mask, directory, dirtype, numentries ) );
2374 /* Check if we can close the dirptr */
2375 if(close_after_request || (finished && close_if_end)) {
2376 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2377 dptr_close(&dptr_num); /* This frees up the saved mask */
2380 /* Set up the return parameter block */
2381 SSVAL(params,0,numentries);
2382 SSVAL(params,2,finished);
2383 SSVAL(params,4,0); /* Never an EA error */
2384 SSVAL(params,6,last_entry_off);
2386 send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata),
2392 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2394 E_md4hash(lp_servicename(SNUM(conn)),objid);
2398 /****************************************************************************
2399 Reply to a TRANS2_QFSINFO (query filesystem info).
2400 ****************************************************************************/
2402 static void call_trans2qfsinfo(connection_struct *conn,
2403 struct smb_request *req,
2404 char **pparams, int total_params,
2405 char **ppdata, int total_data,
2406 unsigned int max_data_bytes)
2408 char *pdata, *end_data;
2409 char *params = *pparams;
2413 const char *vname = volume_label(SNUM(conn));
2414 int snum = SNUM(conn);
2415 char *fstype = lp_fstype(SNUM(conn));
2418 if (total_params < 2) {
2419 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2423 info_level = SVAL(params,0);
2425 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2427 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2428 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2429 reply_doserror(req, ERRSRV, ERRinvdevice);
2433 *ppdata = (char *)SMB_REALLOC(
2434 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2435 if (*ppdata == NULL ) {
2436 reply_nterror(req, NT_STATUS_NO_MEMORY);
2441 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2442 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2444 switch (info_level) {
2445 case SMB_INFO_ALLOCATION:
2447 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2449 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2450 reply_unixerror(req, ERRHRD, ERRgeneral);
2454 block_size = lp_block_size(snum);
2455 if (bsize < block_size) {
2456 SMB_BIG_UINT factor = block_size/bsize;
2461 if (bsize > block_size) {
2462 SMB_BIG_UINT factor = bsize/block_size;
2467 bytes_per_sector = 512;
2468 sectors_per_unit = bsize/bytes_per_sector;
2470 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2471 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2472 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2474 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2475 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2476 SIVAL(pdata,l1_cUnit,dsize);
2477 SIVAL(pdata,l1_cUnitAvail,dfree);
2478 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2482 case SMB_INFO_VOLUME:
2483 /* Return volume name */
2485 * Add volume serial number - hash of a combination of
2486 * the called hostname and the service name.
2488 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2490 * Win2k3 and previous mess this up by sending a name length
2491 * one byte short. I believe only older clients (OS/2 Win9x) use
2492 * this call so try fixing this by adding a terminating null to
2493 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2497 pdata+l2_vol_szVolLabel, vname,
2498 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2499 STR_NOALIGN|STR_TERMINATE);
2500 SCVAL(pdata,l2_vol_cch,len);
2501 data_len = l2_vol_szVolLabel + len;
2502 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2503 (unsigned)st.st_ctime, len, vname));
2506 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2507 case SMB_FS_ATTRIBUTE_INFORMATION:
2510 #if defined(HAVE_SYS_QUOTAS)
2511 quota_flag = FILE_VOLUME_QUOTAS;
2514 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2515 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2516 FILE_SUPPORTS_OBJECT_IDS|
2517 FILE_UNICODE_ON_DISK|
2518 quota_flag); /* FS ATTRIBUTES */
2520 SIVAL(pdata,4,255); /* Max filename component length */
2521 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2522 and will think we can't do long filenames */
2523 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2524 PTR_DIFF(end_data, pdata+12),
2527 data_len = 12 + len;
2530 case SMB_QUERY_FS_LABEL_INFO:
2531 case SMB_FS_LABEL_INFORMATION:
2532 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2533 PTR_DIFF(end_data, pdata+4), 0);
2538 case SMB_QUERY_FS_VOLUME_INFO:
2539 case SMB_FS_VOLUME_INFORMATION:
2542 * Add volume serial number - hash of a combination of
2543 * the called hostname and the service name.
2545 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2546 (str_checksum(get_local_machine_name())<<16));
2548 /* Max label len is 32 characters. */
2549 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2550 PTR_DIFF(end_data, pdata+18),
2552 SIVAL(pdata,12,len);
2555 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2556 (int)strlen(vname),vname, lp_servicename(snum)));
2559 case SMB_QUERY_FS_SIZE_INFO:
2560 case SMB_FS_SIZE_INFORMATION:
2562 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2564 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2565 reply_unixerror(req, ERRHRD, ERRgeneral);
2568 block_size = lp_block_size(snum);
2569 if (bsize < block_size) {
2570 SMB_BIG_UINT factor = block_size/bsize;
2575 if (bsize > block_size) {
2576 SMB_BIG_UINT factor = bsize/block_size;
2581 bytes_per_sector = 512;
2582 sectors_per_unit = bsize/bytes_per_sector;
2583 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2584 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2585 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2586 SBIG_UINT(pdata,0,dsize);
2587 SBIG_UINT(pdata,8,dfree);
2588 SIVAL(pdata,16,sectors_per_unit);
2589 SIVAL(pdata,20,bytes_per_sector);
2593 case SMB_FS_FULL_SIZE_INFORMATION:
2595 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2597 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2598 reply_unixerror(req, ERRHRD, ERRgeneral);
2601 block_size = lp_block_size(snum);
2602 if (bsize < block_size) {
2603 SMB_BIG_UINT factor = block_size/bsize;
2608 if (bsize > block_size) {
2609 SMB_BIG_UINT factor = bsize/block_size;
2614 bytes_per_sector = 512;
2615 sectors_per_unit = bsize/bytes_per_sector;
2616 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2617 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2618 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2619 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2620 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2621 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2622 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2623 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2627 case SMB_QUERY_FS_DEVICE_INFO:
2628 case SMB_FS_DEVICE_INFORMATION:
2630 SIVAL(pdata,0,0); /* dev type */
2631 SIVAL(pdata,4,0); /* characteristics */
2634 #ifdef HAVE_SYS_QUOTAS
2635 case SMB_FS_QUOTA_INFORMATION:
2637 * what we have to send --metze:
2639 * Unknown1: 24 NULL bytes
2640 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2641 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2642 * Quota Flags: 2 byte :
2643 * Unknown3: 6 NULL bytes
2647 * details for Quota Flags:
2649 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2650 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2651 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2652 * 0x0001 Enable Quotas: enable quota for this fs
2656 /* we need to fake up a fsp here,
2657 * because its not send in this call
2660 SMB_NTQUOTA_STRUCT quotas;
2663 ZERO_STRUCT(quotas);
2669 if (current_user.ut.uid != 0) {
2670 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2671 lp_servicename(SNUM(conn)),conn->user));
2672 reply_doserror(req, ERRDOS, ERRnoaccess);
2676 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2677 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2678 reply_doserror(req, ERRSRV, ERRerror);
2684 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2686 /* Unknown1 24 NULL bytes*/
2687 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2688 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2689 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2691 /* Default Soft Quota 8 bytes */
2692 SBIG_UINT(pdata,24,quotas.softlim);
2694 /* Default Hard Quota 8 bytes */
2695 SBIG_UINT(pdata,32,quotas.hardlim);
2697 /* Quota flag 2 bytes */
2698 SSVAL(pdata,40,quotas.qflags);
2700 /* Unknown3 6 NULL bytes */
2706 #endif /* HAVE_SYS_QUOTAS */
2707 case SMB_FS_OBJECTID_INFORMATION:
2709 unsigned char objid[16];
2710 memcpy(pdata,create_volume_objectid(conn, objid),16);
2716 * Query the version and capabilities of the CIFS UNIX extensions
2720 case SMB_QUERY_CIFS_UNIX_INFO:
2722 bool large_write = lp_min_receive_file_size() &&
2723 !srv_is_signing_active();
2725 if (!lp_unix_extensions()) {
2726 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2730 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2731 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2732 /* We have POSIX ACLs, pathname and locking capability. */
2733 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2734 CIFS_UNIX_POSIX_ACLS_CAP|
2735 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2736 CIFS_UNIX_FCNTL_LOCKS_CAP|
2737 CIFS_UNIX_EXTATTR_CAP|
2738 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2739 CIFS_UNIX_LARGE_READ_CAP|
2741 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2745 case SMB_QUERY_POSIX_FS_INFO:
2748 vfs_statvfs_struct svfs;
2750 if (!lp_unix_extensions()) {
2751 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2755 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2759 SIVAL(pdata,0,svfs.OptimalTransferSize);
2760 SIVAL(pdata,4,svfs.BlockSize);
2761 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2762 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2763 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2764 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2765 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2766 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2767 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2769 } else if (rc == EOPNOTSUPP) {
2770 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2772 #endif /* EOPNOTSUPP */
2774 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2775 reply_doserror(req, ERRSRV, ERRerror);
2781 case SMB_QUERY_POSIX_WHOAMI:
2787 if (!lp_unix_extensions()) {
2788 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2792 if (max_data_bytes < 40) {
2793 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2797 /* We ARE guest if global_sid_Builtin_Guests is
2798 * in our list of SIDs.
2800 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2801 current_user.nt_user_token)) {
2802 flags |= SMB_WHOAMI_GUEST;
2805 /* We are NOT guest if global_sid_Authenticated_Users
2806 * is in our list of SIDs.
2808 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2809 current_user.nt_user_token)) {
2810 flags &= ~SMB_WHOAMI_GUEST;
2813 /* NOTE: 8 bytes for UID/GID, irrespective of native
2814 * platform size. This matches
2815 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2817 data_len = 4 /* flags */
2824 + 4 /* pad/reserved */
2825 + (current_user.ut.ngroups * 8)
2827 + (current_user.nt_user_token->num_sids *
2831 SIVAL(pdata, 0, flags);
2832 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2833 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2834 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2837 if (data_len >= max_data_bytes) {
2838 /* Potential overflow, skip the GIDs and SIDs. */
2840 SIVAL(pdata, 24, 0); /* num_groups */
2841 SIVAL(pdata, 28, 0); /* num_sids */
2842 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2843 SIVAL(pdata, 36, 0); /* reserved */
2849 SIVAL(pdata, 24, current_user.ut.ngroups);
2851 current_user.nt_user_token->num_sids);
2853 /* We walk the SID list twice, but this call is fairly
2854 * infrequent, and I don't expect that it's performance
2855 * sensitive -- jpeach
2857 for (i = 0, sid_bytes = 0;
2858 i < current_user.nt_user_token->num_sids; ++i) {
2860 sid_size(¤t_user.nt_user_token->user_sids[i]);
2863 /* SID list byte count */
2864 SIVAL(pdata, 32, sid_bytes);
2866 /* 4 bytes pad/reserved - must be zero */
2867 SIVAL(pdata, 36, 0);
2871 for (i = 0; i < current_user.ut.ngroups; ++i) {
2872 SBIG_UINT(pdata, data_len,
2873 (SMB_BIG_UINT)current_user.ut.groups[i]);
2879 i < current_user.nt_user_token->num_sids; ++i) {
2881 sid_size(¤t_user.nt_user_token->user_sids[i]);
2883 sid_linearize(pdata + data_len, sid_len,
2884 ¤t_user.nt_user_token->user_sids[i]);
2885 data_len += sid_len;
2891 case SMB_MAC_QUERY_FS_INFO:
2893 * Thursby MAC extension... ONLY on NTFS filesystems
2894 * once we do streams then we don't need this
2896 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2898 SIVAL(pdata,84,0x100); /* Don't support mac... */
2903 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2908 send_trans2_replies(req, params, 0, pdata, data_len,
2911 DEBUG( 4, ( "%s info_level = %d\n",
2912 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2917 /****************************************************************************
2918 Reply to a TRANS2_SETFSINFO (set filesystem info).
2919 ****************************************************************************/
2921 static void call_trans2setfsinfo(connection_struct *conn,
2922 struct smb_request *req,
2923 char **pparams, int total_params,
2924 char **ppdata, int total_data,
2925 unsigned int max_data_bytes)
2927 char *pdata = *ppdata;
2928 char *params = *pparams;
2931 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2934 if (total_params < 4) {
2935 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2937 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2941 info_level = SVAL(params,2);
2943 switch(info_level) {
2944 case SMB_SET_CIFS_UNIX_INFO:
2946 uint16 client_unix_major;
2947 uint16 client_unix_minor;
2948 uint32 client_unix_cap_low;
2949 uint32 client_unix_cap_high;
2951 if (!lp_unix_extensions()) {
2953 NT_STATUS_INVALID_LEVEL);
2957 /* There should be 12 bytes of capabilities set. */
2958 if (total_data < 8) {
2961 NT_STATUS_INVALID_PARAMETER);
2964 client_unix_major = SVAL(pdata,0);
2965 client_unix_minor = SVAL(pdata,2);
2966 client_unix_cap_low = IVAL(pdata,4);
2967 client_unix_cap_high = IVAL(pdata,8);
2968 /* Just print these values for now. */
2969 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2970 cap_low = 0x%x, cap_high = 0x%x\n",
2971 (unsigned int)client_unix_major,
2972 (unsigned int)client_unix_minor,
2973 (unsigned int)client_unix_cap_low,
2974 (unsigned int)client_unix_cap_high ));
2976 /* Here is where we must switch to posix pathname processing... */
2977 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2978 lp_set_posix_pathnames();
2979 mangle_change_to_posix();
2982 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2983 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2984 /* Client that knows how to do posix locks,
2985 * but not posix open/mkdir operations. Set a
2986 * default type for read/write checks. */
2988 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2993 case SMB_FS_QUOTA_INFORMATION:
2995 files_struct *fsp = NULL;
2996 SMB_NTQUOTA_STRUCT quotas;
2998 ZERO_STRUCT(quotas);
3001 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3002 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3003 lp_servicename(SNUM(conn)),conn->user));
3004 reply_doserror(req, ERRSRV, ERRaccess);
3008 /* note: normaly there're 48 bytes,
3009 * but we didn't use the last 6 bytes for now
3012 fsp = file_fsp(SVAL(params,0));
3013 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3014 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3016 req, NT_STATUS_INVALID_HANDLE);
3020 if (total_data < 42) {
3021 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3025 NT_STATUS_INVALID_PARAMETER);
3029 /* unknown_1 24 NULL bytes in pdata*/
3031 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3032 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3033 #ifdef LARGE_SMB_OFF_T
3034 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3035 #else /* LARGE_SMB_OFF_T */
3036 if ((IVAL(pdata,28) != 0)&&
3037 ((quotas.softlim != 0xFFFFFFFF)||
3038 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3039 /* more than 32 bits? */
3042 NT_STATUS_INVALID_PARAMETER);
3045 #endif /* LARGE_SMB_OFF_T */
3047 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3048 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3049 #ifdef LARGE_SMB_OFF_T
3050 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3051 #else /* LARGE_SMB_OFF_T */
3052 if ((IVAL(pdata,36) != 0)&&
3053 ((quotas.hardlim != 0xFFFFFFFF)||
3054 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3055 /* more than 32 bits? */
3058 NT_STATUS_INVALID_PARAMETER);
3061 #endif /* LARGE_SMB_OFF_T */
3063 /* quota_flags 2 bytes **/
3064 quotas.qflags = SVAL(pdata,40);
3066 /* unknown_2 6 NULL bytes follow*/
3068 /* now set the quotas */
3069 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3070 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3071 reply_doserror(req, ERRSRV, ERRerror);
3078 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3080 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3086 * sending this reply works fine,
3087 * but I'm not sure it's the same
3088 * like windows do...
3091 reply_outbuf(req, 10, 0);
3094 #if defined(HAVE_POSIX_ACLS)
3095 /****************************************************************************
3096 Utility function to count the number of entries in a POSIX acl.
3097 ****************************************************************************/
3099 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3101 unsigned int ace_count = 0;
3102 int entry_id = SMB_ACL_FIRST_ENTRY;
3103 SMB_ACL_ENTRY_T entry;
3105 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3107 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3108 entry_id = SMB_ACL_NEXT_ENTRY;
3115 /****************************************************************************
3116 Utility function to marshall a POSIX acl into wire format.
3117 ****************************************************************************/
3119 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3121 int entry_id = SMB_ACL_FIRST_ENTRY;
3122 SMB_ACL_ENTRY_T entry;
3124 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3125 SMB_ACL_TAG_T tagtype;
3126 SMB_ACL_PERMSET_T permset;
3127 unsigned char perms = 0;
3128 unsigned int own_grp;
3131 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3132 entry_id = SMB_ACL_NEXT_ENTRY;
3135 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3136 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3140 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3141 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3145 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3146 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3147 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3149 SCVAL(pdata,1,perms);
3152 case SMB_ACL_USER_OBJ:
3153 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3154 own_grp = (unsigned int)pst->st_uid;
3155 SIVAL(pdata,2,own_grp);
3160 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3162 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3165 own_grp = (unsigned int)*puid;
3166 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3167 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3168 SIVAL(pdata,2,own_grp);
3172 case SMB_ACL_GROUP_OBJ:
3173 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3174 own_grp = (unsigned int)pst->st_gid;
3175 SIVAL(pdata,2,own_grp);
3180 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3182 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3185 own_grp = (unsigned int)*pgid;
3186 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3187 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3188 SIVAL(pdata,2,own_grp);
3193 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3194 SIVAL(pdata,2,0xFFFFFFFF);
3195 SIVAL(pdata,6,0xFFFFFFFF);
3198 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3199 SIVAL(pdata,2,0xFFFFFFFF);
3200 SIVAL(pdata,6,0xFFFFFFFF);
3203 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3206 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3213 /****************************************************************************
3214 Store the FILE_UNIX_BASIC info.
3215 ****************************************************************************/
3217 static char *store_file_unix_basic(connection_struct *conn,
3220 const SMB_STRUCT_STAT *psbuf)
3222 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3223 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3225 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3228 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3231 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3232 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3233 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3236 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3240 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3244 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3247 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3251 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3255 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3258 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3262 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3269 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3270 * the chflags(2) (or equivalent) flags.
3272 * XXX: this really should be behind the VFS interface. To do this, we would
3273 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3274 * Each VFS module could then implement it's own mapping as appropriate for the
3275 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3277 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3281 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3285 { UF_IMMUTABLE, EXT_IMMUTABLE },
3289 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3293 { UF_HIDDEN, EXT_HIDDEN },
3296 /* Do not remove. We need to guarantee that this array has at least one
3297 * entry to build on HP-UX.
3303 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3304 uint32 *smb_fflags, uint32 *smb_fmask)
3306 #ifdef HAVE_STAT_ST_FLAGS
3309 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3310 *smb_fmask |= info2_flags_map[i].smb_fflag;
3311 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3312 *smb_fflags |= info2_flags_map[i].smb_fflag;
3315 #endif /* HAVE_STAT_ST_FLAGS */
3318 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3319 const uint32 smb_fflags,
3320 const uint32 smb_fmask,
3323 #ifdef HAVE_STAT_ST_FLAGS
3324 uint32 max_fmask = 0;
3327 *stat_fflags = psbuf->st_flags;
3329 /* For each flags requested in smb_fmask, check the state of the
3330 * corresponding flag in smb_fflags and set or clear the matching
3334 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3335 max_fmask |= info2_flags_map[i].smb_fflag;
3336 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3337 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3338 *stat_fflags |= info2_flags_map[i].stat_fflag;
3340 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3345 /* If smb_fmask is asking to set any bits that are not supported by
3346 * our flag mappings, we should fail.
3348 if ((smb_fmask & max_fmask) != smb_fmask) {
3355 #endif /* HAVE_STAT_ST_FLAGS */
3359 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3360 * of file flags and birth (create) time.
3362 static char *store_file_unix_basic_info2(connection_struct *conn,
3365 const SMB_STRUCT_STAT *psbuf)
3367 uint32 file_flags = 0;
3368 uint32 flags_mask = 0;
3370 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3372 /* Create (birth) time 64 bit */
3373 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3376 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3377 SIVAL(pdata, 0, file_flags); /* flags */
3378 SIVAL(pdata, 4, flags_mask); /* mask */
3384 /****************************************************************************
3385 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3386 ****************************************************************************/
3388 static void call_trans2qpipeinfo(connection_struct *conn,
3389 struct smb_request *req,
3390 unsigned int tran_call,
3391 char **pparams, int total_params,
3392 char **ppdata, int total_data,
3393 unsigned int max_data_bytes)
3395 char *params = *pparams;
3396 char *pdata = *ppdata;
3397 unsigned int data_size = 0;
3398 unsigned int param_size = 2;
3400 smb_np_struct *p_pipe = NULL;
3403 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3407 if (total_params < 4) {
3408 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3412 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3413 if (p_pipe == NULL) {
3414 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3418 info_level = SVAL(params,2);
3420 *pparams = (char *)SMB_REALLOC(*pparams,2);
3421 if (*pparams == NULL) {
3422 reply_nterror(req, NT_STATUS_NO_MEMORY);
3427 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3428 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3429 if (*ppdata == NULL ) {
3430 reply_nterror(req, NT_STATUS_NO_MEMORY);
3435 switch (info_level) {
3436 case SMB_FILE_STANDARD_INFORMATION:
3438 SOFF_T(pdata,0,4096LL);
3445 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3449 send_trans2_replies(req, params, param_size, *ppdata, data_size,
3455 /****************************************************************************
3456 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3457 file name or file id).
3458 ****************************************************************************/
3460 static void call_trans2qfilepathinfo(connection_struct *conn,
3461 struct smb_request *req,
3462 unsigned int tran_call,
3463 char **pparams, int total_params,
3464 char **ppdata, int total_data,
3465 unsigned int max_data_bytes)
3467 char *params = *pparams;
3468 char *pdata = *ppdata;
3469 char *dstart, *dend;
3473 SMB_OFF_T file_size=0;
3474 SMB_BIG_UINT allocation_size=0;
3475 unsigned int data_size = 0;
3476 unsigned int param_size = 2;
3477 SMB_STRUCT_STAT sbuf;
3478 char *dos_fname = NULL;
3484 bool delete_pending = False;
3486 time_t create_time, mtime, atime;
3487 struct timespec create_time_ts, mtime_ts, atime_ts;
3488 files_struct *fsp = NULL;
3489 struct file_id fileid;
3490 struct ea_list *ea_list = NULL;
3491 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3492 char *lock_data = NULL;
3493 TALLOC_CTX *ctx = talloc_tos();
3496 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3502 if (tran_call == TRANSACT2_QFILEINFO) {
3503 if (total_params < 4) {
3504 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3509 call_trans2qpipeinfo(conn, req, tran_call,
3510 pparams, total_params,
3516 fsp = file_fsp(SVAL(params,0));
3517 info_level = SVAL(params,2);
3519 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3521 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3522 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3526 /* Initial check for valid fsp ptr. */
3527 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
3531 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3533 reply_nterror(req, NT_STATUS_NO_MEMORY);
3537 if(fsp->fake_file_handle) {
3539 * This is actually for the QUOTA_FAKE_FILE --metze
3542 /* We know this name is ok, it's already passed the checks. */
3544 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3546 * This is actually a QFILEINFO on a directory
3547 * handle (returned from an NT SMB). NT5.0 seems
3548 * to do this call. JRA.
3551 if (INFO_LEVEL_IS_UNIX(info_level)) {
3552 /* Always do lstat for UNIX calls. */
3553 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3554 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3555 reply_unixerror(req,ERRDOS,ERRbadpath);
3558 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3559 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3560 reply_unixerror(req, ERRDOS, ERRbadpath);
3564 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3565 delete_pending = get_delete_on_close_flag(fileid);
3568 * Original code - this is an open file.
3570 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3574 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3575 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3576 reply_unixerror(req, ERRDOS, ERRbadfid);
3579 pos = fsp->fh->position_information;
3580 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3581 delete_pending = get_delete_on_close_flag(fileid);
3582 access_mask = fsp->access_mask;
3586 NTSTATUS status = NT_STATUS_OK;
3589 if (total_params < 7) {
3590 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3594 info_level = SVAL(params,0);
3596 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3598 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3599 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3603 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3605 STR_TERMINATE, &status);
3606 if (!NT_STATUS_IS_OK(status)) {
3607 reply_nterror(req, status);
3611 status = resolve_dfspath(ctx,
3613 req->flags2 & FLAGS2_DFS_PATHNAMES,
3616 if (!NT_STATUS_IS_OK(status)) {
3617 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3618 reply_botherror(req,
3619 NT_STATUS_PATH_NOT_COVERED,
3620 ERRSRV, ERRbadpath);
3622 reply_nterror(req, status);
3626 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3627 if (!NT_STATUS_IS_OK(status)) {
3628 reply_nterror(req, status);
3631 status = check_name(conn, fname);
3632 if (!NT_STATUS_IS_OK(status)) {
3633 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3634 reply_nterror(req, status);
3638 if (INFO_LEVEL_IS_UNIX(info_level)) {
3639 /* Always do lstat for UNIX calls. */
3640 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3641 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3642 reply_unixerror(req, ERRDOS, ERRbadpath);
3645 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3646 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3647 reply_unixerror(req, ERRDOS, ERRbadpath);
3651 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3652 delete_pending = get_delete_on_close_flag(fileid);
3653 if (delete_pending) {
3654 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3659 nlink = sbuf.st_nlink;
3661 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3662 /* NTFS does not seem to count ".." */
3666 if ((nlink > 0) && delete_pending) {
3670 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3671 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3675 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3676 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3678 p = strrchr_m(fname,'/');
3684 mode = dos_mode(conn,fname,&sbuf);
3686 mode = FILE_ATTRIBUTE_NORMAL;
3688 fullpathname = fname;
3690 file_size = get_file_size(sbuf);
3692 /* Pull out any data sent here before we realloc. */
3693 switch (info_level) {
3694 case SMB_INFO_QUERY_EAS_FROM_LIST:
3696 /* Pull any EA list from the data portion. */
3699 if (total_data < 4) {
3701 req, NT_STATUS_INVALID_PARAMETER);
3704 ea_size = IVAL(pdata,0);
3706 if (total_data > 0 && ea_size != total_data) {
3707 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3708 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3710 req, NT_STATUS_INVALID_PARAMETER);
3714 if (!lp_ea_support(SNUM(conn))) {
3715 reply_doserror(req, ERRDOS,
3716 ERReasnotsupported);
3720 /* Pull out the list of names. */
3721 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3724 req, NT_STATUS_INVALID_PARAMETER);
3730 case SMB_QUERY_POSIX_LOCK:
3732 if (fsp == NULL || fsp->fh->fd == -1) {
3733 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3737 if (total_data != POSIX_LOCK_DATA_SIZE) {
3739 req, NT_STATUS_INVALID_PARAMETER);
3743 /* Copy the lock range data. */
3744 lock_data = (char *)TALLOC_MEMDUP(
3745 ctx, pdata, total_data);
3747 reply_nterror(req, NT_STATUS_NO_MEMORY);
3755 *pparams = (char *)SMB_REALLOC(*pparams,2);
3756 if (*pparams == NULL) {
3757 reply_nterror(req, NT_STATUS_NO_MEMORY);
3762 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3763 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3764 if (*ppdata == NULL ) {
3765 reply_nterror(req, NT_STATUS_NO_MEMORY);
3770 dend = dstart + data_size - 1;
3772 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3773 mtime_ts = get_mtimespec(&sbuf);
3774 atime_ts = get_atimespec(&sbuf);
3776 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3779 if (!null_timespec(fsp->pending_modtime)) {
3780 /* the pending modtime overrides the current modtime */
3781 mtime_ts = fsp->pending_modtime;
3785 /* Do we have this path open ? */
3786 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3787 fsp1 = file_find_di_first(fileid);
3788 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3789 /* the pending modtime overrides the current modtime */
3790 mtime_ts = fsp1->pending_modtime;
3792 if (fsp1 && fsp1->initial_allocation_size) {
3793 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3797 if (lp_dos_filetime_resolution(SNUM(conn))) {
3798 dos_filetime_timespec(&create_time_ts);
3799 dos_filetime_timespec(&mtime_ts);
3800 dos_filetime_timespec(&atime_ts);
3803 create_time = convert_timespec_to_time_t(create_time_ts);
3804 mtime = convert_timespec_to_time_t(mtime_ts);
3805 atime = convert_timespec_to_time_t(atime_ts);
3807 /* NT expects the name to be in an exact form of the *full*
3808 filename. See the trans2 torture test */
3809 if (ISDOT(base_name)) {
3810 dos_fname = talloc_strdup(ctx, "\\");
3812 reply_nterror(req, NT_STATUS_NO_MEMORY);
3816 dos_fname = talloc_asprintf(ctx,
3820 reply_nterror(req, NT_STATUS_NO_MEMORY);
3823 string_replace(dos_fname, '/', '\\');
3826 switch (info_level) {
3827 case SMB_INFO_STANDARD:
3828 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3830 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3831 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3832 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3833 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3834 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3835 SSVAL(pdata,l1_attrFile,mode);
3838 case SMB_INFO_QUERY_EA_SIZE:
3840 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3841 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3843 srv_put_dos_date2(pdata,0,create_time);
3844 srv_put_dos_date2(pdata,4,atime);
3845 srv_put_dos_date2(pdata,8,mtime); /* write time */
3846 SIVAL(pdata,12,(uint32)file_size);
3847 SIVAL(pdata,16,(uint32)allocation_size);
3848 SSVAL(pdata,20,mode);
3849 SIVAL(pdata,22,ea_size);
3853 case SMB_INFO_IS_NAME_VALID:
3854 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3855 if (tran_call == TRANSACT2_QFILEINFO) {
3856 /* os/2 needs this ? really ?*/
3857 reply_doserror(req, ERRDOS, ERRbadfunc);
3864 case SMB_INFO_QUERY_EAS_FROM_LIST:
3866 size_t total_ea_len = 0;
3867 struct ea_list *ea_file_list = NULL;
3869 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3871 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3872 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3874 if (!ea_list || (total_ea_len > data_size)) {
3876 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3880 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3884 case SMB_INFO_QUERY_ALL_EAS:
3886 /* We have data_size bytes to put EA's into. */
3887 size_t total_ea_len = 0;
3889 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3891 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3892 if (!ea_list || (total_ea_len > data_size)) {
3894 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3898 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3902 case SMB_FILE_BASIC_INFORMATION:
3903 case SMB_QUERY_FILE_BASIC_INFO:
3905 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3906 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3907 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3909 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3913 put_long_date_timespec(pdata,create_time_ts);
3914 put_long_date_timespec(pdata+8,atime_ts);
3915 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3916 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3917 SIVAL(pdata,32,mode);
3919 DEBUG(5,("SMB_QFBI - "));
3920 DEBUG(5,("create: %s ", ctime(&create_time)));
3921 DEBUG(5,("access: %s ", ctime(&atime)));
3922 DEBUG(5,("write: %s ", ctime(&mtime)));
3923 DEBUG(5,("change: %s ", ctime(&mtime)));
3924 DEBUG(5,("mode: %x\n", mode));
3927 case SMB_FILE_STANDARD_INFORMATION:
3928 case SMB_QUERY_FILE_STANDARD_INFO:
3930 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3932 SOFF_T(pdata,0,allocation_size);
3933 SOFF_T(pdata,8,file_size);
3934 SIVAL(pdata,16,nlink);
3935 SCVAL(pdata,20,delete_pending?1:0);
3936 SCVAL(pdata,21,(mode&aDIR)?1:0);
3937 SSVAL(pdata,22,0); /* Padding. */
3940 case SMB_FILE_EA_INFORMATION:
3941 case SMB_QUERY_FILE_EA_INFO:
3943 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3944 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3946 SIVAL(pdata,0,ea_size);
3950 /* Get the 8.3 name - used if NT SMB was negotiated. */
3951 case SMB_QUERY_FILE_ALT_NAME_INFO:
3952 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3954 char mangled_name[13];
3955 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3956 if (!name_to_8_3(base_name,mangled_name,
3957 True,conn->params)) {
3960 NT_STATUS_NO_MEMORY);
3962 len = srvstr_push(dstart, req->flags2,
3963 pdata+4, mangled_name,
3964 PTR_DIFF(dend, pdata+4),
3966 data_size = 4 + len;
3971 case SMB_QUERY_FILE_NAME_INFO:
3973 this must be *exactly* right for ACLs on mapped drives to work
3975 len = srvstr_push(dstart, req->flags2,
3977 PTR_DIFF(dend, pdata+4),
3979 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3980 data_size = 4 + len;
3984 case SMB_FILE_ALLOCATION_INFORMATION:
3985 case SMB_QUERY_FILE_ALLOCATION_INFO:
3986 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3988 SOFF_T(pdata,0,allocation_size);
3991 case SMB_FILE_END_OF_FILE_INFORMATION:
3992 case SMB_QUERY_FILE_END_OF_FILEINFO:
3993 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3995 SOFF_T(pdata,0,file_size);
3998 case SMB_QUERY_FILE_ALL_INFO:
3999 case SMB_FILE_ALL_INFORMATION:
4001 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4002 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4003 put_long_date_timespec(pdata,create_time_ts);
4004 put_long_date_timespec(pdata+8,atime_ts);
4005 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4006 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4007 SIVAL(pdata,32,mode);
4008 SIVAL(pdata,36,0); /* padding. */
4010 SOFF_T(pdata,0,allocation_size);
4011 SOFF_T(pdata,8,file_size);
4012 SIVAL(pdata,16,nlink);
4013 SCVAL(pdata,20,delete_pending);
4014 SCVAL(pdata,21,(mode&aDIR)?1:0);
4017 SIVAL(pdata,0,ea_size);
4018 pdata += 4; /* EA info */
4019 len = srvstr_push(dstart, req->flags2,
4021 PTR_DIFF(dend, pdata+4),
4025 data_size = PTR_DIFF(pdata,(*ppdata));
4028 case SMB_FILE_INTERNAL_INFORMATION:
4029 /* This should be an index number - looks like
4032 I think this causes us to fail the IFSKIT
4033 BasicFileInformationTest. -tpot */
4035 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4036 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4037 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4041 case SMB_FILE_ACCESS_INFORMATION:
4042 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4043 SIVAL(pdata,0,access_mask);
4047 case SMB_FILE_NAME_INFORMATION:
4048 /* Pathname with leading '\'. */
4051 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4052 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4053 SIVAL(pdata,0,byte_len);
4054 data_size = 4 + byte_len;
4058 case SMB_FILE_DISPOSITION_INFORMATION:
4059 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4061 SCVAL(pdata,0,delete_pending);
4064 case SMB_FILE_POSITION_INFORMATION:
4065 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4067 SOFF_T(pdata,0,pos);
4070 case SMB_FILE_MODE_INFORMATION:
4071 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4072 SIVAL(pdata,0,mode);
4076 case SMB_FILE_ALIGNMENT_INFORMATION:
4077 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4078 SIVAL(pdata,0,0); /* No alignment needed. */
4084 * NT4 server just returns "invalid query" to this - if we try to answer
4085 * it then NTws gets a BSOD! (tridge).
4086 * W2K seems to want this. JRA.
4088 case SMB_QUERY_FILE_STREAM_INFO:
4090 case SMB_FILE_STREAM_INFORMATION:
4091 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4095 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4096 SIVAL(pdata,0,0); /* ??? */
4097 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4098 SOFF_T(pdata,8,file_size);
4099 SOFF_T(pdata,16,allocation_size);
4100 data_size = 24 + byte_len;
4104 case SMB_QUERY_COMPRESSION_INFO:
4105 case SMB_FILE_COMPRESSION_INFORMATION:
4106 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4107 SOFF_T(pdata,0,file_size);
4108 SIVAL(pdata,8,0); /* ??? */
4109 SIVAL(pdata,12,0); /* ??? */
4113 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4114 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4115 put_long_date_timespec(pdata,create_time_ts);
4116 put_long_date_timespec(pdata+8,atime_ts);
4117 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4118 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4119 SOFF_T(pdata,32,allocation_size);
4120 SOFF_T(pdata,40,file_size);
4121 SIVAL(pdata,48,mode);
4122 SIVAL(pdata,52,0); /* ??? */
4126 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4127 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4128 SIVAL(pdata,0,mode);
4134 * CIFS UNIX Extensions.
4137 case SMB_QUERY_FILE_UNIX_BASIC:
4139 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4140 data_size = PTR_DIFF(pdata,(*ppdata));
4144 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4146 for (i=0; i<100; i++)
4147 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4153 case SMB_QUERY_FILE_UNIX_INFO2:
4155 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4156 data_size = PTR_DIFF(pdata,(*ppdata));
4160 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4162 for (i=0; i<100; i++)
4163 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4169 case SMB_QUERY_FILE_UNIX_LINK:
4171 char *buffer = TALLOC_ARRAY(ctx, char, 1024);
4174 reply_nterror(req, NT_STATUS_NO_MEMORY);
4178 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4180 if(!S_ISLNK(sbuf.st_mode)) {
4181 reply_unixerror(req, ERRSRV,
4186 reply_unixerror(req, ERRDOS, ERRbadlink);
4189 len = SMB_VFS_READLINK(conn,fullpathname,
4192 reply_unixerror(req, ERRDOS,
4197 len = srvstr_push(dstart, req->flags2,
4199 PTR_DIFF(dend, pdata),
4202 data_size = PTR_DIFF(pdata,(*ppdata));
4207 #if defined(HAVE_POSIX_ACLS)
4208 case SMB_QUERY_POSIX_ACL:
4210 SMB_ACL_T file_acl = NULL;
4211 SMB_ACL_T def_acl = NULL;
4212 uint16 num_file_acls = 0;
4213 uint16 num_def_acls = 0;
4215 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4216 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4218 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4221 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4222 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4226 NT_STATUS_NOT_IMPLEMENTED);
4230 if (S_ISDIR(sbuf.st_mode)) {
4231 if (fsp && fsp->is_directory) {
4232 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4234 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4236 def_acl = free_empty_sys_acl(conn, def_acl);
4239 num_file_acls = count_acl_entries(conn, file_acl);
4240 num_def_acls = count_acl_entries(conn, def_acl);
4242 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4243 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4245 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4246 SMB_POSIX_ACL_HEADER_SIZE) ));
4248 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4251 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4255 NT_STATUS_BUFFER_TOO_SMALL);
4259 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4260 SSVAL(pdata,2,num_file_acls);
4261 SSVAL(pdata,4,num_def_acls);
4262 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4264 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4267 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4270 req, NT_STATUS_INTERNAL_ERROR);
4273 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4275 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4278 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4282 NT_STATUS_INTERNAL_ERROR);
4287 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4290 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4292 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4298 case SMB_QUERY_POSIX_LOCK:
4300 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4302 SMB_BIG_UINT offset;
4304 enum brl_type lock_type;
4306 if (total_data != POSIX_LOCK_DATA_SIZE) {
4308 req, NT_STATUS_INVALID_PARAMETER);
4312 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4313 case POSIX_LOCK_TYPE_READ:
4314 lock_type = READ_LOCK;
4316 case POSIX_LOCK_TYPE_WRITE:
4317 lock_type = WRITE_LOCK;
4319 case POSIX_LOCK_TYPE_UNLOCK:
4321 /* There's no point in asking for an unlock... */
4324 NT_STATUS_INVALID_PARAMETER);
4328 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4329 #if defined(HAVE_LONGLONG)
4330 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4331 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4332 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4333 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4334 #else /* HAVE_LONGLONG */
4335 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4336 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4337 #endif /* HAVE_LONGLONG */
4339 status = query_lock(fsp,
4346 if (ERROR_WAS_LOCK_DENIED(status)) {
4347 /* Here we need to report who has it locked... */
4348 data_size = POSIX_LOCK_DATA_SIZE;
4350 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4351 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4352 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4353 #if defined(HAVE_LONGLONG)
4354 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4355 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4356 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4357 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4358 #else /* HAVE_LONGLONG */
4359 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4360 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4361 #endif /* HAVE_LONGLONG */
4363 } else if (NT_STATUS_IS_OK(status)) {
4364 /* For success we just return a copy of what we sent
4365 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4366 data_size = POSIX_LOCK_DATA_SIZE;
4367 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4368 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4370 reply_nterror(req, status);
4377 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4381 send_trans2_replies(req, params, param_size, *ppdata, data_size,
4387 /****************************************************************************
4388 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4390 ****************************************************************************/
4392 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4393 connection_struct *conn,
4394 const char *oldname_in,
4395 const char *newname_in)
4397 SMB_STRUCT_STAT sbuf1, sbuf2;
4398 char *last_component_oldname = NULL;
4399 char *last_component_newname = NULL;
4400 char *oldname = NULL;
4401 char *newname = NULL;
4402 NTSTATUS status = NT_STATUS_OK;
4407 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4408 &last_component_oldname, &sbuf1);
4409 if (!NT_STATUS_IS_OK(status)) {
4413 status = check_name(conn, oldname);
4414 if (!NT_STATUS_IS_OK(status)) {
4418 /* source must already exist. */
4419 if (!VALID_STAT(sbuf1)) {
4420 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4423 status = unix_convert(ctx, conn, newname_in, False, &newname,
4424 &last_component_newname, &sbuf2);
4425 if (!NT_STATUS_IS_OK(status)) {
4429 status = check_name(conn, newname);
4430 if (!NT_STATUS_IS_OK(status)) {
4434 /* Disallow if newname already exists. */
4435 if (VALID_STAT(sbuf2)) {
4436 return NT_STATUS_OBJECT_NAME_COLLISION;
4439 /* No links from a directory. */
4440 if (S_ISDIR(sbuf1.st_mode)) {
4441 return NT_STATUS_FILE_IS_A_DIRECTORY;
4444 /* Ensure this is within the share. */
4445 status = check_reduced_name(conn, oldname);
4446 if (!NT_STATUS_IS_OK(status)) {
4450 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4452 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4453 status = map_nt_error_from_unix(errno);
4454 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4455 nt_errstr(status), newname, oldname));
4461 /****************************************************************************
4462 Deal with setting the time from any of the setfilepathinfo functions.
4463 ****************************************************************************/
4465 static NTSTATUS smb_set_file_time(connection_struct *conn,
4468 const SMB_STRUCT_STAT *psbuf,
4469 struct timespec ts[2],
4470 bool setting_write_time)
4473 FILE_NOTIFY_CHANGE_LAST_ACCESS
4474 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4476 if (!VALID_STAT(*psbuf)) {
4477 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4480 /* get some defaults (no modifications) if any info is zero or -1. */
4481 if (null_timespec(ts[0])) {
4482 ts[0] = get_atimespec(psbuf);
4483 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4486 if (null_timespec(ts[1])) {
4487 ts[1] = get_mtimespec(psbuf);
4488 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4491 if (!setting_write_time) {
4492 /* ts[1] comes from change time, not write time. */
4493 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4496 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4497 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4500 * Try and set the times of this file if
4501 * they are different from the current values.
4505 struct timespec mts = get_mtimespec(psbuf);
4506 struct timespec ats = get_atimespec(psbuf);
4507 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4508 return NT_STATUS_OK;
4514 * This was a setfileinfo on an open file.
4515 * NT does this a lot. We also need to
4516 * set the time here, as it can be read by
4517 * FindFirst/FindNext and with the patch for bug #2045
4518 * in smbd/fileio.c it ensures that this timestamp is
4519 * kept sticky even after a write. We save the request
4520 * away and will set it on file close and after a write. JRA.
4523 if (!null_timespec(ts[1])) {
4524 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4525 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4526 fsp_set_pending_modtime(fsp, ts[1]);
4530 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4532 if(file_ntimes(conn, fname, ts)!=0) {
4533 return map_nt_error_from_unix(errno);
4535 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4537 return NT_STATUS_OK;
4540 /****************************************************************************
4541 Deal with setting the dosmode from any of the setfilepathinfo functions.
4542 ****************************************************************************/
4544 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4546 SMB_STRUCT_STAT *psbuf,
4549 if (!VALID_STAT(*psbuf)) {
4550 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4554 if (S_ISDIR(psbuf->st_mode)) {
4561 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4563 /* check the mode isn't different, before changing it */
4564 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4566 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4567 fname, (unsigned int)dosmode ));
4569 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4570 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4571 fname, strerror(errno)));
4572 return map_nt_error_from_unix(errno);
4575 return NT_STATUS_OK;
4578 /****************************************************************************
4579 Deal with setting the size from any of the setfilepathinfo functions.
4580 ****************************************************************************/
4582 static NTSTATUS smb_set_file_size(connection_struct *conn,
4583 struct smb_request *req,
4586 SMB_STRUCT_STAT *psbuf,
4589 NTSTATUS status = NT_STATUS_OK;
4590 files_struct *new_fsp = NULL;
4592 if (!VALID_STAT(*psbuf)) {
4593 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4596 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4598 if (size == get_file_size(*psbuf)) {
4599 return NT_STATUS_OK;
4602 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4603 fname, (double)size ));
4605 if (fsp && fsp->fh->fd != -1) {
4606 /* Handle based call. */
4607 if (vfs_set_filelen(fsp, size) == -1) {
4608 return map_nt_error_from_unix(errno);
4610 return NT_STATUS_OK;
4613 status = open_file_ntcreate(conn, req, fname, psbuf,
4615 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4618 FILE_ATTRIBUTE_NORMAL,
4619 FORCE_OPLOCK_BREAK_TO_NONE,
4622 if (!NT_STATUS_IS_OK(status)) {
4623 /* NB. We check for open_was_deferred in the caller. */
4627 if (vfs_set_filelen(new_fsp, size) == -1) {
4628 status = map_nt_error_from_unix(errno);
4629 close_file(new_fsp,NORMAL_CLOSE);
4633 close_file(new_fsp,NORMAL_CLOSE);
4634 return NT_STATUS_OK;
4637 /****************************************************************************
4638 Deal with SMB_INFO_SET_EA.
4639 ****************************************************************************/
4641 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4647 struct ea_list *ea_list = NULL;
4648 TALLOC_CTX *ctx = NULL;
4649 NTSTATUS status = NT_STATUS_OK;
4651 if (total_data < 10) {
4653 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4654 length. They seem to have no effect. Bug #3212. JRA */
4656 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4657 /* We're done. We only get EA info in this call. */
4658 return NT_STATUS_OK;
4661 return NT_STATUS_INVALID_PARAMETER;
4664 if (IVAL(pdata,0) > total_data) {
4665 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4666 IVAL(pdata,0), (unsigned int)total_data));
4667 return NT_STATUS_INVALID_PARAMETER;
4670 ctx = talloc_init("SMB_INFO_SET_EA");
4672 return NT_STATUS_NO_MEMORY;
4674 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4676 talloc_destroy(ctx);
4677 return NT_STATUS_INVALID_PARAMETER;
4679 status = set_ea(conn, fsp, fname, ea_list);
4680 talloc_destroy(ctx);
4685 /****************************************************************************
4686 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4687 ****************************************************************************/
4689 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4694 SMB_STRUCT_STAT *psbuf)
4696 NTSTATUS status = NT_STATUS_OK;
4697 bool delete_on_close;
4700 if (total_data < 1) {
4701 return NT_STATUS_INVALID_PARAMETER;
4705 return NT_STATUS_INVALID_HANDLE;
4708 delete_on_close = (CVAL(pdata,0) ? True : False);
4709 dosmode = dos_mode(conn, fname, psbuf);
4711 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4712 "delete_on_close = %u\n",
4714 (unsigned int)dosmode,
4715 (unsigned int)delete_on_close ));
4717 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4719 if (!NT_STATUS_IS_OK(status)) {
4723 /* The set is across all open files on this dev/inode pair. */
4724 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4725 return NT_STATUS_ACCESS_DENIED;
4727 return NT_STATUS_OK;
4730 /****************************************************************************
4731 Deal with SMB_FILE_POSITION_INFORMATION.
4732 ****************************************************************************/
4734 static NTSTATUS smb_file_position_information(connection_struct *conn,
4739 SMB_BIG_UINT position_information;
4741 if (total_data < 8) {
4742 return NT_STATUS_INVALID_PARAMETER;
4746 /* Ignore on pathname based set. */
4747 return NT_STATUS_OK;
4750 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4751 #ifdef LARGE_SMB_OFF_T
4752 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4753 #else /* LARGE_SMB_OFF_T */
4754 if (IVAL(pdata,4) != 0) {
4755 /* more than 32 bits? */
4756 return NT_STATUS_INVALID_PARAMETER;
4758 #endif /* LARGE_SMB_OFF_T */
4760 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4761 fsp->fsp_name, (double)position_information ));
4762 fsp->fh->position_information = position_information;
4763 return NT_STATUS_OK;
4766 /****************************************************************************
4767 Deal with SMB_FILE_MODE_INFORMATION.
4768 ****************************************************************************/
4770 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4776 if (total_data < 4) {
4777 return NT_STATUS_INVALID_PARAMETER;
4779 mode = IVAL(pdata,0);
4780 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4781 return NT_STATUS_INVALID_PARAMETER;
4783 return NT_STATUS_OK;
4786 /****************************************************************************
4787 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4788 ****************************************************************************/
4790 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4791 struct smb_request *req,
4796 char *link_target = NULL;
4797 const char *newname = fname;
4798 NTSTATUS status = NT_STATUS_OK;
4799 TALLOC_CTX *ctx = talloc_tos();
4801 /* Set a symbolic link. */
4802 /* Don't allow this if follow links is false. */
4804 if (total_data == 0) {
4805 return NT_STATUS_INVALID_PARAMETER;
4808 if (!lp_symlinks(SNUM(conn))) {
4809 return NT_STATUS_ACCESS_DENIED;
4812 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
4813 total_data, STR_TERMINATE);
4816 return NT_STATUS_INVALID_PARAMETER;
4819 /* !widelinks forces the target path to be within the share. */
4820 /* This means we can interpret the target as a pathname. */
4821 if (!lp_widelinks(SNUM(conn))) {
4822 char *rel_name = NULL;
4823 char *last_dirp = NULL;
4825 if (*link_target == '/') {
4826 /* No absolute paths allowed. */
4827 return NT_STATUS_ACCESS_DENIED;
4829 rel_name = talloc_strdup(ctx,newname);
4831 return NT_STATUS_NO_MEMORY;
4833 last_dirp = strrchr_m(rel_name, '/');
4835 last_dirp[1] = '\0';
4837 rel_name = talloc_strdup(ctx,"./");
4839 return NT_STATUS_NO_MEMORY;
4842 rel_name = talloc_asprintf_append(rel_name,
4846 return NT_STATUS_NO_MEMORY;
4849 status = check_name(conn, rel_name);
4850 if (!NT_STATUS_IS_OK(status)) {
4855 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4856 newname, link_target ));
4858 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4859 return map_nt_error_from_unix(errno);
4862 return NT_STATUS_OK;
4865 /****************************************************************************
4866 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4867 ****************************************************************************/
4869 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4870 struct smb_request *req,
4871 const char *pdata, int total_data,
4874 char *oldname = NULL;
4875 TALLOC_CTX *ctx = talloc_tos();
4876 NTSTATUS status = NT_STATUS_OK;
4878 /* Set a hard link. */
4879 if (total_data == 0) {
4880 return NT_STATUS_INVALID_PARAMETER;
4883 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
4884 total_data, STR_TERMINATE, &status);
4885 if (!NT_STATUS_IS_OK(status)) {
4889 status = resolve_dfspath(ctx, conn,
4890 req->flags2 & FLAGS2_DFS_PATHNAMES,
4893 if (!NT_STATUS_IS_OK(status)) {
4897 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4900 return hardlink_internals(ctx, conn, oldname, fname);
4903 /****************************************************************************
4904 Deal with SMB_FILE_RENAME_INFORMATION.
4905 ****************************************************************************/
4907 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4908 struct smb_request *req,
4917 char *newname = NULL;
4918 char *base_name = NULL;
4919 bool dest_has_wcard = False;
4920 NTSTATUS status = NT_STATUS_OK;
4922 TALLOC_CTX *ctx = talloc_tos();
4924 if (total_data < 13) {
4925 return NT_STATUS_INVALID_PARAMETER;
4928 overwrite = (CVAL(pdata,0) ? True : False);
4929 root_fid = IVAL(pdata,4);
4930 len = IVAL(pdata,8);
4932 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4933 return NT_STATUS_INVALID_PARAMETER;
4936 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
4939 if (!NT_STATUS_IS_OK(status)) {
4943 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4946 status = resolve_dfspath_wcard(ctx, conn,
4947 req->flags2 & FLAGS2_DFS_PATHNAMES,
4951 if (!NT_STATUS_IS_OK(status)) {
4955 /* Check the new name has no '/' characters. */
4956 if (strchr_m(newname, '/')) {
4957 return NT_STATUS_NOT_SUPPORTED;
4960 /* Create the base directory. */
4961 base_name = talloc_strdup(ctx, fname);
4963 return NT_STATUS_NO_MEMORY;
4965 p = strrchr_m(base_name, '/');
4969 base_name = talloc_strdup(ctx, "./");
4971 return NT_STATUS_NO_MEMORY;
4974 /* Append the new name. */
4975 base_name = talloc_asprintf_append(base_name,
4979 return NT_STATUS_NO_MEMORY;
4983 SMB_STRUCT_STAT sbuf;
4984 char *newname_last_component = NULL;
4988 status = unix_convert(ctx, conn, newname, False,
4990 &newname_last_component,
4993 /* If an error we expect this to be
4994 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
4996 if (!NT_STATUS_IS_OK(status)
4997 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5002 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5003 fsp->fnum, fsp->fsp_name, base_name ));
5004 status = rename_internals_fsp(conn, fsp, base_name,
5005 newname_last_component, 0,
5008 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5009 fname, base_name ));
5010 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5011 overwrite, False, dest_has_wcard);
5017 /****************************************************************************
5018 Deal with SMB_SET_POSIX_ACL.
5019 ****************************************************************************/
5021 #if defined(HAVE_POSIX_ACLS)
5022 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5027 SMB_STRUCT_STAT *psbuf)
5029 uint16 posix_acl_version;
5030 uint16 num_file_acls;
5031 uint16 num_def_acls;
5032 bool valid_file_acls = True;
5033 bool valid_def_acls = True;
5035 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5036 return NT_STATUS_INVALID_PARAMETER;
5038 posix_acl_version = SVAL(pdata,0);
5039 num_file_acls = SVAL(pdata,2);
5040 num_def_acls = SVAL(pdata,4);
5042 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5043 valid_file_acls = False;
5047 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5048 valid_def_acls = False;
5052 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5053 return NT_STATUS_INVALID_PARAMETER;
5056 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5057 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5058 return NT_STATUS_INVALID_PARAMETER;
5061 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5062 fname ? fname : fsp->fsp_name,
5063 (unsigned int)num_file_acls,
5064 (unsigned int)num_def_acls));
5066 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5067 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5068 return map_nt_error_from_unix(errno);
5071 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5072 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5073 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5074 return map_nt_error_from_unix(errno);
5076 return NT_STATUS_OK;
5080 /****************************************************************************
5081 Deal with SMB_SET_POSIX_LOCK.
5082 ****************************************************************************/
5084 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5092 SMB_BIG_UINT offset;
5094 bool blocking_lock = False;
5095 enum brl_type lock_type;
5096 NTSTATUS status = NT_STATUS_OK;
5098 if (fsp == NULL || fsp->fh->fd == -1) {
5099 return NT_STATUS_INVALID_HANDLE;
5102 if (total_data != POSIX_LOCK_DATA_SIZE) {
5103 return NT_STATUS_INVALID_PARAMETER;
5106 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5107 case POSIX_LOCK_TYPE_READ:
5108 lock_type = READ_LOCK;
5110 case POSIX_LOCK_TYPE_WRITE:
5111 /* Return the right POSIX-mappable error code for files opened read-only. */
5112 if (!fsp->can_write) {
5113 return NT_STATUS_INVALID_HANDLE;
5115 lock_type = WRITE_LOCK;
5117 case POSIX_LOCK_TYPE_UNLOCK:
5118 lock_type = UNLOCK_LOCK;
5121 return NT_STATUS_INVALID_PARAMETER;
5124 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5125 blocking_lock = False;
5126 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5127 blocking_lock = True;
5129 return NT_STATUS_INVALID_PARAMETER;
5132 if (!lp_blocking_locks(SNUM(conn))) {
5133 blocking_lock = False;
5136 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5137 #if defined(HAVE_LONGLONG)
5138 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5139 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5140 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5141 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5142 #else /* HAVE_LONGLONG */
5143 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5144 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5145 #endif /* HAVE_LONGLONG */
5147 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5148 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5150 (unsigned int)lock_type,
5151 (unsigned int)lock_pid,
5155 if (lock_type == UNLOCK_LOCK) {
5156 status = do_unlock(smbd_messaging_context(),
5163 uint32 block_smbpid;
5165 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5176 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5178 * A blocking lock was requested. Package up
5179 * this smb into a queued request and push it
5180 * onto the blocking lock queue.
5182 if(push_blocking_lock_request(br_lck,
5183 (char *)inbuf, length,
5185 -1, /* infinite timeout. */
5193 TALLOC_FREE(br_lck);
5197 TALLOC_FREE(br_lck);
5203 /****************************************************************************
5204 Deal with SMB_INFO_STANDARD.
5205 ****************************************************************************/
5207 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5212 const SMB_STRUCT_STAT *psbuf)
5214 struct timespec ts[2];
5216 if (total_data < 12) {
5217 return NT_STATUS_INVALID_PARAMETER;
5221 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5223 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5225 DEBUG(10,("smb_set_info_standard: file %s\n",
5226 fname ? fname : fsp->fsp_name ));
5228 return smb_set_file_time(conn,
5236 /****************************************************************************
5237 Deal with SMB_SET_FILE_BASIC_INFO.
5238 ****************************************************************************/
5240 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5245 SMB_STRUCT_STAT *psbuf)
5247 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5248 struct timespec write_time;
5249 struct timespec changed_time;
5251 struct timespec ts[2];
5252 NTSTATUS status = NT_STATUS_OK;
5253 bool setting_write_time = true;
5255 if (total_data < 36) {
5256 return NT_STATUS_INVALID_PARAMETER;
5259 /* Set the attributes */
5260 dosmode = IVAL(pdata,32);
5261 status = smb_set_file_dosmode(conn,
5265 if (!NT_STATUS_IS_OK(status)) {
5269 /* Ignore create time at offset pdata. */
5272 ts[0] = interpret_long_date(pdata+8);
5274 write_time = interpret_long_date(pdata+16);
5275 changed_time = interpret_long_date(pdata+24);
5278 ts[1] = timespec_min(&write_time, &changed_time);
5280 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5284 /* Prefer a defined time to an undefined one. */
5285 if (null_timespec(ts[1])) {
5286 if (null_timespec(write_time)) {
5287 ts[1] = changed_time;
5288 setting_write_time = false;
5294 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5295 fname ? fname : fsp->fsp_name ));
5297 return smb_set_file_time(conn,
5302 setting_write_time);
5305 /****************************************************************************
5306 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5307 ****************************************************************************/
5309 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5310 struct smb_request *req,
5315 SMB_STRUCT_STAT *psbuf)
5317 SMB_BIG_UINT allocation_size = 0;
5318 NTSTATUS status = NT_STATUS_OK;
5319 files_struct *new_fsp = NULL;
5321 if (!VALID_STAT(*psbuf)) {
5322 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5325 if (total_data < 8) {
5326 return NT_STATUS_INVALID_PARAMETER;
5329 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5330 #ifdef LARGE_SMB_OFF_T
5331 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5332 #else /* LARGE_SMB_OFF_T */
5333 if (IVAL(pdata,4) != 0) {
5334 /* more than 32 bits? */
5335 return NT_STATUS_INVALID_PARAMETER;
5337 #endif /* LARGE_SMB_OFF_T */
5339 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5340 fname, (double)allocation_size ));
5342 if (allocation_size) {
5343 allocation_size = smb_roundup(conn, allocation_size);
5346 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5347 fname, (double)allocation_size ));
5349 if (fsp && fsp->fh->fd != -1) {
5350 /* Open file handle. */
5351 /* Only change if needed. */
5352 if (allocation_size != get_file_size(*psbuf)) {
5353 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5354 return map_nt_error_from_unix(errno);
5357 /* But always update the time. */
5358 if (null_timespec(fsp->pending_modtime)) {
5360 * This is equivalent to a write. Ensure it's seen immediately
5361 * if there are no pending writes.
5363 set_filetime(fsp->conn, fsp->fsp_name,
5364 timespec_current());
5366 return NT_STATUS_OK;
5369 /* Pathname or stat or directory file. */
5371 status = open_file_ntcreate(conn, req, fname, psbuf,
5373 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5376 FILE_ATTRIBUTE_NORMAL,
5377 FORCE_OPLOCK_BREAK_TO_NONE,
5380 if (!NT_STATUS_IS_OK(status)) {
5381 /* NB. We check for open_was_deferred in the caller. */
5385 /* Only change if needed. */
5386 if (allocation_size != get_file_size(*psbuf)) {
5387 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5388 status = map_nt_error_from_unix(errno);
5389 close_file(new_fsp,NORMAL_CLOSE);
5394 /* Changing the allocation size should set the last mod time. */
5395 /* Don't need to call set_filetime as this will be flushed on
5398 fsp_set_pending_modtime(new_fsp, timespec_current());
5400 close_file(new_fsp,NORMAL_CLOSE);
5401 return NT_STATUS_OK;
5404 /****************************************************************************
5405 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5406 ****************************************************************************/
5408 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5409 struct smb_request *req,
5414 SMB_STRUCT_STAT *psbuf)
5418 if (total_data < 8) {
5419 return NT_STATUS_INVALID_PARAMETER;
5422 size = IVAL(pdata,0);
5423 #ifdef LARGE_SMB_OFF_T
5424 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5425 #else /* LARGE_SMB_OFF_T */
5426 if (IVAL(pdata,4) != 0) {
5427 /* more than 32 bits? */
5428 return NT_STATUS_INVALID_PARAMETER;
5430 #endif /* LARGE_SMB_OFF_T */
5431 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5432 "file %s to %.0f\n", fname, (double)size ));
5434 return smb_set_file_size(conn, req,
5441 /****************************************************************************
5442 Allow a UNIX info mknod.
5443 ****************************************************************************/
5445 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5449 SMB_STRUCT_STAT *psbuf)
5451 uint32 file_type = IVAL(pdata,56);
5452 #if defined(HAVE_MAKEDEV)
5453 uint32 dev_major = IVAL(pdata,60);
5454 uint32 dev_minor = IVAL(pdata,68);
5456 SMB_DEV_T dev = (SMB_DEV_T)0;
5457 uint32 raw_unixmode = IVAL(pdata,84);
5461 if (total_data < 100) {
5462 return NT_STATUS_INVALID_PARAMETER;
5465 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5466 if (!NT_STATUS_IS_OK(status)) {
5470 #if defined(HAVE_MAKEDEV)
5471 dev = makedev(dev_major, dev_minor);
5474 switch (file_type) {
5475 #if defined(S_IFIFO)
5476 case UNIX_TYPE_FIFO:
5477 unixmode |= S_IFIFO;
5480 #if defined(S_IFSOCK)
5481 case UNIX_TYPE_SOCKET:
5482 unixmode |= S_IFSOCK;
5485 #if defined(S_IFCHR)
5486 case UNIX_TYPE_CHARDEV:
5487 unixmode |= S_IFCHR;
5490 #if defined(S_IFBLK)
5491 case UNIX_TYPE_BLKDEV:
5492 unixmode |= S_IFBLK;
5496 return NT_STATUS_INVALID_PARAMETER;
5499 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5500 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5502 /* Ok - do the mknod. */
5503 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5504 return map_nt_error_from_unix(errno);
5507 /* If any of the other "set" calls fail we
5508 * don't want to end up with a half-constructed mknod.
5511 if (lp_inherit_perms(SNUM(conn))) {
5513 conn, parent_dirname(fname),
5517 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5518 status = map_nt_error_from_unix(errno);
5519 SMB_VFS_UNLINK(conn,fname);
5522 return NT_STATUS_OK;
5525 /****************************************************************************
5526 Deal with SMB_SET_FILE_UNIX_BASIC.
5527 ****************************************************************************/
5529 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5530 struct smb_request *req,
5535 SMB_STRUCT_STAT *psbuf)
5537 struct timespec ts[2];
5538 uint32 raw_unixmode;
5541 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5542 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5543 NTSTATUS status = NT_STATUS_OK;
5544 bool delete_on_fail = False;
5545 enum perm_type ptype;
5547 if (total_data < 100) {
5548 return NT_STATUS_INVALID_PARAMETER;
5551 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5552 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5553 size=IVAL(pdata,0); /* first 8 Bytes are size */
5554 #ifdef LARGE_SMB_OFF_T
5555 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5556 #else /* LARGE_SMB_OFF_T */
5557 if (IVAL(pdata,4) != 0) {
5558 /* more than 32 bits? */
5559 return NT_STATUS_INVALID_PARAMETER;
5561 #endif /* LARGE_SMB_OFF_T */
5564 ts[0] = interpret_long_date(pdata+24); /* access_time */
5565 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5566 set_owner = (uid_t)IVAL(pdata,40);
5567 set_grp = (gid_t)IVAL(pdata,48);
5568 raw_unixmode = IVAL(pdata,84);
5570 if (VALID_STAT(*psbuf)) {
5571 if (S_ISDIR(psbuf->st_mode)) {
5572 ptype = PERM_EXISTING_DIR;
5574 ptype = PERM_EXISTING_FILE;
5577 ptype = PERM_NEW_FILE;
5580 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5581 if (!NT_STATUS_IS_OK(status)) {
5585 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5586 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5587 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5589 if (!VALID_STAT(*psbuf)) {
5591 * The only valid use of this is to create character and block
5592 * devices, and named pipes. This is deprecated (IMHO) and
5593 * a new info level should be used for mknod. JRA.
5596 status = smb_unix_mknod(conn,
5601 if (!NT_STATUS_IS_OK(status)) {
5605 /* Ensure we don't try and change anything else. */
5606 raw_unixmode = SMB_MODE_NO_CHANGE;
5607 size = get_file_size(*psbuf);
5608 ts[0] = get_atimespec(psbuf);
5609 ts[1] = get_mtimespec(psbuf);
5611 * We continue here as we might want to change the
5614 delete_on_fail = True;
5618 /* Horrible backwards compatibility hack as an old server bug
5619 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5623 size = get_file_size(*psbuf);
5628 * Deal with the UNIX specific mode set.
5631 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5632 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5633 (unsigned int)unixmode, fname ));
5634 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5635 return map_nt_error_from_unix(errno);
5640 * Deal with the UNIX specific uid set.
5643 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5646 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5647 (unsigned int)set_owner, fname ));
5649 if (S_ISLNK(psbuf->st_mode)) {
5650 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5652 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5656 status = map_nt_error_from_unix(errno);
5657 if (delete_on_fail) {
5658 SMB_VFS_UNLINK(conn,fname);
5665 * Deal with the UNIX specific gid set.
5668 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5669 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5670 (unsigned int)set_owner, fname ));
5671 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5672 status = map_nt_error_from_unix(errno);
5673 if (delete_on_fail) {
5674 SMB_VFS_UNLINK(conn,fname);
5680 /* Deal with any size changes. */
5682 status = smb_set_file_size(conn, req,
5687 if (!NT_STATUS_IS_OK(status)) {
5691 /* Deal with any time changes. */
5693 return smb_set_file_time(conn,
5701 /****************************************************************************
5702 Deal with SMB_SET_FILE_UNIX_INFO2.
5703 ****************************************************************************/
5705 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5706 struct smb_request *req,
5711 SMB_STRUCT_STAT *psbuf)
5717 if (total_data < 116) {
5718 return NT_STATUS_INVALID_PARAMETER;
5721 /* Start by setting all the fields that are common between UNIX_BASIC
5724 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5726 if (!NT_STATUS_IS_OK(status)) {
5730 smb_fflags = IVAL(pdata, 108);
5731 smb_fmask = IVAL(pdata, 112);
5733 /* NB: We should only attempt to alter the file flags if the client
5734 * sends a non-zero mask.
5736 if (smb_fmask != 0) {
5737 int stat_fflags = 0;
5739 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5741 /* Client asked to alter a flag we don't understand. */
5742 return NT_STATUS_INVALID_PARAMETER;
5745 if (fsp && fsp->fh->fd != -1) {
5746 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5747 return NT_STATUS_NOT_SUPPORTED;
5749 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5750 return map_nt_error_from_unix(errno);
5755 /* XXX: need to add support for changing the create_time here. You
5756 * can do this for paths on Darwin with setattrlist(2). The right way
5757 * to hook this up is probably by extending the VFS utimes interface.
5760 return NT_STATUS_OK;
5763 /****************************************************************************
5764 Create a directory with POSIX semantics.
5765 ****************************************************************************/
5767 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5768 struct smb_request *req,
5772 SMB_STRUCT_STAT *psbuf,
5773 int *pdata_return_size)
5775 NTSTATUS status = NT_STATUS_OK;
5776 uint32 raw_unixmode = 0;
5777 uint32 mod_unixmode = 0;
5778 mode_t unixmode = (mode_t)0;
5779 files_struct *fsp = NULL;
5780 uint16 info_level_return = 0;
5782 char *pdata = *ppdata;
5784 if (total_data < 18) {
5785 return NT_STATUS_INVALID_PARAMETER;
5788 raw_unixmode = IVAL(pdata,8);
5789 /* Next 4 bytes are not yet defined. */
5791 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5792 if (!NT_STATUS_IS_OK(status)) {
5796 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5798 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5799 fname, (unsigned int)unixmode ));
5801 status = open_directory(conn, req,
5804 FILE_READ_ATTRIBUTES, /* Just a stat open */
5805 FILE_SHARE_NONE, /* Ignored for stat opens */
5812 if (NT_STATUS_IS_OK(status)) {
5813 close_file(fsp, NORMAL_CLOSE);
5816 info_level_return = SVAL(pdata,16);
5818 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5819 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5820 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5821 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5823 *pdata_return_size = 12;
5826 /* Realloc the data size */
5827 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5828 if (*ppdata == NULL) {
5829 *pdata_return_size = 0;
5830 return NT_STATUS_NO_MEMORY;
5834 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5835 SSVAL(pdata,2,0); /* No fnum. */
5836 SIVAL(pdata,4,info); /* Was directory created. */
5838 switch (info_level_return) {
5839 case SMB_QUERY_FILE_UNIX_BASIC:
5840 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5841 SSVAL(pdata,10,0); /* Padding. */
5842 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5844 case SMB_QUERY_FILE_UNIX_INFO2:
5845 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5846 SSVAL(pdata,10,0); /* Padding. */
5847 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5850 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5851 SSVAL(pdata,10,0); /* Padding. */
5858 /****************************************************************************
5859 Open/Create a file with POSIX semantics.
5860 ****************************************************************************/
5862 static NTSTATUS smb_posix_open(connection_struct *conn,
5863 struct smb_request *req,
5867 SMB_STRUCT_STAT *psbuf,
5868 int *pdata_return_size)
5870 bool extended_oplock_granted = False;
5871 char *pdata = *ppdata;
5873 uint32 wire_open_mode = 0;
5874 uint32 raw_unixmode = 0;
5875 uint32 mod_unixmode = 0;
5876 uint32 create_disp = 0;
5877 uint32 access_mask = 0;
5878 uint32 create_options = 0;
5879 NTSTATUS status = NT_STATUS_OK;
5880 mode_t unixmode = (mode_t)0;
5881 files_struct *fsp = NULL;
5882 int oplock_request = 0;
5884 uint16 info_level_return = 0;
5886 if (total_data < 18) {
5887 return NT_STATUS_INVALID_PARAMETER;
5890 flags = IVAL(pdata,0);
5891 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5892 if (oplock_request) {
5893 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5896 wire_open_mode = IVAL(pdata,4);
5898 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5899 return smb_posix_mkdir(conn, req,
5907 switch (wire_open_mode & SMB_ACCMODE) {
5909 access_mask = FILE_READ_DATA;
5912 access_mask = FILE_WRITE_DATA;
5915 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5918 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5919 (unsigned int)wire_open_mode ));
5920 return NT_STATUS_INVALID_PARAMETER;
5923 wire_open_mode &= ~SMB_ACCMODE;
5925 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5926 create_disp = FILE_CREATE;
5927 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5928 create_disp = FILE_OVERWRITE_IF;
5929 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5930 create_disp = FILE_OPEN_IF;
5932 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5933 (unsigned int)wire_open_mode ));
5934 return NT_STATUS_INVALID_PARAMETER;
5937 raw_unixmode = IVAL(pdata,8);
5938 /* Next 4 bytes are not yet defined. */
5940 status = unix_perms_from_wire(conn,
5943 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5946 if (!NT_STATUS_IS_OK(status)) {
5950 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5952 if (wire_open_mode & SMB_O_SYNC) {
5953 create_options |= FILE_WRITE_THROUGH;
5955 if (wire_open_mode & SMB_O_APPEND) {
5956 access_mask |= FILE_APPEND_DATA;
5958 if (wire_open_mode & SMB_O_DIRECT) {
5959 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5962 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5964 (unsigned int)wire_open_mode,
5965 (unsigned int)unixmode ));
5967 status = open_file_ntcreate(conn, req,
5971 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5973 0, /* no create options yet. */
5979 if (!NT_STATUS_IS_OK(status)) {
5983 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5984 extended_oplock_granted = True;
5987 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5988 extended_oplock_granted = True;
5991 info_level_return = SVAL(pdata,16);
5993 /* Allocate the correct return size. */
5995 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5996 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5997 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5998 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6000 *pdata_return_size = 12;
6003 /* Realloc the data size */
6004 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6005 if (*ppdata == NULL) {
6006 close_file(fsp,ERROR_CLOSE);
6007 *pdata_return_size = 0;
6008 return NT_STATUS_NO_MEMORY;
6012 if (extended_oplock_granted) {
6013 if (flags & REQUEST_BATCH_OPLOCK) {
6014 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6016 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6018 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6019 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6021 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6024 SSVAL(pdata,2,fsp->fnum);
6025 SIVAL(pdata,4,info); /* Was file created etc. */
6027 switch (info_level_return) {
6028 case SMB_QUERY_FILE_UNIX_BASIC:
6029 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6030 SSVAL(pdata,10,0); /* padding. */
6031 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6033 case SMB_QUERY_FILE_UNIX_INFO2:
6034 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6035 SSVAL(pdata,10,0); /* padding. */
6036 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6039 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6040 SSVAL(pdata,10,0); /* padding. */
6043 return NT_STATUS_OK;
6046 /****************************************************************************
6047 Delete a file with POSIX semantics.
6048 ****************************************************************************/
6050 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6051 struct smb_request *req,
6055 SMB_STRUCT_STAT *psbuf)
6057 NTSTATUS status = NT_STATUS_OK;
6058 files_struct *fsp = NULL;
6063 struct share_mode_lock *lck = NULL;
6065 if (total_data < 2) {
6066 return NT_STATUS_INVALID_PARAMETER;
6069 flags = SVAL(pdata,0);
6071 if (!VALID_STAT(*psbuf)) {
6072 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6075 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6076 !VALID_STAT_OF_DIR(*psbuf)) {
6077 return NT_STATUS_NOT_A_DIRECTORY;
6080 DEBUG(10,("smb_posix_unlink: %s %s\n",
6081 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6084 if (VALID_STAT_OF_DIR(*psbuf)) {
6085 status = open_directory(conn, req,
6089 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6092 FILE_FLAG_POSIX_SEMANTICS|0777,
6097 status = open_file_ntcreate(conn, req,
6101 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6104 FILE_FLAG_POSIX_SEMANTICS|0777,
6105 0, /* No oplock, but break existing ones. */
6110 if (!NT_STATUS_IS_OK(status)) {
6115 * Don't lie to client. If we can't really delete due to
6116 * non-POSIX opens return SHARING_VIOLATION.
6119 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
6121 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6122 "lock for file %s\n", fsp->fsp_name));
6123 close_file(fsp, NORMAL_CLOSE);
6124 return NT_STATUS_INVALID_PARAMETER;
6128 * See if others still have the file open. If this is the case, then
6129 * don't delete. If all opens are POSIX delete we can set the delete
6130 * on close disposition.
6132 for (i=0; i<lck->num_share_modes; i++) {
6133 struct share_mode_entry *e = &lck->share_modes[i];
6134 if (is_valid_share_mode_entry(e)) {
6135 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6138 /* Fail with sharing violation. */
6139 close_file(fsp, NORMAL_CLOSE);
6141 return NT_STATUS_SHARING_VIOLATION;
6146 * Set the delete on close.
6148 status = smb_set_file_disposition_info(conn,
6155 if (!NT_STATUS_IS_OK(status)) {
6156 close_file(fsp, NORMAL_CLOSE);
6161 return close_file(fsp, NORMAL_CLOSE);
6164 /****************************************************************************
6165 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6166 ****************************************************************************/
6168 static void call_trans2setfilepathinfo(connection_struct *conn,
6169 struct smb_request *req,
6170 unsigned int tran_call,
6171 char **pparams, int total_params,
6172 char **ppdata, int total_data,
6173 unsigned int max_data_bytes)
6175 char *params = *pparams;
6176 char *pdata = *ppdata;
6178 SMB_STRUCT_STAT sbuf;
6180 files_struct *fsp = NULL;
6181 NTSTATUS status = NT_STATUS_OK;
6182 int data_return_size = 0;
6183 TALLOC_CTX *ctx = talloc_tos();
6186 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6192 if (tran_call == TRANSACT2_SETFILEINFO) {
6193 if (total_params < 4) {
6194 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6198 fsp = file_fsp(SVAL(params,0));
6199 /* Basic check for non-null fsp. */
6200 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
6203 info_level = SVAL(params,2);
6205 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6207 reply_nterror(req, NT_STATUS_NO_MEMORY);
6211 if(fsp->is_directory || fsp->fh->fd == -1) {
6213 * This is actually a SETFILEINFO on a directory
6214 * handle (returned from an NT SMB). NT5.0 seems
6215 * to do this call. JRA.
6217 if (INFO_LEVEL_IS_UNIX(info_level)) {
6218 /* Always do lstat for UNIX calls. */
6219 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6220 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6221 reply_unixerror(req,ERRDOS,ERRbadpath);
6225 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6226 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6227 reply_unixerror(req,ERRDOS,ERRbadpath);
6231 } else if (fsp->print_file) {
6233 * Doing a DELETE_ON_CLOSE should cancel a print job.
6235 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6236 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6238 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6241 send_trans2_replies(req, params, 2,
6246 reply_unixerror(req, ERRDOS, ERRbadpath);
6251 * Original code - this is an open file.
6253 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6257 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6258 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6259 reply_unixerror(req, ERRDOS, ERRbadfid);
6265 if (total_params < 7) {
6266 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6270 info_level = SVAL(params,0);
6271 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6272 total_params - 6, STR_TERMINATE,
6274 if (!NT_STATUS_IS_OK(status)) {
6275 reply_nterror(req, status);
6279 status = resolve_dfspath(ctx, conn,
6280 req->flags2 & FLAGS2_DFS_PATHNAMES,
6283 if (!NT_STATUS_IS_OK(status)) {
6284 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6285 reply_botherror(req,
6286 NT_STATUS_PATH_NOT_COVERED,
6287 ERRSRV, ERRbadpath);
6290 reply_nterror(req, status);
6294 status = unix_convert(ctx, conn, fname, False,
6295 &fname, NULL, &sbuf);
6296 if (!NT_STATUS_IS_OK(status)) {
6297 reply_nterror(req, status);
6301 status = check_name(conn, fname);
6302 if (!NT_STATUS_IS_OK(status)) {
6303 reply_nterror(req, status);
6307 if (INFO_LEVEL_IS_UNIX(info_level)) {
6309 * For CIFS UNIX extensions the target name may not exist.
6312 /* Always do lstat for UNIX calls. */
6313 SMB_VFS_LSTAT(conn,fname,&sbuf);
6315 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6316 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6317 reply_unixerror(req, ERRDOS, ERRbadpath);
6322 if (!CAN_WRITE(conn)) {
6323 reply_doserror(req, ERRSRV, ERRaccess);
6327 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6328 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6332 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6333 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6335 /* Realloc the parameter size */
6336 *pparams = (char *)SMB_REALLOC(*pparams,2);
6337 if (*pparams == NULL) {
6338 reply_nterror(req, NT_STATUS_NO_MEMORY);
6345 if (fsp && !null_timespec(fsp->pending_modtime)) {
6346 /* the pending modtime overrides the current modtime */
6347 set_mtimespec(&sbuf, fsp->pending_modtime);
6350 switch (info_level) {
6352 case SMB_INFO_STANDARD:
6354 status = smb_set_info_standard(conn,
6363 case SMB_INFO_SET_EA:
6365 status = smb_info_set_ea(conn,
6373 case SMB_SET_FILE_BASIC_INFO:
6374 case SMB_FILE_BASIC_INFORMATION:
6376 status = smb_set_file_basic_info(conn,
6385 case SMB_FILE_ALLOCATION_INFORMATION:
6386 case SMB_SET_FILE_ALLOCATION_INFO:
6388 status = smb_set_file_allocation_info(conn, req,
6397 case SMB_FILE_END_OF_FILE_INFORMATION:
6398 case SMB_SET_FILE_END_OF_FILE_INFO:
6400 status = smb_set_file_end_of_file_info(conn, req,
6409 case SMB_FILE_DISPOSITION_INFORMATION:
6410 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6413 /* JRA - We used to just ignore this on a path ?
6414 * Shouldn't this be invalid level on a pathname
6417 if (tran_call != TRANSACT2_SETFILEINFO) {
6418 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6421 status = smb_set_file_disposition_info(conn,
6430 case SMB_FILE_POSITION_INFORMATION:
6432 status = smb_file_position_information(conn,
6439 /* From tridge Samba4 :
6440 * MODE_INFORMATION in setfileinfo (I have no
6441 * idea what "mode information" on a file is - it takes a value of 0,
6442 * 2, 4 or 6. What could it be?).
6445 case SMB_FILE_MODE_INFORMATION:
6447 status = smb_file_mode_information(conn,
6454 * CIFS UNIX extensions.
6457 case SMB_SET_FILE_UNIX_BASIC:
6459 status = smb_set_file_unix_basic(conn, req,
6468 case SMB_SET_FILE_UNIX_INFO2:
6470 status = smb_set_file_unix_info2(conn, req,
6479 case SMB_SET_FILE_UNIX_LINK:
6481 if (tran_call != TRANSACT2_SETPATHINFO) {
6482 /* We must have a pathname for this. */
6483 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6486 status = smb_set_file_unix_link(conn, req, pdata,
6491 case SMB_SET_FILE_UNIX_HLINK:
6493 if (tran_call != TRANSACT2_SETPATHINFO) {
6494 /* We must have a pathname for this. */
6495 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6498 status = smb_set_file_unix_hlink(conn, req,
6504 case SMB_FILE_RENAME_INFORMATION:
6506 status = smb_file_rename_information(conn, req,
6512 #if defined(HAVE_POSIX_ACLS)
6513 case SMB_SET_POSIX_ACL:
6515 status = smb_set_posix_acl(conn,
6525 case SMB_SET_POSIX_LOCK:
6527 if (tran_call != TRANSACT2_SETFILEINFO) {
6528 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6531 status = smb_set_posix_lock(conn, req->inbuf,
6532 smb_len(req->inbuf) + 4,
6533 pdata, total_data, fsp);
6537 case SMB_POSIX_PATH_OPEN:
6539 if (tran_call != TRANSACT2_SETPATHINFO) {
6540 /* We must have a pathname for this. */
6541 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6545 status = smb_posix_open(conn, req,
6554 case SMB_POSIX_PATH_UNLINK:
6556 if (tran_call != TRANSACT2_SETPATHINFO) {
6557 /* We must have a pathname for this. */
6558 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6562 status = smb_posix_unlink(conn, req,
6571 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6576 if (!NT_STATUS_IS_OK(status)) {
6577 if (open_was_deferred(req->mid)) {
6578 /* We have re-scheduled this call. */
6581 if (blocking_lock_was_deferred(req->mid)) {
6582 /* We have re-scheduled this call. */
6585 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6586 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6587 ERRSRV, ERRbadpath);
6590 if (info_level == SMB_POSIX_PATH_OPEN) {
6591 reply_openerror(req, status);
6595 reply_nterror(req, status);
6600 send_trans2_replies(req, params, 2, *ppdata, data_return_size,
6606 /****************************************************************************
6607 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6608 ****************************************************************************/
6610 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6611 char **pparams, int total_params,
6612 char **ppdata, int total_data,
6613 unsigned int max_data_bytes)
6615 char *params = *pparams;
6616 char *pdata = *ppdata;
6617 char *directory = NULL;
6618 SMB_STRUCT_STAT sbuf;
6619 NTSTATUS status = NT_STATUS_OK;
6620 struct ea_list *ea_list = NULL;
6621 TALLOC_CTX *ctx = talloc_tos();
6623 if (!CAN_WRITE(conn)) {
6624 reply_doserror(req, ERRSRV, ERRaccess);
6628 if (total_params < 5) {
6629 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6633 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
6634 total_params - 4, STR_TERMINATE,
6636 if (!NT_STATUS_IS_OK(status)) {
6637 reply_nterror(req, status);
6641 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6643 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6644 if (!NT_STATUS_IS_OK(status)) {
6645 reply_nterror(req, status);
6649 status = check_name(conn, directory);
6650 if (!NT_STATUS_IS_OK(status)) {
6651 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6652 reply_nterror(req, status);
6656 /* Any data in this call is an EA list. */
6657 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6658 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6663 * OS/2 workplace shell seems to send SET_EA requests of "null"
6664 * length (4 bytes containing IVAL 4).
6665 * They seem to have no effect. Bug #3212. JRA.
6668 if (total_data != 4) {
6669 if (total_data < 10) {
6670 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6674 if (IVAL(pdata,0) > total_data) {
6675 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6676 IVAL(pdata,0), (unsigned int)total_data));
6677 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6681 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6684 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6687 } else if (IVAL(pdata,0) != 4) {
6688 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6692 status = create_directory(conn, directory);
6694 if (!NT_STATUS_IS_OK(status)) {
6695 reply_nterror(req, status);
6699 /* Try and set any given EA. */
6701 status = set_ea(conn, NULL, directory, ea_list);
6702 if (!NT_STATUS_IS_OK(status)) {
6703 reply_nterror(req, status);
6708 /* Realloc the parameter and data sizes */
6709 *pparams = (char *)SMB_REALLOC(*pparams,2);
6710 if(*pparams == NULL) {
6711 reply_nterror(req, NT_STATUS_NO_MEMORY);
6718 send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
6723 /****************************************************************************
6724 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6725 We don't actually do this - we just send a null response.
6726 ****************************************************************************/
6728 static void call_trans2findnotifyfirst(connection_struct *conn,
6729 struct smb_request *req,
6730 char **pparams, int total_params,
6731 char **ppdata, int total_data,
6732 unsigned int max_data_bytes)
6734 static uint16 fnf_handle = 257;
6735 char *params = *pparams;
6738 if (total_params < 6) {
6739 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6743 info_level = SVAL(params,4);
6744 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6746 switch (info_level) {
6751 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6755 /* Realloc the parameter and data sizes */
6756 *pparams = (char *)SMB_REALLOC(*pparams,6);
6757 if (*pparams == NULL) {
6758 reply_nterror(req, NT_STATUS_NO_MEMORY);
6763 SSVAL(params,0,fnf_handle);
6764 SSVAL(params,2,0); /* No changes */
6765 SSVAL(params,4,0); /* No EA errors */
6772 send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
6777 /****************************************************************************
6778 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6779 changes). Currently this does nothing.
6780 ****************************************************************************/
6782 static void call_trans2findnotifynext(connection_struct *conn,
6783 struct smb_request *req,
6784 char **pparams, int total_params,
6785 char **ppdata, int total_data,
6786 unsigned int max_data_bytes)
6788 char *params = *pparams;
6790 DEBUG(3,("call_trans2findnotifynext\n"));
6792 /* Realloc the parameter and data sizes */
6793 *pparams = (char *)SMB_REALLOC(*pparams,4);
6794 if (*pparams == NULL) {
6795 reply_nterror(req, NT_STATUS_NO_MEMORY);
6800 SSVAL(params,0,0); /* No changes */
6801 SSVAL(params,2,0); /* No EA errors */
6803 send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes);
6808 /****************************************************************************
6809 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6810 ****************************************************************************/
6812 static void call_trans2getdfsreferral(connection_struct *conn,
6813 struct smb_request *req,
6814 char **pparams, int total_params,
6815 char **ppdata, int total_data,
6816 unsigned int max_data_bytes)
6818 char *params = *pparams;
6819 char *pathname = NULL;
6821 int max_referral_level;
6822 NTSTATUS status = NT_STATUS_OK;
6823 TALLOC_CTX *ctx = talloc_tos();
6825 DEBUG(10,("call_trans2getdfsreferral\n"));
6827 if (total_params < 3) {
6828 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6832 max_referral_level = SVAL(params,0);
6834 if(!lp_host_msdfs()) {
6835 reply_doserror(req, ERRDOS, ERRbadfunc);
6839 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
6840 total_params - 2, STR_TERMINATE);
6842 reply_nterror(req, NT_STATUS_NOT_FOUND);
6845 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6846 ppdata,&status)) < 0) {
6847 reply_nterror(req, status);
6851 SSVAL(req->inbuf, smb_flg2,
6852 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6853 send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes);
6858 #define LMCAT_SPL 0x53
6859 #define LMFUNC_GETJOBID 0x60
6861 /****************************************************************************
6862 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6863 ****************************************************************************/
6865 static void call_trans2ioctl(connection_struct *conn,
6866 struct smb_request *req,
6867 char **pparams, int total_params,
6868 char **ppdata, int total_data,
6869 unsigned int max_data_bytes)
6871 char *pdata = *ppdata;
6872 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6874 /* check for an invalid fid before proceeding */
6877 reply_doserror(req, ERRDOS, ERRbadfid);
6881 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6882 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6883 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6884 if (*ppdata == NULL) {
6885 reply_nterror(req, NT_STATUS_NO_MEMORY);
6890 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6891 CAN ACCEPT THIS IN UNICODE. JRA. */
6893 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6894 srvstr_push(pdata, req->flags2, pdata + 2,
6895 global_myname(), 15,
6896 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6897 srvstr_push(pdata, req->flags2, pdata+18,
6898 lp_servicename(SNUM(conn)), 13,
6899 STR_ASCII|STR_TERMINATE); /* Service name */
6900 send_trans2_replies(req, *pparams, 0, *ppdata, 32,
6905 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6906 reply_doserror(req, ERRSRV, ERRerror);
6909 /****************************************************************************
6910 Reply to a SMBfindclose (stop trans2 directory search).
6911 ****************************************************************************/
6913 void reply_findclose(connection_struct *conn, struct smb_request *req)
6917 START_PROFILE(SMBfindclose);
6920 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6921 END_PROFILE(SMBfindclose);
6925 dptr_num = SVALS(req->inbuf,smb_vwv0);
6927 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6929 dptr_close(&dptr_num);
6931 reply_outbuf(req, 0, 0);
6933 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6935 END_PROFILE(SMBfindclose);
6939 /****************************************************************************
6940 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6941 ****************************************************************************/
6943 void reply_findnclose(connection_struct *conn, struct smb_request *req)
6947 START_PROFILE(SMBfindnclose);
6950 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6951 END_PROFILE(SMBfindnclose);
6955 dptr_num = SVAL(req->inbuf,smb_vwv0);
6957 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6959 /* We never give out valid handles for a
6960 findnotifyfirst - so any dptr_num is ok here.
6963 reply_outbuf(req, 0, 0);
6965 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6967 END_PROFILE(SMBfindnclose);
6971 static void handle_trans2(connection_struct *conn, struct smb_request *req,
6972 struct trans_state *state)
6974 if (Protocol >= PROTOCOL_NT1) {
6975 req->flags2 |= 0x40; /* IS_LONG_NAME */
6976 SSVAL(req->inbuf,smb_flg2,req->flags2);
6979 /* Now we must call the relevant TRANS2 function */
6980 switch(state->call) {
6981 case TRANSACT2_OPEN:
6983 START_PROFILE(Trans2_open);
6984 call_trans2open(conn, req,
6985 &state->param, state->total_param,
6986 &state->data, state->total_data,
6987 state->max_data_return);
6988 END_PROFILE(Trans2_open);
6992 case TRANSACT2_FINDFIRST:
6994 START_PROFILE(Trans2_findfirst);
6995 call_trans2findfirst(conn, req,
6996 &state->param, state->total_param,
6997 &state->data, state->total_data,
6998 state->max_data_return);
6999 END_PROFILE(Trans2_findfirst);
7003 case TRANSACT2_FINDNEXT:
7005 START_PROFILE(Trans2_findnext);
7006 call_trans2findnext(conn, req,
7007 &state->param, state->total_param,
7008 &state->data, state->total_data,
7009 state->max_data_return);
7010 END_PROFILE(Trans2_findnext);
7014 case TRANSACT2_QFSINFO:
7016 START_PROFILE(Trans2_qfsinfo);
7017 call_trans2qfsinfo(conn, req,
7018 &state->param, state->total_param,
7019 &state->data, state->total_data,
7020 state->max_data_return);
7021 END_PROFILE(Trans2_qfsinfo);
7025 case TRANSACT2_SETFSINFO:
7027 START_PROFILE(Trans2_setfsinfo);
7028 call_trans2setfsinfo(conn, req,
7029 &state->param, state->total_param,
7030 &state->data, state->total_data,
7031 state->max_data_return);
7032 END_PROFILE(Trans2_setfsinfo);
7036 case TRANSACT2_QPATHINFO:
7037 case TRANSACT2_QFILEINFO:
7039 START_PROFILE(Trans2_qpathinfo);
7040 call_trans2qfilepathinfo(conn, req, state->call,
7041 &state->param, state->total_param,
7042 &state->data, state->total_data,
7043 state->max_data_return);
7044 END_PROFILE(Trans2_qpathinfo);
7048 case TRANSACT2_SETPATHINFO:
7049 case TRANSACT2_SETFILEINFO:
7051 START_PROFILE(Trans2_setpathinfo);
7052 call_trans2setfilepathinfo(conn, req, state->call,
7053 &state->param, state->total_param,
7054 &state->data, state->total_data,
7055 state->max_data_return);
7056 END_PROFILE(Trans2_setpathinfo);
7060 case TRANSACT2_FINDNOTIFYFIRST:
7062 START_PROFILE(Trans2_findnotifyfirst);
7063 call_trans2findnotifyfirst(conn, req,
7064 &state->param, state->total_param,
7065 &state->data, state->total_data,
7066 state->max_data_return);
7067 END_PROFILE(Trans2_findnotifyfirst);
7071 case TRANSACT2_FINDNOTIFYNEXT:
7073 START_PROFILE(Trans2_findnotifynext);
7074 call_trans2findnotifynext(conn, req,
7075 &state->param, state->total_param,
7076 &state->data, state->total_data,
7077 state->max_data_return);
7078 END_PROFILE(Trans2_findnotifynext);
7082 case TRANSACT2_MKDIR:
7084 START_PROFILE(Trans2_mkdir);
7085 call_trans2mkdir(conn, req,
7086 &state->param, state->total_param,
7087 &state->data, state->total_data,
7088 state->max_data_return);
7089 END_PROFILE(Trans2_mkdir);
7093 case TRANSACT2_GET_DFS_REFERRAL:
7095 START_PROFILE(Trans2_get_dfs_referral);
7096 call_trans2getdfsreferral(conn, req,
7097 &state->param, state->total_param,
7098 &state->data, state->total_data,
7099 state->max_data_return);
7100 END_PROFILE(Trans2_get_dfs_referral);
7104 case TRANSACT2_IOCTL:
7106 START_PROFILE(Trans2_ioctl);
7107 call_trans2ioctl(conn, req,
7108 &state->param, state->total_param,
7109 &state->data, state->total_data,
7110 state->max_data_return);
7111 END_PROFILE(Trans2_ioctl);
7116 /* Error in request */
7117 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7118 reply_doserror(req, ERRSRV,ERRerror);
7122 /****************************************************************************
7123 Reply to a SMBtrans2.
7124 ****************************************************************************/
7126 void reply_trans2(connection_struct *conn, struct smb_request *req)
7132 unsigned int tran_call;
7134 struct trans_state *state;
7137 START_PROFILE(SMBtrans2);
7139 if (req->wct < 14) {
7140 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7141 END_PROFILE(SMBtrans2);
7145 dsoff = SVAL(req->inbuf, smb_dsoff);
7146 dscnt = SVAL(req->inbuf, smb_dscnt);
7147 psoff = SVAL(req->inbuf, smb_psoff);
7148 pscnt = SVAL(req->inbuf, smb_pscnt);
7149 tran_call = SVAL(req->inbuf, smb_setup0);
7150 size = smb_len(req->inbuf) + 4;
7152 result = allow_new_trans(conn->pending_trans, req->mid);
7153 if (!NT_STATUS_IS_OK(result)) {
7154 DEBUG(2, ("Got invalid trans2 request: %s\n",
7155 nt_errstr(result)));
7156 reply_nterror(req, result);
7157 END_PROFILE(SMBtrans2);
7161 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
7162 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
7163 && (tran_call != TRANSACT2_QFILEINFO)) {
7164 reply_doserror(req, ERRSRV, ERRaccess);
7165 END_PROFILE(SMBtrans2);
7169 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7170 DEBUG(0, ("talloc failed\n"));
7171 reply_nterror(req, NT_STATUS_NO_MEMORY);
7172 END_PROFILE(SMBtrans2);
7176 state->cmd = SMBtrans2;
7178 state->mid = req->mid;
7179 state->vuid = req->vuid;
7180 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7181 state->setup = NULL;
7182 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7183 state->param = NULL;
7184 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7186 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7187 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7188 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7189 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7190 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7192 state->call = tran_call;
7194 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7195 is so as a sanity check */
7196 if (state->setup_count != 1) {
7198 * Need to have rc=0 for ioctl to get job id for OS/2.
7199 * Network printing will fail if function is not successful.
7200 * Similar function in reply.c will be used if protocol
7201 * is LANMAN1.0 instead of LM1.2X002.
7202 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7203 * outbuf doesn't have to be set(only job id is used).
7205 if ( (state->setup_count == 4)
7206 && (tran_call == TRANSACT2_IOCTL)
7207 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7208 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7209 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7211 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7212 DEBUG(2,("Transaction is %d\n",tran_call));
7214 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7215 END_PROFILE(SMBtrans2);
7220 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7223 if (state->total_data) {
7224 /* Can't use talloc here, the core routines do realloc on the
7225 * params and data. */
7226 state->data = (char *)SMB_MALLOC(state->total_data);
7227 if (state->data == NULL) {
7228 DEBUG(0,("reply_trans2: data malloc fail for %u "
7229 "bytes !\n", (unsigned int)state->total_data));
7231 reply_nterror(req, NT_STATUS_NO_MEMORY);
7232 END_PROFILE(SMBtrans2);
7235 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7237 if ((smb_base(req->inbuf)+dsoff+dscnt
7238 > (char *)req->inbuf + size) ||
7239 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7242 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7245 if (state->total_param) {
7246 /* Can't use talloc here, the core routines do realloc on the
7247 * params and data. */
7248 state->param = (char *)SMB_MALLOC(state->total_param);
7249 if (state->param == NULL) {
7250 DEBUG(0,("reply_trans: param malloc fail for %u "
7251 "bytes !\n", (unsigned int)state->total_param));
7252 SAFE_FREE(state->data);
7254 reply_nterror(req, NT_STATUS_NO_MEMORY);
7255 END_PROFILE(SMBtrans2);
7258 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7260 if ((smb_base(req->inbuf)+psoff+pscnt
7261 > (char *)req->inbuf + size) ||
7262 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7265 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7268 state->received_data = dscnt;
7269 state->received_param = pscnt;
7271 if ((state->received_param == state->total_param) &&
7272 (state->received_data == state->total_data)) {
7274 handle_trans2(conn, req, state);
7276 SAFE_FREE(state->data);
7277 SAFE_FREE(state->param);
7279 END_PROFILE(SMBtrans2);
7283 DLIST_ADD(conn->pending_trans, state);
7285 /* We need to send an interim response then receive the rest
7286 of the parameter/data bytes */
7287 reply_outbuf(req, 0, 0);
7288 show_msg((char *)req->outbuf);
7289 END_PROFILE(SMBtrans2);
7294 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7295 SAFE_FREE(state->data);
7296 SAFE_FREE(state->param);
7298 END_PROFILE(SMBtrans2);
7299 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7303 /****************************************************************************
7304 Reply to a SMBtranss2
7305 ****************************************************************************/
7307 void reply_transs2(connection_struct *conn, struct smb_request *req)
7309 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7310 struct trans_state *state;
7313 START_PROFILE(SMBtranss2);
7315 show_msg((char *)req->inbuf);
7318 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7319 END_PROFILE(SMBtranss2);
7323 size = smb_len(req->inbuf)+4;
7325 for (state = conn->pending_trans; state != NULL;
7326 state = state->next) {
7327 if (state->mid == req->mid) {
7332 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7333 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7334 END_PROFILE(SMBtranss2);
7338 /* Revise state->total_param and state->total_data in case they have
7339 changed downwards */
7341 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7342 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7343 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7344 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7346 pcnt = SVAL(req->inbuf, smb_spscnt);
7347 poff = SVAL(req->inbuf, smb_spsoff);
7348 pdisp = SVAL(req->inbuf, smb_spsdisp);
7350 dcnt = SVAL(req->inbuf, smb_sdscnt);
7351 doff = SVAL(req->inbuf, smb_sdsoff);
7352 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7354 state->received_param += pcnt;
7355 state->received_data += dcnt;
7357 if ((state->received_data > state->total_data) ||
7358 (state->received_param > state->total_param))
7362 if (pdisp+pcnt > state->total_param)
7364 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7366 if (pdisp > state->total_param)
7368 if ((smb_base(req->inbuf) + poff + pcnt
7369 > (char *)req->inbuf + size) ||
7370 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7372 if (state->param + pdisp < state->param)
7375 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7380 if (ddisp+dcnt > state->total_data)
7382 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7384 if (ddisp > state->total_data)
7386 if ((smb_base(req->inbuf) + doff + dcnt
7387 > (char *)req->inbuf + size) ||
7388 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7390 if (state->data + ddisp < state->data)
7393 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7397 if ((state->received_param < state->total_param) ||
7398 (state->received_data < state->total_data)) {
7399 END_PROFILE(SMBtranss2);
7404 * construct_reply_common will copy smb_com from inbuf to
7405 * outbuf. SMBtranss2 is wrong here.
7407 SCVAL(req->inbuf,smb_com,SMBtrans2);
7409 handle_trans2(conn, req, state);
7411 DLIST_REMOVE(conn->pending_trans, state);
7412 SAFE_FREE(state->data);
7413 SAFE_FREE(state->param);
7416 END_PROFILE(SMBtranss2);
7421 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7422 DLIST_REMOVE(conn->pending_trans, state);
7423 SAFE_FREE(state->data);
7424 SAFE_FREE(state->param);
7426 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7427 END_PROFILE(SMBtranss2);