2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 extern enum protocol_types Protocol;
30 extern uint32 global_client_caps;
31 extern struct current_user current_user;
33 #define get_file_size(sbuf) ((sbuf).st_size)
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
36 static char *store_file_unix_basic(connection_struct *conn,
39 const SMB_STRUCT_STAT *psbuf);
41 static char *store_file_unix_basic_info2(connection_struct *conn,
44 const SMB_STRUCT_STAT *psbuf);
46 /********************************************************************
47 Roundup a value to the nearest allocation roundup size boundary.
48 Only do this for Windows clients.
49 ********************************************************************/
51 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
53 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
55 /* Only roundup for Windows clients. */
56 enum remote_arch_types ra_type = get_remote_arch();
57 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
58 val = SMB_ROUNDUP(val,rval);
63 /********************************************************************
64 Given a stat buffer return the allocated size on disk, taking into
66 ********************************************************************/
68 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
72 if(S_ISDIR(sbuf->st_mode)) {
76 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
77 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
79 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
82 if (fsp && fsp->initial_allocation_size)
83 ret = MAX(ret,fsp->initial_allocation_size);
85 return smb_roundup(conn, ret);
88 /****************************************************************************
89 Utility functions for dealing with extended attributes.
90 ****************************************************************************/
92 /****************************************************************************
93 Refuse to allow clients to overwrite our private xattrs.
94 ****************************************************************************/
96 static bool samba_private_attr_name(const char *unix_ea_name)
98 static const char *prohibited_ea_names[] = {
99 SAMBA_POSIX_INHERITANCE_EA_NAME,
100 SAMBA_XATTR_DOS_ATTRIB,
106 for (i = 0; prohibited_ea_names[i]; i++) {
107 if (strequal( prohibited_ea_names[i], unix_ea_name))
113 /****************************************************************************
114 Get one EA value. Fill in a struct ea_struct.
115 ****************************************************************************/
117 static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
118 const char *fname, char *ea_name, struct ea_struct *pea)
120 /* Get the value of this xattr. Max size is 64k. */
121 size_t attr_size = 256;
127 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
132 if (fsp && fsp->fh->fd != -1) {
133 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
135 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
138 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
147 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
148 dump_data(10, (uint8 *)val, sizeret);
151 if (strnequal(ea_name, "user.", 5)) {
152 pea->name = &ea_name[5];
156 pea->value.data = (unsigned char *)val;
157 pea->value.length = (size_t)sizeret;
161 /****************************************************************************
162 Return a linked list of the total EA's. Plus the total size
163 ****************************************************************************/
165 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
166 const char *fname, size_t *pea_total_len)
168 /* Get a list of all xattrs. Max namesize is 64k. */
169 size_t ea_namelist_size = 1024;
174 struct ea_list *ea_list_head = NULL;
178 if (!lp_ea_support(SNUM(conn))) {
182 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
183 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
189 if (fsp && fsp->fh->fd != -1) {
190 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
192 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
195 if (sizeret == -1 && errno == ERANGE) {
196 ea_namelist_size *= 2;
205 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
208 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
209 struct ea_list *listp;
211 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
214 listp = TALLOC_P(mem_ctx, struct ea_list);
218 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
224 push_ascii_fstring(dos_ea_name, listp->ea.name);
225 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
226 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
227 (unsigned int)*pea_total_len, dos_ea_name,
228 (unsigned int)listp->ea.value.length ));
230 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
232 /* Add on 4 for total length. */
233 if (*pea_total_len) {
238 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
242 /****************************************************************************
243 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
245 ****************************************************************************/
247 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
248 connection_struct *conn, struct ea_list *ea_list)
250 unsigned int ret_data_size = 4;
253 SMB_ASSERT(total_data_size >= 4);
255 if (!lp_ea_support(SNUM(conn))) {
260 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
263 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
264 dos_namelen = strlen(dos_ea_name);
265 if (dos_namelen > 255 || dos_namelen == 0) {
268 if (ea_list->ea.value.length > 65535) {
271 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
275 /* We know we have room. */
276 SCVAL(p,0,ea_list->ea.flags);
277 SCVAL(p,1,dos_namelen);
278 SSVAL(p,2,ea_list->ea.value.length);
279 fstrcpy(p+4, dos_ea_name);
280 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
282 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
283 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
286 ret_data_size = PTR_DIFF(p, pdata);
287 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
288 SIVAL(pdata,0,ret_data_size);
289 return ret_data_size;
292 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
294 size_t total_ea_len = 0;
295 TALLOC_CTX *mem_ctx = NULL;
297 if (!lp_ea_support(SNUM(conn))) {
300 mem_ctx = talloc_init("estimate_ea_size");
301 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
302 talloc_destroy(mem_ctx);
306 /****************************************************************************
307 Ensure the EA name is case insensitive by matching any existing EA name.
308 ****************************************************************************/
310 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
313 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
314 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
316 for (; ea_list; ea_list = ea_list->next) {
317 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
318 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
319 &unix_ea_name[5], ea_list->ea.name));
320 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
324 talloc_destroy(mem_ctx);
327 /****************************************************************************
328 Set or delete an extended attribute.
329 ****************************************************************************/
331 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
333 if (!lp_ea_support(SNUM(conn))) {
334 return NT_STATUS_EAS_NOT_SUPPORTED;
337 for (;ea_list; ea_list = ea_list->next) {
339 fstring unix_ea_name;
341 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
342 fstrcat(unix_ea_name, ea_list->ea.name);
344 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
346 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
348 if (samba_private_attr_name(unix_ea_name)) {
349 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
350 return NT_STATUS_ACCESS_DENIED;
353 if (ea_list->ea.value.length == 0) {
354 /* Remove the attribute. */
355 if (fsp && (fsp->fh->fd != -1)) {
356 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
357 unix_ea_name, fsp->fsp_name));
358 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
360 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
361 unix_ea_name, fname));
362 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
365 /* Removing a non existent attribute always succeeds. */
366 if (ret == -1 && errno == ENOATTR) {
367 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
373 if (fsp && (fsp->fh->fd != -1)) {
374 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
375 unix_ea_name, fsp->fsp_name));
376 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
377 ea_list->ea.value.data, ea_list->ea.value.length, 0);
379 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
380 unix_ea_name, fname));
381 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
382 ea_list->ea.value.data, ea_list->ea.value.length, 0);
388 if (errno == ENOTSUP) {
389 return NT_STATUS_EAS_NOT_SUPPORTED;
392 return map_nt_error_from_unix(errno);
398 /****************************************************************************
399 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
400 ****************************************************************************/
402 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
404 struct ea_list *ea_list_head = NULL;
407 while (offset + 2 < data_size) {
408 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
409 unsigned int namelen = CVAL(pdata,offset);
411 offset++; /* Go past the namelen byte. */
413 /* integer wrap paranioa. */
414 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
415 (offset > data_size) || (namelen > data_size) ||
416 (offset + namelen >= data_size)) {
419 /* Ensure the name is null terminated. */
420 if (pdata[offset + namelen] != '\0') {
423 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
428 offset += (namelen + 1); /* Go past the name + terminating zero. */
429 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
430 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
436 /****************************************************************************
437 Read one EA list entry from the buffer.
438 ****************************************************************************/
440 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
442 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
444 unsigned int namelen;
454 eal->ea.flags = CVAL(pdata,0);
455 namelen = CVAL(pdata,1);
456 val_len = SVAL(pdata,2);
458 if (4 + namelen + 1 + val_len > data_size) {
462 /* Ensure the name is null terminated. */
463 if (pdata[namelen + 4] != '\0') {
466 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
471 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
472 if (!eal->ea.value.data) {
476 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
478 /* Ensure we're null terminated just in case we print the value. */
479 eal->ea.value.data[val_len] = '\0';
480 /* But don't count the null. */
481 eal->ea.value.length--;
484 *pbytes_used = 4 + namelen + 1 + val_len;
487 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
488 dump_data(10, eal->ea.value.data, eal->ea.value.length);
493 /****************************************************************************
494 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
495 ****************************************************************************/
497 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
499 struct ea_list *ea_list_head = NULL;
501 size_t bytes_used = 0;
503 while (offset < data_size) {
504 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
510 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
511 offset += bytes_used;
517 /****************************************************************************
518 Count the total EA size needed.
519 ****************************************************************************/
521 static size_t ea_list_size(struct ea_list *ealist)
524 struct ea_list *listp;
527 for (listp = ealist; listp; listp = listp->next) {
528 push_ascii_fstring(dos_ea_name, listp->ea.name);
529 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
531 /* Add on 4 for total length. */
539 /****************************************************************************
540 Return a union of EA's from a file list and a list of names.
541 The TALLOC context for the two lists *MUST* be identical as we steal
542 memory from one list to add to another. JRA.
543 ****************************************************************************/
545 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
547 struct ea_list *nlistp, *flistp;
549 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
550 for (flistp = file_list; flistp; flistp = flistp->next) {
551 if (strequal(nlistp->ea.name, flistp->ea.name)) {
557 /* Copy the data from this entry. */
558 nlistp->ea.flags = flistp->ea.flags;
559 nlistp->ea.value = flistp->ea.value;
562 nlistp->ea.flags = 0;
563 ZERO_STRUCT(nlistp->ea.value);
567 *total_ea_len = ea_list_size(name_list);
571 /****************************************************************************
572 Send the required number of replies back.
573 We assume all fields other than the data fields are
574 set correctly for the type of call.
575 HACK ! Always assumes smb_setup field is zero.
576 ****************************************************************************/
578 void send_trans2_replies(struct smb_request *req,
585 /* As we are using a protocol > LANMAN1 then the max_send
586 variable must have been set in the sessetupX call.
587 This takes precedence over the max_xmit field in the
588 global struct. These different max_xmit variables should
589 be merged as this is now too confusing */
591 int data_to_send = datasize;
592 int params_to_send = paramsize;
594 const char *pp = params;
595 const char *pd = pdata;
596 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
597 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
598 int data_alignment_offset = 0;
599 bool overflow = False;
601 /* Modify the data_to_send and datasize and set the error if
602 we're trying to send more than max_data_bytes. We still send
603 the part of the packet(s) that fit. Strange, but needed
606 if (max_data_bytes > 0 && datasize > max_data_bytes) {
607 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
608 max_data_bytes, datasize ));
609 datasize = data_to_send = max_data_bytes;
613 /* If there genuinely are no parameters or data to send just send the empty packet */
615 if(params_to_send == 0 && data_to_send == 0) {
616 reply_outbuf(req, 10, 0);
617 show_msg((char *)req->outbuf);
621 /* When sending params and data ensure that both are nicely aligned */
622 /* Only do this alignment when there is also data to send - else
623 can cause NT redirector problems. */
625 if (((params_to_send % 4) != 0) && (data_to_send != 0))
626 data_alignment_offset = 4 - (params_to_send % 4);
628 /* Space is bufsize minus Netbios over TCP header minus SMB header */
629 /* The alignment_offset is to align the param bytes on an even byte
630 boundary. NT 4.0 Beta needs this to work correctly. */
632 useable_space = max_send - (smb_size
635 + data_alignment_offset);
637 /* useable_space can never be more than max_send minus the alignment offset. */
639 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
641 while (params_to_send || data_to_send) {
642 /* Calculate whether we will totally or partially fill this packet */
644 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
646 /* We can never send more than useable_space */
648 * Note that 'useable_space' does not include the alignment offsets,
649 * but we must include the alignment offsets in the calculation of
650 * the length of the data we send over the wire, as the alignment offsets
651 * are sent here. Fix from Marc_Jacobsen@hp.com.
654 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
656 reply_outbuf(req, 10, total_sent_thistime);
658 /* Set total params and data to be sent */
659 SSVAL(req->outbuf,smb_tprcnt,paramsize);
660 SSVAL(req->outbuf,smb_tdrcnt,datasize);
662 /* Calculate how many parameters and data we can fit into
663 * this packet. Parameters get precedence
666 params_sent_thistime = MIN(params_to_send,useable_space);
667 data_sent_thistime = useable_space - params_sent_thistime;
668 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
670 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
672 /* smb_proff is the offset from the start of the SMB header to the
673 parameter bytes, however the first 4 bytes of outbuf are
674 the Netbios over TCP header. Thus use smb_base() to subtract
675 them from the calculation */
677 SSVAL(req->outbuf,smb_proff,
678 ((smb_buf(req->outbuf)+alignment_offset)
679 - smb_base(req->outbuf)));
681 if(params_sent_thistime == 0)
682 SSVAL(req->outbuf,smb_prdisp,0);
684 /* Absolute displacement of param bytes sent in this packet */
685 SSVAL(req->outbuf,smb_prdisp,pp - params);
687 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
688 if(data_sent_thistime == 0) {
689 SSVAL(req->outbuf,smb_droff,0);
690 SSVAL(req->outbuf,smb_drdisp, 0);
692 /* The offset of the data bytes is the offset of the
693 parameter bytes plus the number of parameters being sent this time */
694 SSVAL(req->outbuf, smb_droff,
695 ((smb_buf(req->outbuf)+alignment_offset)
696 - smb_base(req->outbuf))
697 + params_sent_thistime + data_alignment_offset);
698 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
701 /* Initialize the padding for alignment */
703 if (alignment_offset != 0) {
704 memset(smb_buf(req->outbuf), 0, alignment_offset);
707 /* Copy the param bytes into the packet */
709 if(params_sent_thistime) {
710 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
711 params_sent_thistime);
714 /* Copy in the data bytes */
715 if(data_sent_thistime) {
716 if (data_alignment_offset != 0) {
717 memset((smb_buf(req->outbuf)+alignment_offset+
718 params_sent_thistime), 0,
719 data_alignment_offset);
721 memcpy(smb_buf(req->outbuf)+alignment_offset
722 +params_sent_thistime+data_alignment_offset,
723 pd,data_sent_thistime);
726 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
727 params_sent_thistime, data_sent_thistime, useable_space));
728 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
729 params_to_send, data_to_send, paramsize, datasize));
732 error_packet_set((char *)req->outbuf,
733 ERRDOS,ERRbufferoverflow,
734 STATUS_BUFFER_OVERFLOW,
738 /* Send the packet */
739 show_msg((char *)req->outbuf);
740 if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
741 exit_server_cleanly("send_trans2_replies: send_smb failed.");
743 TALLOC_FREE(req->outbuf);
745 pp += params_sent_thistime;
746 pd += data_sent_thistime;
748 params_to_send -= params_sent_thistime;
749 data_to_send -= data_sent_thistime;
752 if(params_to_send < 0 || data_to_send < 0) {
753 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
754 params_to_send, data_to_send));
762 /****************************************************************************
763 Reply to a TRANSACT2_OPEN.
764 ****************************************************************************/
766 static void call_trans2open(connection_struct *conn,
767 struct smb_request *req,
768 char **pparams, int total_params,
769 char **ppdata, int total_data,
770 unsigned int max_data_bytes)
772 char *params = *pparams;
773 char *pdata = *ppdata;
778 bool return_additional_info;
789 SMB_STRUCT_STAT sbuf;
792 struct ea_list *ea_list = NULL;
797 uint32 create_disposition;
798 uint32 create_options = 0;
799 TALLOC_CTX *ctx = talloc_tos();
802 * Ensure we have enough parameters to perform the operation.
805 if (total_params < 29) {
806 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
810 flags = SVAL(params, 0);
811 deny_mode = SVAL(params, 2);
812 open_attr = SVAL(params,6);
813 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
814 if (oplock_request) {
815 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
819 return_additional_info = BITSETW(params,0);
820 open_sattr = SVAL(params, 4);
821 open_time = make_unix_date3(params+8);
823 open_ofun = SVAL(params,12);
824 open_size = IVAL(params,14);
828 reply_doserror(req, ERRSRV, ERRaccess);
832 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
833 total_params - 28, STR_TERMINATE,
835 if (!NT_STATUS_IS_OK(status)) {
836 reply_nterror(req, status);
840 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
841 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
842 (unsigned int)open_ofun, open_size));
844 /* XXXX we need to handle passed times, sattr and flags */
846 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
847 if (!NT_STATUS_IS_OK(status)) {
848 reply_nterror(req, status);
852 status = check_name(conn, fname);
853 if (!NT_STATUS_IS_OK(status)) {
854 reply_nterror(req, status);
858 if (open_ofun == 0) {
859 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
863 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
868 reply_doserror(req, ERRDOS, ERRbadaccess);
872 /* Any data in this call is an EA list. */
873 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
874 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
878 if (total_data != 4) {
879 if (total_data < 10) {
880 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
884 if (IVAL(pdata,0) > total_data) {
885 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
886 IVAL(pdata,0), (unsigned int)total_data));
887 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
891 ea_list = read_ea_list(talloc_tos(), pdata + 4,
894 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
897 } else if (IVAL(pdata,0) != 4) {
898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
902 status = open_file_ntcreate(conn, req, fname, &sbuf,
911 if (!NT_STATUS_IS_OK(status)) {
912 if (open_was_deferred(req->mid)) {
913 /* We have re-scheduled this call. */
916 reply_openerror(req, status);
920 size = get_file_size(sbuf);
921 fattr = dos_mode(conn,fname,&sbuf);
922 mtime = sbuf.st_mtime;
925 close_file(fsp,ERROR_CLOSE);
926 reply_doserror(req, ERRDOS,ERRnoaccess);
930 /* Save the requested allocation size. */
931 /* Allocate space for the file if a size hint is supplied */
932 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
933 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
934 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
935 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
936 if (fsp->is_directory) {
937 close_file(fsp,ERROR_CLOSE);
938 /* Can't set allocation size on a directory. */
939 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
942 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
943 close_file(fsp,ERROR_CLOSE);
944 reply_nterror(req, NT_STATUS_DISK_FULL);
948 /* Adjust size here to return the right size in the reply.
949 Windows does it this way. */
950 size = fsp->initial_allocation_size;
952 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
956 if (ea_list && smb_action == FILE_WAS_CREATED) {
957 status = set_ea(conn, fsp, fname, ea_list);
958 if (!NT_STATUS_IS_OK(status)) {
959 close_file(fsp,ERROR_CLOSE);
960 reply_nterror(req, status);
965 /* Realloc the size of parameters and data we will return */
966 *pparams = (char *)SMB_REALLOC(*pparams, 30);
967 if(*pparams == NULL ) {
968 reply_nterror(req, NT_STATUS_NO_MEMORY);
973 SSVAL(params,0,fsp->fnum);
974 SSVAL(params,2,fattr);
975 srv_put_dos_date2(params,4, mtime);
976 SIVAL(params,8, (uint32)size);
977 SSVAL(params,12,deny_mode);
978 SSVAL(params,14,0); /* open_type - file or directory. */
979 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
981 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
982 smb_action |= EXTENDED_OPLOCK_GRANTED;
985 SSVAL(params,18,smb_action);
988 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
990 SIVAL(params,20,inode);
991 SSVAL(params,24,0); /* Padding. */
993 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
994 SIVAL(params, 26, ea_size);
996 SIVAL(params, 26, 0);
999 /* Send the required number of replies */
1000 send_trans2_replies(req, params, 30, *ppdata, 0, max_data_bytes);
1003 /*********************************************************
1004 Routine to check if a given string matches exactly.
1005 as a special case a mask of "." does NOT match. That
1006 is required for correct wildcard semantics
1007 Case can be significant or not.
1008 **********************************************************/
1010 static bool exact_match(connection_struct *conn,
1014 if (mask[0] == '.' && mask[1] == 0)
1016 if (conn->case_sensitive)
1017 return strcmp(str,mask)==0;
1018 if (StrCaseCmp(str,mask) != 0) {
1021 if (dptr_has_wild(conn->dirptr)) {
1027 /****************************************************************************
1028 Return the filetype for UNIX extensions.
1029 ****************************************************************************/
1031 static uint32 unix_filetype(mode_t mode)
1034 return UNIX_TYPE_FILE;
1035 else if(S_ISDIR(mode))
1036 return UNIX_TYPE_DIR;
1038 else if(S_ISLNK(mode))
1039 return UNIX_TYPE_SYMLINK;
1042 else if(S_ISCHR(mode))
1043 return UNIX_TYPE_CHARDEV;
1046 else if(S_ISBLK(mode))
1047 return UNIX_TYPE_BLKDEV;
1050 else if(S_ISFIFO(mode))
1051 return UNIX_TYPE_FIFO;
1054 else if(S_ISSOCK(mode))
1055 return UNIX_TYPE_SOCKET;
1058 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1059 return UNIX_TYPE_UNKNOWN;
1062 /****************************************************************************
1063 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1064 ****************************************************************************/
1066 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1068 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1069 SMB_STRUCT_STAT *psbuf,
1071 enum perm_type ptype,
1076 if (perms == SMB_MODE_NO_CHANGE) {
1077 if (!VALID_STAT(*psbuf)) {
1078 return NT_STATUS_INVALID_PARAMETER;
1080 *ret_perms = psbuf->st_mode;
1081 return NT_STATUS_OK;
1085 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1086 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1087 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1088 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1089 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1090 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1091 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1092 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1093 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1095 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1098 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1101 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1106 /* Apply mode mask */
1107 ret &= lp_create_mask(SNUM(conn));
1108 /* Add in force bits */
1109 ret |= lp_force_create_mode(SNUM(conn));
1112 ret &= lp_dir_mask(SNUM(conn));
1113 /* Add in force bits */
1114 ret |= lp_force_dir_mode(SNUM(conn));
1116 case PERM_EXISTING_FILE:
1117 /* Apply mode mask */
1118 ret &= lp_security_mask(SNUM(conn));
1119 /* Add in force bits */
1120 ret |= lp_force_security_mode(SNUM(conn));
1122 case PERM_EXISTING_DIR:
1123 /* Apply mode mask */
1124 ret &= lp_dir_security_mask(SNUM(conn));
1125 /* Add in force bits */
1126 ret |= lp_force_dir_security_mode(SNUM(conn));
1131 return NT_STATUS_OK;
1134 /****************************************************************************
1135 Get a level dependent lanman2 dir entry.
1136 ****************************************************************************/
1138 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1139 connection_struct *conn,
1141 const char *path_mask,
1144 int requires_resume_key,
1149 int space_remaining,
1151 bool *got_exact_match,
1152 int *last_entry_off,
1153 struct ea_list *name_list)
1157 SMB_STRUCT_STAT sbuf;
1158 const char *mask = NULL;
1159 char *pathreal = NULL;
1160 const char *fname = NULL;
1161 char *p, *q, *pdata = *ppdata;
1165 SMB_OFF_T file_size = 0;
1166 SMB_BIG_UINT allocation_size = 0;
1168 struct timespec mdate_ts, adate_ts, create_date_ts;
1169 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1171 char *last_entry_ptr;
1173 uint32 nt_extmode; /* Used for NT connections instead of mode */
1174 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1175 bool check_mangled_names = lp_manglednames(conn->params);
1176 char mangled_name[13]; /* mangled 8.3 name. */
1178 *out_of_space = False;
1179 *got_exact_match = False;
1181 ZERO_STRUCT(mdate_ts);
1182 ZERO_STRUCT(adate_ts);
1183 ZERO_STRUCT(create_date_ts);
1185 if (!conn->dirptr) {
1189 p = strrchr_m(path_mask,'/');
1192 mask = talloc_strdup(ctx,"*.*");
1202 bool ms_dfs_link = False;
1204 /* Needed if we run out of space */
1205 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1206 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1209 * Due to bugs in NT client redirectors we are not using
1210 * resume keys any more - set them to zero.
1211 * Check out the related comments in findfirst/findnext.
1217 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1218 (long)conn->dirptr,curr_dirpos));
1225 * fname may get mangled, dname is never mangled.
1226 * Whenever we're accessing the filesystem we use
1227 * pathreal which is composed from dname.
1233 /* Mangle fname if it's an illegal name. */
1234 if (mangle_must_mangle(dname,conn->params)) {
1235 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1236 continue; /* Error - couldn't mangle. */
1238 fname = mangled_name;
1241 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1242 got_match = mask_match(fname, mask, conn->case_sensitive);
1245 if(!got_match && check_mangled_names &&
1246 !mangle_is_8_3(fname, False, conn->params)) {
1248 * It turns out that NT matches wildcards against
1249 * both long *and* short names. This may explain some
1250 * of the wildcard wierdness from old DOS clients
1251 * that some people have been seeing.... JRA.
1253 /* Force the mangling into 8.3. */
1254 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1255 continue; /* Error - couldn't mangle. */
1258 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1259 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1264 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1266 if (dont_descend && !isdots) {
1272 pathreal = talloc_asprintf(ctx,
1277 pathreal = talloc_asprintf(ctx,
1287 if (INFO_LEVEL_IS_UNIX(info_level)) {
1288 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1289 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1290 pathreal,strerror(errno)));
1291 TALLOC_FREE(pathreal);
1294 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1295 /* Needed to show the msdfs symlinks as
1298 if(lp_host_msdfs() &&
1299 lp_msdfs_root(SNUM(conn)) &&
1300 ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) {
1301 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1304 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1308 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1309 pathreal,strerror(errno)));
1310 TALLOC_FREE(pathreal);
1316 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1318 mode = dos_mode(conn,pathreal,&sbuf);
1321 if (!dir_check_ftype(conn,mode,dirtype)) {
1322 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1323 TALLOC_FREE(pathreal);
1327 if (!(mode & aDIR)) {
1328 file_size = get_file_size(sbuf);
1330 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1332 mdate_ts = get_mtimespec(&sbuf);
1333 adate_ts = get_atimespec(&sbuf);
1334 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1336 if (lp_dos_filetime_resolution(SNUM(conn))) {
1337 dos_filetime_timespec(&create_date_ts);
1338 dos_filetime_timespec(&mdate_ts);
1339 dos_filetime_timespec(&adate_ts);
1342 create_date = convert_timespec_to_time_t(create_date_ts);
1343 mdate = convert_timespec_to_time_t(mdate_ts);
1344 adate = convert_timespec_to_time_t(adate_ts);
1346 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1350 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1357 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1359 switch (info_level) {
1360 case SMB_FIND_INFO_STANDARD:
1361 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1362 if(requires_resume_key) {
1366 srv_put_dos_date2(p,0,create_date);
1367 srv_put_dos_date2(p,4,adate);
1368 srv_put_dos_date2(p,8,mdate);
1369 SIVAL(p,12,(uint32)file_size);
1370 SIVAL(p,16,(uint32)allocation_size);
1374 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1375 p += ucs2_align(base_data, p, 0);
1377 len = srvstr_push(base_data, flags2, p,
1378 fname, PTR_DIFF(end_data, p),
1380 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1382 SCVAL(nameptr, -1, len - 2);
1384 SCVAL(nameptr, -1, 0);
1388 SCVAL(nameptr, -1, len - 1);
1390 SCVAL(nameptr, -1, 0);
1396 case SMB_FIND_EA_SIZE:
1397 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1398 if(requires_resume_key) {
1402 srv_put_dos_date2(p,0,create_date);
1403 srv_put_dos_date2(p,4,adate);
1404 srv_put_dos_date2(p,8,mdate);
1405 SIVAL(p,12,(uint32)file_size);
1406 SIVAL(p,16,(uint32)allocation_size);
1409 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1410 SIVAL(p,22,ea_size); /* Extended attributes */
1414 len = srvstr_push(base_data, flags2,
1415 p, fname, PTR_DIFF(end_data, p),
1416 STR_TERMINATE | STR_NOALIGN);
1417 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1430 SCVAL(nameptr,0,len);
1432 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1435 case SMB_FIND_EA_LIST:
1437 struct ea_list *file_list = NULL;
1440 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1444 if(requires_resume_key) {
1448 srv_put_dos_date2(p,0,create_date);
1449 srv_put_dos_date2(p,4,adate);
1450 srv_put_dos_date2(p,8,mdate);
1451 SIVAL(p,12,(uint32)file_size);
1452 SIVAL(p,16,(uint32)allocation_size);
1454 p += 22; /* p now points to the EA area. */
1456 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1457 name_list = ea_list_union(name_list, file_list, &ea_len);
1459 /* We need to determine if this entry will fit in the space available. */
1460 /* Max string size is 255 bytes. */
1461 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1462 /* Move the dirptr back to prev_dirpos */
1463 dptr_SeekDir(conn->dirptr, prev_dirpos);
1464 *out_of_space = True;
1465 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1466 return False; /* Not finished - just out of space */
1469 /* Push the ea_data followed by the name. */
1470 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1472 len = srvstr_push(base_data, flags2,
1473 p + 1, fname, PTR_DIFF(end_data, p+1),
1474 STR_TERMINATE | STR_NOALIGN);
1475 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1488 SCVAL(nameptr,0,len);
1490 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1494 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1495 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1496 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1498 SIVAL(p,0,reskey); p += 4;
1499 put_long_date_timespec(p,create_date_ts); p += 8;
1500 put_long_date_timespec(p,adate_ts); p += 8;
1501 put_long_date_timespec(p,mdate_ts); p += 8;
1502 put_long_date_timespec(p,mdate_ts); p += 8;
1503 SOFF_T(p,0,file_size); p += 8;
1504 SOFF_T(p,0,allocation_size); p += 8;
1505 SIVAL(p,0,nt_extmode); p += 4;
1506 q = p; p += 4; /* q is placeholder for name length. */
1508 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1509 SIVAL(p,0,ea_size); /* Extended attributes */
1512 /* Clear the short name buffer. This is
1513 * IMPORTANT as not doing so will trigger
1514 * a Win2k client bug. JRA.
1516 if (!was_8_3 && check_mangled_names) {
1517 if (!name_to_8_3(fname,mangled_name,True,
1519 /* Error - mangle failed ! */
1520 memset(mangled_name,'\0',12);
1522 mangled_name[12] = 0;
1523 len = srvstr_push(base_data, flags2,
1524 p+2, mangled_name, 24,
1525 STR_UPPER|STR_UNICODE);
1527 memset(p + 2 + len,'\0',24 - len);
1534 len = srvstr_push(base_data, flags2, p,
1535 fname, PTR_DIFF(end_data, p),
1536 STR_TERMINATE_ASCII);
1539 SIVAL(p,0,0); /* Ensure any padding is null. */
1540 len = PTR_DIFF(p, pdata);
1541 len = (len + 3) & ~3;
1546 case SMB_FIND_FILE_DIRECTORY_INFO:
1547 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1549 SIVAL(p,0,reskey); p += 4;
1550 put_long_date_timespec(p,create_date_ts); p += 8;
1551 put_long_date_timespec(p,adate_ts); p += 8;
1552 put_long_date_timespec(p,mdate_ts); p += 8;
1553 put_long_date_timespec(p,mdate_ts); p += 8;
1554 SOFF_T(p,0,file_size); p += 8;
1555 SOFF_T(p,0,allocation_size); p += 8;
1556 SIVAL(p,0,nt_extmode); p += 4;
1557 len = srvstr_push(base_data, flags2,
1558 p + 4, fname, PTR_DIFF(end_data, p+4),
1559 STR_TERMINATE_ASCII);
1562 SIVAL(p,0,0); /* Ensure any padding is null. */
1563 len = PTR_DIFF(p, pdata);
1564 len = (len + 3) & ~3;
1569 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1570 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1572 SIVAL(p,0,reskey); p += 4;
1573 put_long_date_timespec(p,create_date_ts); p += 8;
1574 put_long_date_timespec(p,adate_ts); p += 8;
1575 put_long_date_timespec(p,mdate_ts); p += 8;
1576 put_long_date_timespec(p,mdate_ts); p += 8;
1577 SOFF_T(p,0,file_size); p += 8;
1578 SOFF_T(p,0,allocation_size); p += 8;
1579 SIVAL(p,0,nt_extmode); p += 4;
1580 q = p; p += 4; /* q is placeholder for name length. */
1582 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1583 SIVAL(p,0,ea_size); /* Extended attributes */
1586 len = srvstr_push(base_data, flags2, p,
1587 fname, PTR_DIFF(end_data, p),
1588 STR_TERMINATE_ASCII);
1592 SIVAL(p,0,0); /* Ensure any padding is null. */
1593 len = PTR_DIFF(p, pdata);
1594 len = (len + 3) & ~3;
1599 case SMB_FIND_FILE_NAMES_INFO:
1600 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1602 SIVAL(p,0,reskey); p += 4;
1604 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1605 acl on a dir (tridge) */
1606 len = srvstr_push(base_data, flags2, p,
1607 fname, PTR_DIFF(end_data, p),
1608 STR_TERMINATE_ASCII);
1611 SIVAL(p,0,0); /* Ensure any padding is null. */
1612 len = PTR_DIFF(p, pdata);
1613 len = (len + 3) & ~3;
1618 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1619 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1621 SIVAL(p,0,reskey); p += 4;
1622 put_long_date_timespec(p,create_date_ts); p += 8;
1623 put_long_date_timespec(p,adate_ts); p += 8;
1624 put_long_date_timespec(p,mdate_ts); p += 8;
1625 put_long_date_timespec(p,mdate_ts); p += 8;
1626 SOFF_T(p,0,file_size); p += 8;
1627 SOFF_T(p,0,allocation_size); p += 8;
1628 SIVAL(p,0,nt_extmode); p += 4;
1629 q = p; p += 4; /* q is placeholder for name length. */
1631 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1632 SIVAL(p,0,ea_size); /* Extended attributes */
1635 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1636 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1637 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1638 len = srvstr_push(base_data, flags2, p,
1639 fname, PTR_DIFF(end_data, p),
1640 STR_TERMINATE_ASCII);
1643 SIVAL(p,0,0); /* Ensure any padding is null. */
1644 len = PTR_DIFF(p, pdata);
1645 len = (len + 3) & ~3;
1650 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1651 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1652 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1654 SIVAL(p,0,reskey); p += 4;
1655 put_long_date_timespec(p,create_date_ts); p += 8;
1656 put_long_date_timespec(p,adate_ts); p += 8;
1657 put_long_date_timespec(p,mdate_ts); p += 8;
1658 put_long_date_timespec(p,mdate_ts); p += 8;
1659 SOFF_T(p,0,file_size); p += 8;
1660 SOFF_T(p,0,allocation_size); p += 8;
1661 SIVAL(p,0,nt_extmode); p += 4;
1662 q = p; p += 4; /* q is placeholder for name length */
1664 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1665 SIVAL(p,0,ea_size); /* Extended attributes */
1668 /* Clear the short name buffer. This is
1669 * IMPORTANT as not doing so will trigger
1670 * a Win2k client bug. JRA.
1672 if (!was_8_3 && check_mangled_names) {
1673 if (!name_to_8_3(fname,mangled_name,True,
1675 /* Error - mangle failed ! */
1676 memset(mangled_name,'\0',12);
1678 mangled_name[12] = 0;
1679 len = srvstr_push(base_data, flags2,
1680 p+2, mangled_name, 24,
1681 STR_UPPER|STR_UNICODE);
1684 memset(p + 2 + len,'\0',24 - len);
1691 SSVAL(p,0,0); p += 2; /* Reserved ? */
1692 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1693 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1694 len = srvstr_push(base_data, flags2, p,
1695 fname, PTR_DIFF(end_data, p),
1696 STR_TERMINATE_ASCII);
1699 SIVAL(p,0,0); /* Ensure any padding is null. */
1700 len = PTR_DIFF(p, pdata);
1701 len = (len + 3) & ~3;
1706 /* CIFS UNIX Extension. */
1708 case SMB_FIND_FILE_UNIX:
1709 case SMB_FIND_FILE_UNIX_INFO2:
1711 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1713 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1715 if (info_level == SMB_FIND_FILE_UNIX) {
1716 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1717 p = store_file_unix_basic(conn, p,
1719 len = srvstr_push(base_data, flags2, p,
1720 fname, PTR_DIFF(end_data, p),
1723 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1724 p = store_file_unix_basic_info2(conn, p,
1728 len = srvstr_push(base_data, flags2, p, fname,
1729 PTR_DIFF(end_data, p), 0);
1730 SIVAL(nameptr, 0, len);
1734 SIVAL(p,0,0); /* Ensure any padding is null. */
1736 len = PTR_DIFF(p, pdata);
1737 len = (len + 3) & ~3;
1738 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1740 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1749 if (PTR_DIFF(p,pdata) > space_remaining) {
1750 /* Move the dirptr back to prev_dirpos */
1751 dptr_SeekDir(conn->dirptr, prev_dirpos);
1752 *out_of_space = True;
1753 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1754 return False; /* Not finished - just out of space */
1757 /* Setup the last entry pointer, as an offset from base_data */
1758 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1759 /* Advance the data pointer to the next slot */
1765 /****************************************************************************
1766 Reply to a TRANS2_FINDFIRST.
1767 ****************************************************************************/
1769 static void call_trans2findfirst(connection_struct *conn,
1770 struct smb_request *req,
1771 char **pparams, int total_params,
1772 char **ppdata, int total_data,
1773 unsigned int max_data_bytes)
1775 /* We must be careful here that we don't return more than the
1776 allowed number of data bytes. If this means returning fewer than
1777 maxentries then so be it. We assume that the redirector has
1778 enough room for the fixed number of parameter bytes it has
1780 char *params = *pparams;
1781 char *pdata = *ppdata;
1785 uint16 findfirst_flags;
1786 bool close_after_first;
1788 bool requires_resume_key;
1790 char *directory = NULL;
1791 const char *mask = NULL;
1793 int last_entry_off=0;
1797 bool finished = False;
1798 bool dont_descend = False;
1799 bool out_of_space = False;
1800 int space_remaining;
1801 bool mask_contains_wcard = False;
1802 SMB_STRUCT_STAT sbuf;
1803 struct ea_list *ea_list = NULL;
1804 NTSTATUS ntstatus = NT_STATUS_OK;
1805 TALLOC_CTX *ctx = talloc_tos();
1807 if (total_params < 13) {
1808 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1812 dirtype = SVAL(params,0);
1813 maxentries = SVAL(params,2);
1814 findfirst_flags = SVAL(params,4);
1815 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1816 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1817 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1818 info_level = SVAL(params,6);
1820 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1821 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1822 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1823 info_level, max_data_bytes));
1826 /* W2K3 seems to treat zero as 1. */
1830 switch (info_level) {
1831 case SMB_FIND_INFO_STANDARD:
1832 case SMB_FIND_EA_SIZE:
1833 case SMB_FIND_EA_LIST:
1834 case SMB_FIND_FILE_DIRECTORY_INFO:
1835 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1836 case SMB_FIND_FILE_NAMES_INFO:
1837 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1838 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1839 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1841 case SMB_FIND_FILE_UNIX:
1842 case SMB_FIND_FILE_UNIX_INFO2:
1843 if (!lp_unix_extensions()) {
1844 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1849 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1853 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1854 params+12, total_params - 12,
1855 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1856 if (!NT_STATUS_IS_OK(ntstatus)) {
1857 reply_nterror(req, ntstatus);
1861 ntstatus = resolve_dfspath_wcard(ctx, conn,
1862 req->flags2 & FLAGS2_DFS_PATHNAMES,
1865 &mask_contains_wcard);
1866 if (!NT_STATUS_IS_OK(ntstatus)) {
1867 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1868 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1869 ERRSRV, ERRbadpath);
1872 reply_nterror(req, ntstatus);
1876 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1877 if (!NT_STATUS_IS_OK(ntstatus)) {
1878 reply_nterror(req, ntstatus);
1882 ntstatus = check_name(conn, directory);
1883 if (!NT_STATUS_IS_OK(ntstatus)) {
1884 reply_nterror(req, ntstatus);
1888 p = strrchr_m(directory,'/');
1890 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1891 if((directory[0] == '.') && (directory[1] == '\0')) {
1893 mask_contains_wcard = True;
1897 directory = talloc_strdup(talloc_tos(), "./");
1899 reply_nterror(req, NT_STATUS_NO_MEMORY);
1907 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1909 if (info_level == SMB_FIND_EA_LIST) {
1912 if (total_data < 4) {
1913 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1917 ea_size = IVAL(pdata,0);
1918 if (ea_size != total_data) {
1919 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1920 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1921 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1925 if (!lp_ea_support(SNUM(conn))) {
1926 reply_doserror(req, ERRDOS, ERReasnotsupported);
1930 /* Pull out the list of names. */
1931 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1933 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1938 *ppdata = (char *)SMB_REALLOC(
1939 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1940 if(*ppdata == NULL ) {
1941 reply_nterror(req, NT_STATUS_NO_MEMORY);
1945 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1947 /* Realloc the params space */
1948 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1949 if (*pparams == NULL) {
1950 reply_nterror(req, NT_STATUS_NO_MEMORY);
1955 /* Save the wildcard match and attribs we are using on this directory -
1956 needed as lanman2 assumes these are being saved between calls */
1958 ntstatus = dptr_create(conn,
1964 mask_contains_wcard,
1968 if (!NT_STATUS_IS_OK(ntstatus)) {
1969 reply_nterror(req, ntstatus);
1973 dptr_num = dptr_dnum(conn->dirptr);
1974 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1976 /* We don't need to check for VOL here as this is returned by
1977 a different TRANS2 call. */
1979 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1980 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1981 dont_descend = True;
1984 space_remaining = max_data_bytes;
1985 out_of_space = False;
1987 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1988 bool got_exact_match = False;
1990 /* this is a heuristic to avoid seeking the dirptr except when
1991 absolutely necessary. It allows for a filename of about 40 chars */
1992 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1993 out_of_space = True;
1996 TALLOC_CTX *sub_ctx = talloc_stackframe();
1998 finished = !get_lanman2_dir_entry(sub_ctx,
2001 mask,dirtype,info_level,
2002 requires_resume_key,dont_descend,
2004 space_remaining, &out_of_space,
2006 &last_entry_off, ea_list);
2008 TALLOC_FREE(sub_ctx);
2011 if (finished && out_of_space)
2014 if (!finished && !out_of_space)
2018 * As an optimisation if we know we aren't looking
2019 * for a wildcard name (ie. the name matches the wildcard exactly)
2020 * then we can finish on any (first) match.
2021 * This speeds up large directory searches. JRA.
2027 /* Ensure space_remaining never goes -ve. */
2028 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2029 space_remaining = 0;
2030 out_of_space = true;
2032 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2036 /* Check if we can close the dirptr */
2037 if(close_after_first || (finished && close_if_end)) {
2038 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2039 dptr_close(&dptr_num);
2043 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2044 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2045 * the protocol level is less than NT1. Tested with smbclient. JRA.
2046 * This should fix the OS/2 client bug #2335.
2049 if(numentries == 0) {
2050 dptr_close(&dptr_num);
2051 if (Protocol < PROTOCOL_NT1) {
2052 reply_doserror(req, ERRDOS, ERRnofiles);
2055 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2056 ERRDOS, ERRbadfile);
2061 /* At this point pdata points to numentries directory entries. */
2063 /* Set up the return parameter block */
2064 SSVAL(params,0,dptr_num);
2065 SSVAL(params,2,numentries);
2066 SSVAL(params,4,finished);
2067 SSVAL(params,6,0); /* Never an EA error */
2068 SSVAL(params,8,last_entry_off);
2070 send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
2073 if ((! *directory) && dptr_path(dptr_num)) {
2074 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2076 reply_nterror(req, NT_STATUS_NO_MEMORY);
2080 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2081 smb_fn_name(CVAL(req->inbuf,smb_com)),
2082 mask, directory, dirtype, numentries ) );
2085 * Force a name mangle here to ensure that the
2086 * mask as an 8.3 name is top of the mangled cache.
2087 * The reasons for this are subtle. Don't remove
2088 * this code unless you know what you are doing
2089 * (see PR#13758). JRA.
2092 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2093 char mangled_name[13];
2094 name_to_8_3(mask, mangled_name, True, conn->params);
2100 /****************************************************************************
2101 Reply to a TRANS2_FINDNEXT.
2102 ****************************************************************************/
2104 static void call_trans2findnext(connection_struct *conn,
2105 struct smb_request *req,
2106 char **pparams, int total_params,
2107 char **ppdata, int total_data,
2108 unsigned int max_data_bytes)
2110 /* We must be careful here that we don't return more than the
2111 allowed number of data bytes. If this means returning fewer than
2112 maxentries then so be it. We assume that the redirector has
2113 enough room for the fixed number of parameter bytes it has
2115 char *params = *pparams;
2116 char *pdata = *ppdata;
2122 uint16 findnext_flags;
2123 bool close_after_request;
2125 bool requires_resume_key;
2127 bool mask_contains_wcard = False;
2128 char *resume_name = NULL;
2129 const char *mask = NULL;
2130 const char *directory = NULL;
2134 int i, last_entry_off=0;
2135 bool finished = False;
2136 bool dont_descend = False;
2137 bool out_of_space = False;
2138 int space_remaining;
2139 struct ea_list *ea_list = NULL;
2140 NTSTATUS ntstatus = NT_STATUS_OK;
2141 TALLOC_CTX *ctx = talloc_tos();
2143 if (total_params < 13) {
2144 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2148 dptr_num = SVAL(params,0);
2149 maxentries = SVAL(params,2);
2150 info_level = SVAL(params,4);
2151 resume_key = IVAL(params,6);
2152 findnext_flags = SVAL(params,10);
2153 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2154 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2155 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2156 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2158 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2160 total_params - 12, STR_TERMINATE, &ntstatus,
2161 &mask_contains_wcard);
2162 if (!NT_STATUS_IS_OK(ntstatus)) {
2163 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2164 complain (it thinks we're asking for the directory above the shared
2165 path or an invalid name). Catch this as the resume name is only compared, never used in
2166 a file access. JRA. */
2167 srvstr_pull_talloc(ctx, params, req->flags2,
2168 &resume_name, params+12,
2172 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2173 reply_nterror(req, ntstatus);
2178 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2179 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2180 resume_key = %d resume name = %s continue=%d level = %d\n",
2181 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2182 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2185 /* W2K3 seems to treat zero as 1. */
2189 switch (info_level) {
2190 case SMB_FIND_INFO_STANDARD:
2191 case SMB_FIND_EA_SIZE:
2192 case SMB_FIND_EA_LIST:
2193 case SMB_FIND_FILE_DIRECTORY_INFO:
2194 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2195 case SMB_FIND_FILE_NAMES_INFO:
2196 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2197 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2198 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2200 case SMB_FIND_FILE_UNIX:
2201 case SMB_FIND_FILE_UNIX_INFO2:
2202 if (!lp_unix_extensions()) {
2203 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2208 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2212 if (info_level == SMB_FIND_EA_LIST) {
2215 if (total_data < 4) {
2216 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2220 ea_size = IVAL(pdata,0);
2221 if (ea_size != total_data) {
2222 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2223 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2224 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2228 if (!lp_ea_support(SNUM(conn))) {
2229 reply_doserror(req, ERRDOS, ERReasnotsupported);
2233 /* Pull out the list of names. */
2234 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2236 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2241 *ppdata = (char *)SMB_REALLOC(
2242 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2243 if(*ppdata == NULL) {
2244 reply_nterror(req, NT_STATUS_NO_MEMORY);
2249 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2251 /* Realloc the params space */
2252 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2253 if(*pparams == NULL ) {
2254 reply_nterror(req, NT_STATUS_NO_MEMORY);
2260 /* Check that the dptr is valid */
2261 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2262 reply_doserror(req, ERRDOS, ERRnofiles);
2266 string_set(&conn->dirpath,dptr_path(dptr_num));
2268 /* Get the wildcard mask from the dptr */
2269 if((p = dptr_wcard(dptr_num))== NULL) {
2270 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2271 reply_doserror(req, ERRDOS, ERRnofiles);
2276 directory = conn->dirpath;
2278 /* Get the attr mask from the dptr */
2279 dirtype = dptr_attr(dptr_num);
2281 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2282 dptr_num, mask, dirtype,
2284 dptr_TellDir(conn->dirptr)));
2286 /* We don't need to check for VOL here as this is returned by
2287 a different TRANS2 call. */
2289 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2290 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2291 dont_descend = True;
2294 space_remaining = max_data_bytes;
2295 out_of_space = False;
2298 * Seek to the correct position. We no longer use the resume key but
2299 * depend on the last file name instead.
2302 if(*resume_name && !continue_bit) {
2305 long current_pos = 0;
2307 * Remember, name_to_8_3 is called by
2308 * get_lanman2_dir_entry(), so the resume name
2309 * could be mangled. Ensure we check the unmangled name.
2312 if (mangle_is_mangled(resume_name, conn->params)) {
2313 char *new_resume_name = NULL;
2314 mangle_lookup_name_from_8_3(ctx,
2318 if (new_resume_name) {
2319 resume_name = new_resume_name;
2324 * Fix for NT redirector problem triggered by resume key indexes
2325 * changing between directory scans. We now return a resume key of 0
2326 * and instead look for the filename to continue from (also given
2327 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2328 * findfirst/findnext (as is usual) then the directory pointer
2329 * should already be at the correct place.
2332 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2333 } /* end if resume_name && !continue_bit */
2335 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2336 bool got_exact_match = False;
2338 /* this is a heuristic to avoid seeking the dirptr except when
2339 absolutely necessary. It allows for a filename of about 40 chars */
2340 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2341 out_of_space = True;
2344 TALLOC_CTX *sub_ctx = talloc_stackframe();
2346 finished = !get_lanman2_dir_entry(sub_ctx,
2349 mask,dirtype,info_level,
2350 requires_resume_key,dont_descend,
2352 space_remaining, &out_of_space,
2354 &last_entry_off, ea_list);
2356 TALLOC_FREE(sub_ctx);
2359 if (finished && out_of_space)
2362 if (!finished && !out_of_space)
2366 * As an optimisation if we know we aren't looking
2367 * for a wildcard name (ie. the name matches the wildcard exactly)
2368 * then we can finish on any (first) match.
2369 * This speeds up large directory searches. JRA.
2375 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2378 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2379 smb_fn_name(CVAL(req->inbuf,smb_com)),
2380 mask, directory, dirtype, numentries ) );
2382 /* Check if we can close the dirptr */
2383 if(close_after_request || (finished && close_if_end)) {
2384 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2385 dptr_close(&dptr_num); /* This frees up the saved mask */
2388 /* Set up the return parameter block */
2389 SSVAL(params,0,numentries);
2390 SSVAL(params,2,finished);
2391 SSVAL(params,4,0); /* Never an EA error */
2392 SSVAL(params,6,last_entry_off);
2394 send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata),
2400 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2402 E_md4hash(lp_servicename(SNUM(conn)),objid);
2406 /****************************************************************************
2407 Reply to a TRANS2_QFSINFO (query filesystem info).
2408 ****************************************************************************/
2410 static void call_trans2qfsinfo(connection_struct *conn,
2411 struct smb_request *req,
2412 char **pparams, int total_params,
2413 char **ppdata, int total_data,
2414 unsigned int max_data_bytes)
2416 char *pdata, *end_data;
2417 char *params = *pparams;
2421 const char *vname = volume_label(SNUM(conn));
2422 int snum = SNUM(conn);
2423 char *fstype = lp_fstype(SNUM(conn));
2426 if (total_params < 2) {
2427 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2431 info_level = SVAL(params,0);
2433 if (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF ) {
2434 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2435 DEBUG(0,("call_trans2qfsinfo: encryption required "
2436 "and info level 0x%x sent.\n",
2437 (unsigned int)info_level));
2438 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2443 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2445 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2446 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2447 reply_doserror(req, ERRSRV, ERRinvdevice);
2451 *ppdata = (char *)SMB_REALLOC(
2452 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2453 if (*ppdata == NULL ) {
2454 reply_nterror(req, NT_STATUS_NO_MEMORY);
2459 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2460 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2462 switch (info_level) {
2463 case SMB_INFO_ALLOCATION:
2465 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2467 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2468 reply_unixerror(req, ERRHRD, ERRgeneral);
2472 block_size = lp_block_size(snum);
2473 if (bsize < block_size) {
2474 SMB_BIG_UINT factor = block_size/bsize;
2479 if (bsize > block_size) {
2480 SMB_BIG_UINT factor = bsize/block_size;
2485 bytes_per_sector = 512;
2486 sectors_per_unit = bsize/bytes_per_sector;
2488 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2489 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2490 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2492 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2493 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2494 SIVAL(pdata,l1_cUnit,dsize);
2495 SIVAL(pdata,l1_cUnitAvail,dfree);
2496 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2500 case SMB_INFO_VOLUME:
2501 /* Return volume name */
2503 * Add volume serial number - hash of a combination of
2504 * the called hostname and the service name.
2506 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2508 * Win2k3 and previous mess this up by sending a name length
2509 * one byte short. I believe only older clients (OS/2 Win9x) use
2510 * this call so try fixing this by adding a terminating null to
2511 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2515 pdata+l2_vol_szVolLabel, vname,
2516 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2517 STR_NOALIGN|STR_TERMINATE);
2518 SCVAL(pdata,l2_vol_cch,len);
2519 data_len = l2_vol_szVolLabel + len;
2520 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2521 (unsigned)st.st_ctime, len, vname));
2524 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2525 case SMB_FS_ATTRIBUTE_INFORMATION:
2528 #if defined(HAVE_SYS_QUOTAS)
2529 quota_flag = FILE_VOLUME_QUOTAS;
2532 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2533 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2534 FILE_SUPPORTS_OBJECT_IDS|
2535 FILE_UNICODE_ON_DISK|
2536 quota_flag); /* FS ATTRIBUTES */
2538 SIVAL(pdata,4,255); /* Max filename component length */
2539 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2540 and will think we can't do long filenames */
2541 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2542 PTR_DIFF(end_data, pdata+12),
2545 data_len = 12 + len;
2548 case SMB_QUERY_FS_LABEL_INFO:
2549 case SMB_FS_LABEL_INFORMATION:
2550 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2551 PTR_DIFF(end_data, pdata+4), 0);
2556 case SMB_QUERY_FS_VOLUME_INFO:
2557 case SMB_FS_VOLUME_INFORMATION:
2560 * Add volume serial number - hash of a combination of
2561 * the called hostname and the service name.
2563 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2564 (str_checksum(get_local_machine_name())<<16));
2566 /* Max label len is 32 characters. */
2567 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2568 PTR_DIFF(end_data, pdata+18),
2570 SIVAL(pdata,12,len);
2573 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2574 (int)strlen(vname),vname, lp_servicename(snum)));
2577 case SMB_QUERY_FS_SIZE_INFO:
2578 case SMB_FS_SIZE_INFORMATION:
2580 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2582 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2583 reply_unixerror(req, ERRHRD, ERRgeneral);
2586 block_size = lp_block_size(snum);
2587 if (bsize < block_size) {
2588 SMB_BIG_UINT factor = block_size/bsize;
2593 if (bsize > block_size) {
2594 SMB_BIG_UINT factor = bsize/block_size;
2599 bytes_per_sector = 512;
2600 sectors_per_unit = bsize/bytes_per_sector;
2601 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2602 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2603 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2604 SBIG_UINT(pdata,0,dsize);
2605 SBIG_UINT(pdata,8,dfree);
2606 SIVAL(pdata,16,sectors_per_unit);
2607 SIVAL(pdata,20,bytes_per_sector);
2611 case SMB_FS_FULL_SIZE_INFORMATION:
2613 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2615 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2616 reply_unixerror(req, ERRHRD, ERRgeneral);
2619 block_size = lp_block_size(snum);
2620 if (bsize < block_size) {
2621 SMB_BIG_UINT factor = block_size/bsize;
2626 if (bsize > block_size) {
2627 SMB_BIG_UINT factor = bsize/block_size;
2632 bytes_per_sector = 512;
2633 sectors_per_unit = bsize/bytes_per_sector;
2634 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2635 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2636 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2637 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2638 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2639 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2640 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2641 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2645 case SMB_QUERY_FS_DEVICE_INFO:
2646 case SMB_FS_DEVICE_INFORMATION:
2648 SIVAL(pdata,0,0); /* dev type */
2649 SIVAL(pdata,4,0); /* characteristics */
2652 #ifdef HAVE_SYS_QUOTAS
2653 case SMB_FS_QUOTA_INFORMATION:
2655 * what we have to send --metze:
2657 * Unknown1: 24 NULL bytes
2658 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2659 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2660 * Quota Flags: 2 byte :
2661 * Unknown3: 6 NULL bytes
2665 * details for Quota Flags:
2667 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2668 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2669 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2670 * 0x0001 Enable Quotas: enable quota for this fs
2674 /* we need to fake up a fsp here,
2675 * because its not send in this call
2678 SMB_NTQUOTA_STRUCT quotas;
2681 ZERO_STRUCT(quotas);
2687 if (current_user.ut.uid != 0) {
2688 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2689 lp_servicename(SNUM(conn)),conn->user));
2690 reply_doserror(req, ERRDOS, ERRnoaccess);
2694 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2695 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2696 reply_doserror(req, ERRSRV, ERRerror);
2702 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2704 /* Unknown1 24 NULL bytes*/
2705 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2706 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2707 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2709 /* Default Soft Quota 8 bytes */
2710 SBIG_UINT(pdata,24,quotas.softlim);
2712 /* Default Hard Quota 8 bytes */
2713 SBIG_UINT(pdata,32,quotas.hardlim);
2715 /* Quota flag 2 bytes */
2716 SSVAL(pdata,40,quotas.qflags);
2718 /* Unknown3 6 NULL bytes */
2724 #endif /* HAVE_SYS_QUOTAS */
2725 case SMB_FS_OBJECTID_INFORMATION:
2727 unsigned char objid[16];
2728 memcpy(pdata,create_volume_objectid(conn, objid),16);
2734 * Query the version and capabilities of the CIFS UNIX extensions
2738 case SMB_QUERY_CIFS_UNIX_INFO:
2740 bool large_write = lp_min_receive_file_size() &&
2741 !srv_is_signing_active();
2742 bool large_read = !srv_is_signing_active();
2743 int encrypt_caps = 0;
2745 if (!lp_unix_extensions()) {
2746 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2750 switch (conn->encrypt_level) {
2756 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2759 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2760 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2761 large_write = false;
2767 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2768 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2770 /* We have POSIX ACLs, pathname, encryption,
2771 * large read/write, and locking capability. */
2773 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2774 CIFS_UNIX_POSIX_ACLS_CAP|
2775 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2776 CIFS_UNIX_FCNTL_LOCKS_CAP|
2777 CIFS_UNIX_EXTATTR_CAP|
2778 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2780 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2782 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2786 case SMB_QUERY_POSIX_FS_INFO:
2789 vfs_statvfs_struct svfs;
2791 if (!lp_unix_extensions()) {
2792 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2796 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2800 SIVAL(pdata,0,svfs.OptimalTransferSize);
2801 SIVAL(pdata,4,svfs.BlockSize);
2802 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2803 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2804 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2805 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2806 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2807 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2808 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2810 } else if (rc == EOPNOTSUPP) {
2811 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2813 #endif /* EOPNOTSUPP */
2815 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2816 reply_doserror(req, ERRSRV, ERRerror);
2822 case SMB_QUERY_POSIX_WHOAMI:
2828 if (!lp_unix_extensions()) {
2829 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2833 if (max_data_bytes < 40) {
2834 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2838 /* We ARE guest if global_sid_Builtin_Guests is
2839 * in our list of SIDs.
2841 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2842 current_user.nt_user_token)) {
2843 flags |= SMB_WHOAMI_GUEST;
2846 /* We are NOT guest if global_sid_Authenticated_Users
2847 * is in our list of SIDs.
2849 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2850 current_user.nt_user_token)) {
2851 flags &= ~SMB_WHOAMI_GUEST;
2854 /* NOTE: 8 bytes for UID/GID, irrespective of native
2855 * platform size. This matches
2856 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2858 data_len = 4 /* flags */
2865 + 4 /* pad/reserved */
2866 + (current_user.ut.ngroups * 8)
2868 + (current_user.nt_user_token->num_sids *
2872 SIVAL(pdata, 0, flags);
2873 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2874 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2875 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2878 if (data_len >= max_data_bytes) {
2879 /* Potential overflow, skip the GIDs and SIDs. */
2881 SIVAL(pdata, 24, 0); /* num_groups */
2882 SIVAL(pdata, 28, 0); /* num_sids */
2883 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2884 SIVAL(pdata, 36, 0); /* reserved */
2890 SIVAL(pdata, 24, current_user.ut.ngroups);
2892 current_user.nt_user_token->num_sids);
2894 /* We walk the SID list twice, but this call is fairly
2895 * infrequent, and I don't expect that it's performance
2896 * sensitive -- jpeach
2898 for (i = 0, sid_bytes = 0;
2899 i < current_user.nt_user_token->num_sids; ++i) {
2901 sid_size(¤t_user.nt_user_token->user_sids[i]);
2904 /* SID list byte count */
2905 SIVAL(pdata, 32, sid_bytes);
2907 /* 4 bytes pad/reserved - must be zero */
2908 SIVAL(pdata, 36, 0);
2912 for (i = 0; i < current_user.ut.ngroups; ++i) {
2913 SBIG_UINT(pdata, data_len,
2914 (SMB_BIG_UINT)current_user.ut.groups[i]);
2920 i < current_user.nt_user_token->num_sids; ++i) {
2922 sid_size(¤t_user.nt_user_token->user_sids[i]);
2924 sid_linearize(pdata + data_len, sid_len,
2925 ¤t_user.nt_user_token->user_sids[i]);
2926 data_len += sid_len;
2932 case SMB_MAC_QUERY_FS_INFO:
2934 * Thursby MAC extension... ONLY on NTFS filesystems
2935 * once we do streams then we don't need this
2937 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2939 SIVAL(pdata,84,0x100); /* Don't support mac... */
2944 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2949 send_trans2_replies(req, params, 0, pdata, data_len,
2952 DEBUG( 4, ( "%s info_level = %d\n",
2953 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2958 /****************************************************************************
2959 Reply to a TRANS2_SETFSINFO (set filesystem info).
2960 ****************************************************************************/
2962 static void call_trans2setfsinfo(connection_struct *conn,
2963 struct smb_request *req,
2964 char **pparams, int total_params,
2965 char **ppdata, int total_data,
2966 unsigned int max_data_bytes)
2968 char *pdata = *ppdata;
2969 char *params = *pparams;
2972 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2975 if (total_params < 4) {
2976 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2982 info_level = SVAL(params,2);
2984 if (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF ) {
2985 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
2986 DEBUG(0,("call_trans2setfsinfo: encryption required "
2987 "and info level 0x%x sent.\n",
2988 (unsigned int)info_level));
2989 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2994 switch(info_level) {
2995 case SMB_SET_CIFS_UNIX_INFO:
2997 uint16 client_unix_major;
2998 uint16 client_unix_minor;
2999 uint32 client_unix_cap_low;
3000 uint32 client_unix_cap_high;
3002 if (!lp_unix_extensions()) {
3004 NT_STATUS_INVALID_LEVEL);
3008 /* There should be 12 bytes of capabilities set. */
3009 if (total_data < 8) {
3012 NT_STATUS_INVALID_PARAMETER);
3015 client_unix_major = SVAL(pdata,0);
3016 client_unix_minor = SVAL(pdata,2);
3017 client_unix_cap_low = IVAL(pdata,4);
3018 client_unix_cap_high = IVAL(pdata,8);
3019 /* Just print these values for now. */
3020 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3021 cap_low = 0x%x, cap_high = 0x%x\n",
3022 (unsigned int)client_unix_major,
3023 (unsigned int)client_unix_minor,
3024 (unsigned int)client_unix_cap_low,
3025 (unsigned int)client_unix_cap_high ));
3027 /* Here is where we must switch to posix pathname processing... */
3028 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3029 lp_set_posix_pathnames();
3030 mangle_change_to_posix();
3033 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3034 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3035 /* Client that knows how to do posix locks,
3036 * but not posix open/mkdir operations. Set a
3037 * default type for read/write checks. */
3039 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3045 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3048 size_t param_len = 0;
3049 size_t data_len = total_data;
3051 if (!lp_unix_extensions()) {
3054 NT_STATUS_INVALID_LEVEL);
3058 if (lp_smb_encrypt(SNUM(conn)) == false) {
3061 NT_STATUS_NOT_SUPPORTED);
3065 DEBUG( 4,("call_trans2setfsinfo: "
3066 "request transport encrption.\n"));
3068 status = srv_request_encryption_setup(conn,
3069 (unsigned char **)ppdata,
3071 (unsigned char **)pparams,
3074 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3075 !NT_STATUS_IS_OK(status)) {
3076 reply_nterror(req, status);
3080 send_trans2_replies(req,
3087 if (NT_STATUS_IS_OK(status)) {
3088 /* Server-side transport
3089 * encryption is now *on*. */
3090 status = srv_encryption_start(conn);
3091 if (!NT_STATUS_IS_OK(status)) {
3092 exit_server_cleanly(
3093 "Failure in setting "
3094 "up encrypted transport");
3100 case SMB_FS_QUOTA_INFORMATION:
3102 files_struct *fsp = NULL;
3103 SMB_NTQUOTA_STRUCT quotas;
3105 ZERO_STRUCT(quotas);
3108 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3109 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3110 lp_servicename(SNUM(conn)),conn->user));
3111 reply_doserror(req, ERRSRV, ERRaccess);
3115 /* note: normaly there're 48 bytes,
3116 * but we didn't use the last 6 bytes for now
3119 fsp = file_fsp(SVAL(params,0));
3120 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3121 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3123 req, NT_STATUS_INVALID_HANDLE);
3127 if (total_data < 42) {
3128 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3132 NT_STATUS_INVALID_PARAMETER);
3136 /* unknown_1 24 NULL bytes in pdata*/
3138 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3139 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3140 #ifdef LARGE_SMB_OFF_T
3141 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3142 #else /* LARGE_SMB_OFF_T */
3143 if ((IVAL(pdata,28) != 0)&&
3144 ((quotas.softlim != 0xFFFFFFFF)||
3145 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3146 /* more than 32 bits? */
3149 NT_STATUS_INVALID_PARAMETER);
3152 #endif /* LARGE_SMB_OFF_T */
3154 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3155 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3156 #ifdef LARGE_SMB_OFF_T
3157 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3158 #else /* LARGE_SMB_OFF_T */
3159 if ((IVAL(pdata,36) != 0)&&
3160 ((quotas.hardlim != 0xFFFFFFFF)||
3161 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3162 /* more than 32 bits? */
3165 NT_STATUS_INVALID_PARAMETER);
3168 #endif /* LARGE_SMB_OFF_T */
3170 /* quota_flags 2 bytes **/
3171 quotas.qflags = SVAL(pdata,40);
3173 /* unknown_2 6 NULL bytes follow*/
3175 /* now set the quotas */
3176 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3177 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3178 reply_doserror(req, ERRSRV, ERRerror);
3185 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3187 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3193 * sending this reply works fine,
3194 * but I'm not sure it's the same
3195 * like windows do...
3198 reply_outbuf(req, 10, 0);
3201 #if defined(HAVE_POSIX_ACLS)
3202 /****************************************************************************
3203 Utility function to count the number of entries in a POSIX acl.
3204 ****************************************************************************/
3206 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3208 unsigned int ace_count = 0;
3209 int entry_id = SMB_ACL_FIRST_ENTRY;
3210 SMB_ACL_ENTRY_T entry;
3212 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3214 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3215 entry_id = SMB_ACL_NEXT_ENTRY;
3222 /****************************************************************************
3223 Utility function to marshall a POSIX acl into wire format.
3224 ****************************************************************************/
3226 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3228 int entry_id = SMB_ACL_FIRST_ENTRY;
3229 SMB_ACL_ENTRY_T entry;
3231 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3232 SMB_ACL_TAG_T tagtype;
3233 SMB_ACL_PERMSET_T permset;
3234 unsigned char perms = 0;
3235 unsigned int own_grp;
3238 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3239 entry_id = SMB_ACL_NEXT_ENTRY;
3242 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3243 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3247 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3248 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3252 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3253 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3254 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3256 SCVAL(pdata,1,perms);
3259 case SMB_ACL_USER_OBJ:
3260 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3261 own_grp = (unsigned int)pst->st_uid;
3262 SIVAL(pdata,2,own_grp);
3267 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3269 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3272 own_grp = (unsigned int)*puid;
3273 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3274 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3275 SIVAL(pdata,2,own_grp);
3279 case SMB_ACL_GROUP_OBJ:
3280 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3281 own_grp = (unsigned int)pst->st_gid;
3282 SIVAL(pdata,2,own_grp);
3287 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3289 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3292 own_grp = (unsigned int)*pgid;
3293 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3294 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3295 SIVAL(pdata,2,own_grp);
3300 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3301 SIVAL(pdata,2,0xFFFFFFFF);
3302 SIVAL(pdata,6,0xFFFFFFFF);
3305 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3306 SIVAL(pdata,2,0xFFFFFFFF);
3307 SIVAL(pdata,6,0xFFFFFFFF);
3310 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3313 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3320 /****************************************************************************
3321 Store the FILE_UNIX_BASIC info.
3322 ****************************************************************************/
3324 static char *store_file_unix_basic(connection_struct *conn,
3327 const SMB_STRUCT_STAT *psbuf)
3329 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3330 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3332 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3335 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3338 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3339 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3340 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3343 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3347 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3351 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3354 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3358 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3362 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3365 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3369 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3376 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3377 * the chflags(2) (or equivalent) flags.
3379 * XXX: this really should be behind the VFS interface. To do this, we would
3380 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3381 * Each VFS module could then implement its own mapping as appropriate for the
3382 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3384 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3388 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3392 { UF_IMMUTABLE, EXT_IMMUTABLE },
3396 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3400 { UF_HIDDEN, EXT_HIDDEN },
3403 /* Do not remove. We need to guarantee that this array has at least one
3404 * entry to build on HP-UX.
3410 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3411 uint32 *smb_fflags, uint32 *smb_fmask)
3413 #ifdef HAVE_STAT_ST_FLAGS
3416 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3417 *smb_fmask |= info2_flags_map[i].smb_fflag;
3418 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3419 *smb_fflags |= info2_flags_map[i].smb_fflag;
3422 #endif /* HAVE_STAT_ST_FLAGS */
3425 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3426 const uint32 smb_fflags,
3427 const uint32 smb_fmask,
3430 #ifdef HAVE_STAT_ST_FLAGS
3431 uint32 max_fmask = 0;
3434 *stat_fflags = psbuf->st_flags;
3436 /* For each flags requested in smb_fmask, check the state of the
3437 * corresponding flag in smb_fflags and set or clear the matching
3441 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3442 max_fmask |= info2_flags_map[i].smb_fflag;
3443 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3444 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3445 *stat_fflags |= info2_flags_map[i].stat_fflag;
3447 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3452 /* If smb_fmask is asking to set any bits that are not supported by
3453 * our flag mappings, we should fail.
3455 if ((smb_fmask & max_fmask) != smb_fmask) {
3462 #endif /* HAVE_STAT_ST_FLAGS */
3466 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3467 * of file flags and birth (create) time.
3469 static char *store_file_unix_basic_info2(connection_struct *conn,
3472 const SMB_STRUCT_STAT *psbuf)
3474 uint32 file_flags = 0;
3475 uint32 flags_mask = 0;
3477 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3479 /* Create (birth) time 64 bit */
3480 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3483 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3484 SIVAL(pdata, 0, file_flags); /* flags */
3485 SIVAL(pdata, 4, flags_mask); /* mask */
3491 /****************************************************************************
3492 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3493 ****************************************************************************/
3495 static void call_trans2qpipeinfo(connection_struct *conn,
3496 struct smb_request *req,
3497 unsigned int tran_call,
3498 char **pparams, int total_params,
3499 char **ppdata, int total_data,
3500 unsigned int max_data_bytes)
3502 char *params = *pparams;
3503 char *pdata = *ppdata;
3504 unsigned int data_size = 0;
3505 unsigned int param_size = 2;
3507 smb_np_struct *p_pipe = NULL;
3510 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3514 if (total_params < 4) {
3515 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3519 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3520 if (p_pipe == NULL) {
3521 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3525 info_level = SVAL(params,2);
3527 *pparams = (char *)SMB_REALLOC(*pparams,2);
3528 if (*pparams == NULL) {
3529 reply_nterror(req, NT_STATUS_NO_MEMORY);
3534 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3535 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3536 if (*ppdata == NULL ) {
3537 reply_nterror(req, NT_STATUS_NO_MEMORY);
3542 switch (info_level) {
3543 case SMB_FILE_STANDARD_INFORMATION:
3545 SOFF_T(pdata,0,4096LL);
3552 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3556 send_trans2_replies(req, params, param_size, *ppdata, data_size,
3562 /****************************************************************************
3563 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3564 file name or file id).
3565 ****************************************************************************/
3567 static void call_trans2qfilepathinfo(connection_struct *conn,
3568 struct smb_request *req,
3569 unsigned int tran_call,
3570 char **pparams, int total_params,
3571 char **ppdata, int total_data,
3572 unsigned int max_data_bytes)
3574 char *params = *pparams;
3575 char *pdata = *ppdata;
3576 char *dstart, *dend;
3580 SMB_OFF_T file_size=0;
3581 SMB_BIG_UINT allocation_size=0;
3582 unsigned int data_size = 0;
3583 unsigned int param_size = 2;
3584 SMB_STRUCT_STAT sbuf;
3585 char *dos_fname = NULL;
3591 bool delete_pending = False;
3593 time_t create_time, mtime, atime;
3594 struct timespec create_time_ts, mtime_ts, atime_ts;
3595 files_struct *fsp = NULL;
3596 struct file_id fileid;
3597 struct ea_list *ea_list = NULL;
3598 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3599 char *lock_data = NULL;
3600 TALLOC_CTX *ctx = talloc_tos();
3603 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3609 if (tran_call == TRANSACT2_QFILEINFO) {
3610 if (total_params < 4) {
3611 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3616 call_trans2qpipeinfo(conn, req, tran_call,
3617 pparams, total_params,
3623 fsp = file_fsp(SVAL(params,0));
3624 info_level = SVAL(params,2);
3626 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3628 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3629 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3633 /* Initial check for valid fsp ptr. */
3634 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
3638 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3640 reply_nterror(req, NT_STATUS_NO_MEMORY);
3644 if(fsp->fake_file_handle) {
3646 * This is actually for the QUOTA_FAKE_FILE --metze
3649 /* We know this name is ok, it's already passed the checks. */
3651 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3653 * This is actually a QFILEINFO on a directory
3654 * handle (returned from an NT SMB). NT5.0 seems
3655 * to do this call. JRA.
3658 if (INFO_LEVEL_IS_UNIX(info_level)) {
3659 /* Always do lstat for UNIX calls. */
3660 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3661 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3662 reply_unixerror(req,ERRDOS,ERRbadpath);
3665 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3666 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3667 reply_unixerror(req, ERRDOS, ERRbadpath);
3671 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3672 delete_pending = get_delete_on_close_flag(fileid);
3675 * Original code - this is an open file.
3677 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3681 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3682 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3683 reply_unixerror(req, ERRDOS, ERRbadfid);
3686 pos = fsp->fh->position_information;
3687 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3688 delete_pending = get_delete_on_close_flag(fileid);
3689 access_mask = fsp->access_mask;
3693 NTSTATUS status = NT_STATUS_OK;
3696 if (total_params < 7) {
3697 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3701 info_level = SVAL(params,0);
3703 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3705 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3706 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3710 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3712 STR_TERMINATE, &status);
3713 if (!NT_STATUS_IS_OK(status)) {
3714 reply_nterror(req, status);
3718 status = resolve_dfspath(ctx,
3720 req->flags2 & FLAGS2_DFS_PATHNAMES,
3723 if (!NT_STATUS_IS_OK(status)) {
3724 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3725 reply_botherror(req,
3726 NT_STATUS_PATH_NOT_COVERED,
3727 ERRSRV, ERRbadpath);
3729 reply_nterror(req, status);
3733 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3734 if (!NT_STATUS_IS_OK(status)) {
3735 reply_nterror(req, status);
3738 status = check_name(conn, fname);
3739 if (!NT_STATUS_IS_OK(status)) {
3740 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3741 reply_nterror(req, status);
3745 if (INFO_LEVEL_IS_UNIX(info_level)) {
3746 /* Always do lstat for UNIX calls. */
3747 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3748 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3749 reply_unixerror(req, ERRDOS, ERRbadpath);
3752 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3753 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3754 reply_unixerror(req, ERRDOS, ERRbadpath);
3758 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3759 delete_pending = get_delete_on_close_flag(fileid);
3760 if (delete_pending) {
3761 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3766 nlink = sbuf.st_nlink;
3768 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3769 /* NTFS does not seem to count ".." */
3773 if ((nlink > 0) && delete_pending) {
3777 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3778 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3782 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3783 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3785 p = strrchr_m(fname,'/');
3791 mode = dos_mode(conn,fname,&sbuf);
3793 mode = FILE_ATTRIBUTE_NORMAL;
3795 fullpathname = fname;
3797 file_size = get_file_size(sbuf);
3799 /* Pull out any data sent here before we realloc. */
3800 switch (info_level) {
3801 case SMB_INFO_QUERY_EAS_FROM_LIST:
3803 /* Pull any EA list from the data portion. */
3806 if (total_data < 4) {
3808 req, NT_STATUS_INVALID_PARAMETER);
3811 ea_size = IVAL(pdata,0);
3813 if (total_data > 0 && ea_size != total_data) {
3814 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3815 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3817 req, NT_STATUS_INVALID_PARAMETER);
3821 if (!lp_ea_support(SNUM(conn))) {
3822 reply_doserror(req, ERRDOS,
3823 ERReasnotsupported);
3827 /* Pull out the list of names. */
3828 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3831 req, NT_STATUS_INVALID_PARAMETER);
3837 case SMB_QUERY_POSIX_LOCK:
3839 if (fsp == NULL || fsp->fh->fd == -1) {
3840 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3844 if (total_data != POSIX_LOCK_DATA_SIZE) {
3846 req, NT_STATUS_INVALID_PARAMETER);
3850 /* Copy the lock range data. */
3851 lock_data = (char *)TALLOC_MEMDUP(
3852 ctx, pdata, total_data);
3854 reply_nterror(req, NT_STATUS_NO_MEMORY);
3862 *pparams = (char *)SMB_REALLOC(*pparams,2);
3863 if (*pparams == NULL) {
3864 reply_nterror(req, NT_STATUS_NO_MEMORY);
3869 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3870 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3871 if (*ppdata == NULL ) {
3872 reply_nterror(req, NT_STATUS_NO_MEMORY);
3877 dend = dstart + data_size - 1;
3879 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3880 mtime_ts = get_mtimespec(&sbuf);
3881 atime_ts = get_atimespec(&sbuf);
3883 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3886 if (!null_timespec(fsp->pending_modtime)) {
3887 /* the pending modtime overrides the current modtime */
3888 mtime_ts = fsp->pending_modtime;
3892 /* Do we have this path open ? */
3893 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3894 fsp1 = file_find_di_first(fileid);
3895 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3896 /* the pending modtime overrides the current modtime */
3897 mtime_ts = fsp1->pending_modtime;
3899 if (fsp1 && fsp1->initial_allocation_size) {
3900 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3904 if (lp_dos_filetime_resolution(SNUM(conn))) {
3905 dos_filetime_timespec(&create_time_ts);
3906 dos_filetime_timespec(&mtime_ts);
3907 dos_filetime_timespec(&atime_ts);
3910 create_time = convert_timespec_to_time_t(create_time_ts);
3911 mtime = convert_timespec_to_time_t(mtime_ts);
3912 atime = convert_timespec_to_time_t(atime_ts);
3914 /* NT expects the name to be in an exact form of the *full*
3915 filename. See the trans2 torture test */
3916 if (ISDOT(base_name)) {
3917 dos_fname = talloc_strdup(ctx, "\\");
3919 reply_nterror(req, NT_STATUS_NO_MEMORY);
3923 dos_fname = talloc_asprintf(ctx,
3927 reply_nterror(req, NT_STATUS_NO_MEMORY);
3930 string_replace(dos_fname, '/', '\\');
3933 switch (info_level) {
3934 case SMB_INFO_STANDARD:
3935 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3937 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3938 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3939 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3940 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3941 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3942 SSVAL(pdata,l1_attrFile,mode);
3945 case SMB_INFO_QUERY_EA_SIZE:
3947 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3948 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3950 srv_put_dos_date2(pdata,0,create_time);
3951 srv_put_dos_date2(pdata,4,atime);
3952 srv_put_dos_date2(pdata,8,mtime); /* write time */
3953 SIVAL(pdata,12,(uint32)file_size);
3954 SIVAL(pdata,16,(uint32)allocation_size);
3955 SSVAL(pdata,20,mode);
3956 SIVAL(pdata,22,ea_size);
3960 case SMB_INFO_IS_NAME_VALID:
3961 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3962 if (tran_call == TRANSACT2_QFILEINFO) {
3963 /* os/2 needs this ? really ?*/
3964 reply_doserror(req, ERRDOS, ERRbadfunc);
3971 case SMB_INFO_QUERY_EAS_FROM_LIST:
3973 size_t total_ea_len = 0;
3974 struct ea_list *ea_file_list = NULL;
3976 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3978 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3979 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3981 if (!ea_list || (total_ea_len > data_size)) {
3983 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3987 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3991 case SMB_INFO_QUERY_ALL_EAS:
3993 /* We have data_size bytes to put EA's into. */
3994 size_t total_ea_len = 0;
3996 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3998 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3999 if (!ea_list || (total_ea_len > data_size)) {
4001 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4005 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4009 case SMB_FILE_BASIC_INFORMATION:
4010 case SMB_QUERY_FILE_BASIC_INFO:
4012 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4013 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4014 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4016 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4020 put_long_date_timespec(pdata,create_time_ts);
4021 put_long_date_timespec(pdata+8,atime_ts);
4022 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4023 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4024 SIVAL(pdata,32,mode);
4026 DEBUG(5,("SMB_QFBI - "));
4027 DEBUG(5,("create: %s ", ctime(&create_time)));
4028 DEBUG(5,("access: %s ", ctime(&atime)));
4029 DEBUG(5,("write: %s ", ctime(&mtime)));
4030 DEBUG(5,("change: %s ", ctime(&mtime)));
4031 DEBUG(5,("mode: %x\n", mode));
4034 case SMB_FILE_STANDARD_INFORMATION:
4035 case SMB_QUERY_FILE_STANDARD_INFO:
4037 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4039 SOFF_T(pdata,0,allocation_size);
4040 SOFF_T(pdata,8,file_size);
4041 SIVAL(pdata,16,nlink);
4042 SCVAL(pdata,20,delete_pending?1:0);
4043 SCVAL(pdata,21,(mode&aDIR)?1:0);
4044 SSVAL(pdata,22,0); /* Padding. */
4047 case SMB_FILE_EA_INFORMATION:
4048 case SMB_QUERY_FILE_EA_INFO:
4050 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4051 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4053 SIVAL(pdata,0,ea_size);
4057 /* Get the 8.3 name - used if NT SMB was negotiated. */
4058 case SMB_QUERY_FILE_ALT_NAME_INFO:
4059 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4061 char mangled_name[13];
4062 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4063 if (!name_to_8_3(base_name,mangled_name,
4064 True,conn->params)) {
4067 NT_STATUS_NO_MEMORY);
4069 len = srvstr_push(dstart, req->flags2,
4070 pdata+4, mangled_name,
4071 PTR_DIFF(dend, pdata+4),
4073 data_size = 4 + len;
4078 case SMB_QUERY_FILE_NAME_INFO:
4080 this must be *exactly* right for ACLs on mapped drives to work
4082 len = srvstr_push(dstart, req->flags2,
4084 PTR_DIFF(dend, pdata+4),
4086 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4087 data_size = 4 + len;
4091 case SMB_FILE_ALLOCATION_INFORMATION:
4092 case SMB_QUERY_FILE_ALLOCATION_INFO:
4093 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4095 SOFF_T(pdata,0,allocation_size);
4098 case SMB_FILE_END_OF_FILE_INFORMATION:
4099 case SMB_QUERY_FILE_END_OF_FILEINFO:
4100 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4102 SOFF_T(pdata,0,file_size);
4105 case SMB_QUERY_FILE_ALL_INFO:
4106 case SMB_FILE_ALL_INFORMATION:
4108 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4109 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4110 put_long_date_timespec(pdata,create_time_ts);
4111 put_long_date_timespec(pdata+8,atime_ts);
4112 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4113 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4114 SIVAL(pdata,32,mode);
4115 SIVAL(pdata,36,0); /* padding. */
4117 SOFF_T(pdata,0,allocation_size);
4118 SOFF_T(pdata,8,file_size);
4119 SIVAL(pdata,16,nlink);
4120 SCVAL(pdata,20,delete_pending);
4121 SCVAL(pdata,21,(mode&aDIR)?1:0);
4124 SIVAL(pdata,0,ea_size);
4125 pdata += 4; /* EA info */
4126 len = srvstr_push(dstart, req->flags2,
4128 PTR_DIFF(dend, pdata+4),
4132 data_size = PTR_DIFF(pdata,(*ppdata));
4135 case SMB_FILE_INTERNAL_INFORMATION:
4136 /* This should be an index number - looks like
4139 I think this causes us to fail the IFSKIT
4140 BasicFileInformationTest. -tpot */
4142 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4143 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4144 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4148 case SMB_FILE_ACCESS_INFORMATION:
4149 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4150 SIVAL(pdata,0,access_mask);
4154 case SMB_FILE_NAME_INFORMATION:
4155 /* Pathname with leading '\'. */
4158 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4159 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4160 SIVAL(pdata,0,byte_len);
4161 data_size = 4 + byte_len;
4165 case SMB_FILE_DISPOSITION_INFORMATION:
4166 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4168 SCVAL(pdata,0,delete_pending);
4171 case SMB_FILE_POSITION_INFORMATION:
4172 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4174 SOFF_T(pdata,0,pos);
4177 case SMB_FILE_MODE_INFORMATION:
4178 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4179 SIVAL(pdata,0,mode);
4183 case SMB_FILE_ALIGNMENT_INFORMATION:
4184 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4185 SIVAL(pdata,0,0); /* No alignment needed. */
4191 * NT4 server just returns "invalid query" to this - if we try to answer
4192 * it then NTws gets a BSOD! (tridge).
4193 * W2K seems to want this. JRA.
4195 case SMB_QUERY_FILE_STREAM_INFO:
4197 case SMB_FILE_STREAM_INFORMATION:
4198 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4202 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4203 SIVAL(pdata,0,0); /* ??? */
4204 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4205 SOFF_T(pdata,8,file_size);
4206 SOFF_T(pdata,16,allocation_size);
4207 data_size = 24 + byte_len;
4211 case SMB_QUERY_COMPRESSION_INFO:
4212 case SMB_FILE_COMPRESSION_INFORMATION:
4213 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4214 SOFF_T(pdata,0,file_size);
4215 SIVAL(pdata,8,0); /* ??? */
4216 SIVAL(pdata,12,0); /* ??? */
4220 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4221 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4222 put_long_date_timespec(pdata,create_time_ts);
4223 put_long_date_timespec(pdata+8,atime_ts);
4224 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4225 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4226 SOFF_T(pdata,32,allocation_size);
4227 SOFF_T(pdata,40,file_size);
4228 SIVAL(pdata,48,mode);
4229 SIVAL(pdata,52,0); /* ??? */
4233 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4234 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4235 SIVAL(pdata,0,mode);
4241 * CIFS UNIX Extensions.
4244 case SMB_QUERY_FILE_UNIX_BASIC:
4246 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4247 data_size = PTR_DIFF(pdata,(*ppdata));
4251 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4253 for (i=0; i<100; i++)
4254 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4260 case SMB_QUERY_FILE_UNIX_INFO2:
4262 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4263 data_size = PTR_DIFF(pdata,(*ppdata));
4267 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4269 for (i=0; i<100; i++)
4270 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4276 case SMB_QUERY_FILE_UNIX_LINK:
4278 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4281 reply_nterror(req, NT_STATUS_NO_MEMORY);
4285 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4287 if(!S_ISLNK(sbuf.st_mode)) {
4288 reply_unixerror(req, ERRSRV,
4293 reply_unixerror(req, ERRDOS, ERRbadlink);
4296 len = SMB_VFS_READLINK(conn,fullpathname,
4299 reply_unixerror(req, ERRDOS,
4304 len = srvstr_push(dstart, req->flags2,
4306 PTR_DIFF(dend, pdata),
4309 data_size = PTR_DIFF(pdata,(*ppdata));
4314 #if defined(HAVE_POSIX_ACLS)
4315 case SMB_QUERY_POSIX_ACL:
4317 SMB_ACL_T file_acl = NULL;
4318 SMB_ACL_T def_acl = NULL;
4319 uint16 num_file_acls = 0;
4320 uint16 num_def_acls = 0;
4322 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4323 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4325 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4328 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4329 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4333 NT_STATUS_NOT_IMPLEMENTED);
4337 if (S_ISDIR(sbuf.st_mode)) {
4338 if (fsp && fsp->is_directory) {
4339 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4341 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4343 def_acl = free_empty_sys_acl(conn, def_acl);
4346 num_file_acls = count_acl_entries(conn, file_acl);
4347 num_def_acls = count_acl_entries(conn, def_acl);
4349 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4350 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4352 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4353 SMB_POSIX_ACL_HEADER_SIZE) ));
4355 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4358 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4362 NT_STATUS_BUFFER_TOO_SMALL);
4366 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4367 SSVAL(pdata,2,num_file_acls);
4368 SSVAL(pdata,4,num_def_acls);
4369 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4371 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4374 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4377 req, NT_STATUS_INTERNAL_ERROR);
4380 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4382 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4385 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4389 NT_STATUS_INTERNAL_ERROR);
4394 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4397 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4399 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4405 case SMB_QUERY_POSIX_LOCK:
4407 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4409 SMB_BIG_UINT offset;
4411 enum brl_type lock_type;
4413 if (total_data != POSIX_LOCK_DATA_SIZE) {
4415 req, NT_STATUS_INVALID_PARAMETER);
4419 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4420 case POSIX_LOCK_TYPE_READ:
4421 lock_type = READ_LOCK;
4423 case POSIX_LOCK_TYPE_WRITE:
4424 lock_type = WRITE_LOCK;
4426 case POSIX_LOCK_TYPE_UNLOCK:
4428 /* There's no point in asking for an unlock... */
4431 NT_STATUS_INVALID_PARAMETER);
4435 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4436 #if defined(HAVE_LONGLONG)
4437 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4438 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4439 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4440 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4441 #else /* HAVE_LONGLONG */
4442 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4443 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4444 #endif /* HAVE_LONGLONG */
4446 status = query_lock(fsp,
4453 if (ERROR_WAS_LOCK_DENIED(status)) {
4454 /* Here we need to report who has it locked... */
4455 data_size = POSIX_LOCK_DATA_SIZE;
4457 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4458 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4459 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4460 #if defined(HAVE_LONGLONG)
4461 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4462 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4463 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4464 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4465 #else /* HAVE_LONGLONG */
4466 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4467 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4468 #endif /* HAVE_LONGLONG */
4470 } else if (NT_STATUS_IS_OK(status)) {
4471 /* For success we just return a copy of what we sent
4472 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4473 data_size = POSIX_LOCK_DATA_SIZE;
4474 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4475 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4477 reply_nterror(req, status);
4484 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4488 send_trans2_replies(req, params, param_size, *ppdata, data_size,
4494 /****************************************************************************
4495 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4497 ****************************************************************************/
4499 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4500 connection_struct *conn,
4501 const char *oldname_in,
4502 const char *newname_in)
4504 SMB_STRUCT_STAT sbuf1, sbuf2;
4505 char *last_component_oldname = NULL;
4506 char *last_component_newname = NULL;
4507 char *oldname = NULL;
4508 char *newname = NULL;
4509 NTSTATUS status = NT_STATUS_OK;
4514 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4515 &last_component_oldname, &sbuf1);
4516 if (!NT_STATUS_IS_OK(status)) {
4520 status = check_name(conn, oldname);
4521 if (!NT_STATUS_IS_OK(status)) {
4525 /* source must already exist. */
4526 if (!VALID_STAT(sbuf1)) {
4527 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4530 status = unix_convert(ctx, conn, newname_in, False, &newname,
4531 &last_component_newname, &sbuf2);
4532 if (!NT_STATUS_IS_OK(status)) {
4536 status = check_name(conn, newname);
4537 if (!NT_STATUS_IS_OK(status)) {
4541 /* Disallow if newname already exists. */
4542 if (VALID_STAT(sbuf2)) {
4543 return NT_STATUS_OBJECT_NAME_COLLISION;
4546 /* No links from a directory. */
4547 if (S_ISDIR(sbuf1.st_mode)) {
4548 return NT_STATUS_FILE_IS_A_DIRECTORY;
4551 /* Ensure this is within the share. */
4552 status = check_reduced_name(conn, oldname);
4553 if (!NT_STATUS_IS_OK(status)) {
4557 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4559 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4560 status = map_nt_error_from_unix(errno);
4561 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4562 nt_errstr(status), newname, oldname));
4568 /****************************************************************************
4569 Deal with setting the time from any of the setfilepathinfo functions.
4570 ****************************************************************************/
4572 static NTSTATUS smb_set_file_time(connection_struct *conn,
4575 const SMB_STRUCT_STAT *psbuf,
4576 struct timespec ts[2],
4577 bool setting_write_time)
4580 FILE_NOTIFY_CHANGE_LAST_ACCESS
4581 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4583 if (!VALID_STAT(*psbuf)) {
4584 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4587 /* get some defaults (no modifications) if any info is zero or -1. */
4588 if (null_timespec(ts[0])) {
4589 ts[0] = get_atimespec(psbuf);
4590 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4593 if (null_timespec(ts[1])) {
4594 ts[1] = get_mtimespec(psbuf);
4595 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4598 if (!setting_write_time) {
4599 /* ts[1] comes from change time, not write time. */
4600 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4603 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4604 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4607 * Try and set the times of this file if
4608 * they are different from the current values.
4612 struct timespec mts = get_mtimespec(psbuf);
4613 struct timespec ats = get_atimespec(psbuf);
4614 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4615 return NT_STATUS_OK;
4621 * This was a setfileinfo on an open file.
4622 * NT does this a lot. We also need to
4623 * set the time here, as it can be read by
4624 * FindFirst/FindNext and with the patch for bug #2045
4625 * in smbd/fileio.c it ensures that this timestamp is
4626 * kept sticky even after a write. We save the request
4627 * away and will set it on file close and after a write. JRA.
4630 if (!null_timespec(ts[1])) {
4631 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4632 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4633 fsp_set_pending_modtime(fsp, ts[1]);
4637 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4639 if(file_ntimes(conn, fname, ts)!=0) {
4640 return map_nt_error_from_unix(errno);
4642 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4644 return NT_STATUS_OK;
4647 /****************************************************************************
4648 Deal with setting the dosmode from any of the setfilepathinfo functions.
4649 ****************************************************************************/
4651 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4653 SMB_STRUCT_STAT *psbuf,
4656 if (!VALID_STAT(*psbuf)) {
4657 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4661 if (S_ISDIR(psbuf->st_mode)) {
4668 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4670 /* check the mode isn't different, before changing it */
4671 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4673 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4674 fname, (unsigned int)dosmode ));
4676 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4677 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4678 fname, strerror(errno)));
4679 return map_nt_error_from_unix(errno);
4682 return NT_STATUS_OK;
4685 /****************************************************************************
4686 Deal with setting the size from any of the setfilepathinfo functions.
4687 ****************************************************************************/
4689 static NTSTATUS smb_set_file_size(connection_struct *conn,
4690 struct smb_request *req,
4693 SMB_STRUCT_STAT *psbuf,
4696 NTSTATUS status = NT_STATUS_OK;
4697 files_struct *new_fsp = NULL;
4699 if (!VALID_STAT(*psbuf)) {
4700 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4703 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4705 if (size == get_file_size(*psbuf)) {
4706 return NT_STATUS_OK;
4709 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4710 fname, (double)size ));
4712 if (fsp && fsp->fh->fd != -1) {
4713 /* Handle based call. */
4714 if (vfs_set_filelen(fsp, size) == -1) {
4715 return map_nt_error_from_unix(errno);
4717 return NT_STATUS_OK;
4720 status = open_file_ntcreate(conn, req, fname, psbuf,
4722 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4725 FILE_ATTRIBUTE_NORMAL,
4726 FORCE_OPLOCK_BREAK_TO_NONE,
4729 if (!NT_STATUS_IS_OK(status)) {
4730 /* NB. We check for open_was_deferred in the caller. */
4734 if (vfs_set_filelen(new_fsp, size) == -1) {
4735 status = map_nt_error_from_unix(errno);
4736 close_file(new_fsp,NORMAL_CLOSE);
4740 close_file(new_fsp,NORMAL_CLOSE);
4741 return NT_STATUS_OK;
4744 /****************************************************************************
4745 Deal with SMB_INFO_SET_EA.
4746 ****************************************************************************/
4748 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4754 struct ea_list *ea_list = NULL;
4755 TALLOC_CTX *ctx = NULL;
4756 NTSTATUS status = NT_STATUS_OK;
4758 if (total_data < 10) {
4760 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4761 length. They seem to have no effect. Bug #3212. JRA */
4763 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4764 /* We're done. We only get EA info in this call. */
4765 return NT_STATUS_OK;
4768 return NT_STATUS_INVALID_PARAMETER;
4771 if (IVAL(pdata,0) > total_data) {
4772 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4773 IVAL(pdata,0), (unsigned int)total_data));
4774 return NT_STATUS_INVALID_PARAMETER;
4777 ctx = talloc_init("SMB_INFO_SET_EA");
4779 return NT_STATUS_NO_MEMORY;
4781 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4783 talloc_destroy(ctx);
4784 return NT_STATUS_INVALID_PARAMETER;
4786 status = set_ea(conn, fsp, fname, ea_list);
4787 talloc_destroy(ctx);
4792 /****************************************************************************
4793 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4794 ****************************************************************************/
4796 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4801 SMB_STRUCT_STAT *psbuf)
4803 NTSTATUS status = NT_STATUS_OK;
4804 bool delete_on_close;
4807 if (total_data < 1) {
4808 return NT_STATUS_INVALID_PARAMETER;
4812 return NT_STATUS_INVALID_HANDLE;
4815 delete_on_close = (CVAL(pdata,0) ? True : False);
4816 dosmode = dos_mode(conn, fname, psbuf);
4818 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4819 "delete_on_close = %u\n",
4821 (unsigned int)dosmode,
4822 (unsigned int)delete_on_close ));
4824 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4826 if (!NT_STATUS_IS_OK(status)) {
4830 /* The set is across all open files on this dev/inode pair. */
4831 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4832 return NT_STATUS_ACCESS_DENIED;
4834 return NT_STATUS_OK;
4837 /****************************************************************************
4838 Deal with SMB_FILE_POSITION_INFORMATION.
4839 ****************************************************************************/
4841 static NTSTATUS smb_file_position_information(connection_struct *conn,
4846 SMB_BIG_UINT position_information;
4848 if (total_data < 8) {
4849 return NT_STATUS_INVALID_PARAMETER;
4853 /* Ignore on pathname based set. */
4854 return NT_STATUS_OK;
4857 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4858 #ifdef LARGE_SMB_OFF_T
4859 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4860 #else /* LARGE_SMB_OFF_T */
4861 if (IVAL(pdata,4) != 0) {
4862 /* more than 32 bits? */
4863 return NT_STATUS_INVALID_PARAMETER;
4865 #endif /* LARGE_SMB_OFF_T */
4867 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4868 fsp->fsp_name, (double)position_information ));
4869 fsp->fh->position_information = position_information;
4870 return NT_STATUS_OK;
4873 /****************************************************************************
4874 Deal with SMB_FILE_MODE_INFORMATION.
4875 ****************************************************************************/
4877 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4883 if (total_data < 4) {
4884 return NT_STATUS_INVALID_PARAMETER;
4886 mode = IVAL(pdata,0);
4887 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4888 return NT_STATUS_INVALID_PARAMETER;
4890 return NT_STATUS_OK;
4893 /****************************************************************************
4894 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4895 ****************************************************************************/
4897 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4898 struct smb_request *req,
4903 char *link_target = NULL;
4904 const char *newname = fname;
4905 NTSTATUS status = NT_STATUS_OK;
4906 TALLOC_CTX *ctx = talloc_tos();
4908 /* Set a symbolic link. */
4909 /* Don't allow this if follow links is false. */
4911 if (total_data == 0) {
4912 return NT_STATUS_INVALID_PARAMETER;
4915 if (!lp_symlinks(SNUM(conn))) {
4916 return NT_STATUS_ACCESS_DENIED;
4919 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
4920 total_data, STR_TERMINATE);
4923 return NT_STATUS_INVALID_PARAMETER;
4926 /* !widelinks forces the target path to be within the share. */
4927 /* This means we can interpret the target as a pathname. */
4928 if (!lp_widelinks(SNUM(conn))) {
4929 char *rel_name = NULL;
4930 char *last_dirp = NULL;
4932 if (*link_target == '/') {
4933 /* No absolute paths allowed. */
4934 return NT_STATUS_ACCESS_DENIED;
4936 rel_name = talloc_strdup(ctx,newname);
4938 return NT_STATUS_NO_MEMORY;
4940 last_dirp = strrchr_m(rel_name, '/');
4942 last_dirp[1] = '\0';
4944 rel_name = talloc_strdup(ctx,"./");
4946 return NT_STATUS_NO_MEMORY;
4949 rel_name = talloc_asprintf_append(rel_name,
4953 return NT_STATUS_NO_MEMORY;
4956 status = check_name(conn, rel_name);
4957 if (!NT_STATUS_IS_OK(status)) {
4962 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4963 newname, link_target ));
4965 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4966 return map_nt_error_from_unix(errno);
4969 return NT_STATUS_OK;
4972 /****************************************************************************
4973 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4974 ****************************************************************************/
4976 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4977 struct smb_request *req,
4978 const char *pdata, int total_data,
4981 char *oldname = NULL;
4982 TALLOC_CTX *ctx = talloc_tos();
4983 NTSTATUS status = NT_STATUS_OK;
4985 /* Set a hard link. */
4986 if (total_data == 0) {
4987 return NT_STATUS_INVALID_PARAMETER;
4990 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
4991 total_data, STR_TERMINATE, &status);
4992 if (!NT_STATUS_IS_OK(status)) {
4996 status = resolve_dfspath(ctx, conn,
4997 req->flags2 & FLAGS2_DFS_PATHNAMES,
5000 if (!NT_STATUS_IS_OK(status)) {
5004 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5007 return hardlink_internals(ctx, conn, oldname, fname);
5010 /****************************************************************************
5011 Deal with SMB_FILE_RENAME_INFORMATION.
5012 ****************************************************************************/
5014 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5015 struct smb_request *req,
5024 char *newname = NULL;
5025 char *base_name = NULL;
5026 bool dest_has_wcard = False;
5027 NTSTATUS status = NT_STATUS_OK;
5029 TALLOC_CTX *ctx = talloc_tos();
5031 if (total_data < 13) {
5032 return NT_STATUS_INVALID_PARAMETER;
5035 overwrite = (CVAL(pdata,0) ? True : False);
5036 root_fid = IVAL(pdata,4);
5037 len = IVAL(pdata,8);
5039 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5040 return NT_STATUS_INVALID_PARAMETER;
5043 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5046 if (!NT_STATUS_IS_OK(status)) {
5050 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5053 status = resolve_dfspath_wcard(ctx, conn,
5054 req->flags2 & FLAGS2_DFS_PATHNAMES,
5058 if (!NT_STATUS_IS_OK(status)) {
5062 /* Check the new name has no '/' characters. */
5063 if (strchr_m(newname, '/')) {
5064 return NT_STATUS_NOT_SUPPORTED;
5067 /* Create the base directory. */
5068 base_name = talloc_strdup(ctx, fname);
5070 return NT_STATUS_NO_MEMORY;
5072 p = strrchr_m(base_name, '/');
5076 base_name = talloc_strdup(ctx, "./");
5078 return NT_STATUS_NO_MEMORY;
5081 /* Append the new name. */
5082 base_name = talloc_asprintf_append(base_name,
5086 return NT_STATUS_NO_MEMORY;
5090 SMB_STRUCT_STAT sbuf;
5091 char *newname_last_component = NULL;
5095 status = unix_convert(ctx, conn, newname, False,
5097 &newname_last_component,
5100 /* If an error we expect this to be
5101 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5103 if (!NT_STATUS_IS_OK(status)
5104 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5109 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5110 fsp->fnum, fsp->fsp_name, base_name ));
5111 status = rename_internals_fsp(conn, fsp, base_name,
5112 newname_last_component, 0,
5115 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5116 fname, base_name ));
5117 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5118 overwrite, False, dest_has_wcard);
5124 /****************************************************************************
5125 Deal with SMB_SET_POSIX_ACL.
5126 ****************************************************************************/
5128 #if defined(HAVE_POSIX_ACLS)
5129 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5134 SMB_STRUCT_STAT *psbuf)
5136 uint16 posix_acl_version;
5137 uint16 num_file_acls;
5138 uint16 num_def_acls;
5139 bool valid_file_acls = True;
5140 bool valid_def_acls = True;
5142 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5143 return NT_STATUS_INVALID_PARAMETER;
5145 posix_acl_version = SVAL(pdata,0);
5146 num_file_acls = SVAL(pdata,2);
5147 num_def_acls = SVAL(pdata,4);
5149 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5150 valid_file_acls = False;
5154 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5155 valid_def_acls = False;
5159 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5160 return NT_STATUS_INVALID_PARAMETER;
5163 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5164 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5165 return NT_STATUS_INVALID_PARAMETER;
5168 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5169 fname ? fname : fsp->fsp_name,
5170 (unsigned int)num_file_acls,
5171 (unsigned int)num_def_acls));
5173 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5174 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5175 return map_nt_error_from_unix(errno);
5178 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5179 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5180 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5181 return map_nt_error_from_unix(errno);
5183 return NT_STATUS_OK;
5187 /****************************************************************************
5188 Deal with SMB_SET_POSIX_LOCK.
5189 ****************************************************************************/
5191 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5199 SMB_BIG_UINT offset;
5201 bool blocking_lock = False;
5202 enum brl_type lock_type;
5203 NTSTATUS status = NT_STATUS_OK;
5205 if (fsp == NULL || fsp->fh->fd == -1) {
5206 return NT_STATUS_INVALID_HANDLE;
5209 if (total_data != POSIX_LOCK_DATA_SIZE) {
5210 return NT_STATUS_INVALID_PARAMETER;
5213 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5214 case POSIX_LOCK_TYPE_READ:
5215 lock_type = READ_LOCK;
5217 case POSIX_LOCK_TYPE_WRITE:
5218 /* Return the right POSIX-mappable error code for files opened read-only. */
5219 if (!fsp->can_write) {
5220 return NT_STATUS_INVALID_HANDLE;
5222 lock_type = WRITE_LOCK;
5224 case POSIX_LOCK_TYPE_UNLOCK:
5225 lock_type = UNLOCK_LOCK;
5228 return NT_STATUS_INVALID_PARAMETER;
5231 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5232 blocking_lock = False;
5233 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5234 blocking_lock = True;
5236 return NT_STATUS_INVALID_PARAMETER;
5239 if (!lp_blocking_locks(SNUM(conn))) {
5240 blocking_lock = False;
5243 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5244 #if defined(HAVE_LONGLONG)
5245 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5246 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5247 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5248 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5249 #else /* HAVE_LONGLONG */
5250 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5251 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5252 #endif /* HAVE_LONGLONG */
5254 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5255 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5257 (unsigned int)lock_type,
5258 (unsigned int)lock_pid,
5262 if (lock_type == UNLOCK_LOCK) {
5263 status = do_unlock(smbd_messaging_context(),
5270 uint32 block_smbpid;
5272 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5283 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5285 * A blocking lock was requested. Package up
5286 * this smb into a queued request and push it
5287 * onto the blocking lock queue.
5289 if(push_blocking_lock_request(br_lck,
5290 (char *)inbuf, length,
5292 -1, /* infinite timeout. */
5300 TALLOC_FREE(br_lck);
5304 TALLOC_FREE(br_lck);
5310 /****************************************************************************
5311 Deal with SMB_INFO_STANDARD.
5312 ****************************************************************************/
5314 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5319 const SMB_STRUCT_STAT *psbuf)
5321 struct timespec ts[2];
5323 if (total_data < 12) {
5324 return NT_STATUS_INVALID_PARAMETER;
5328 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5330 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5332 DEBUG(10,("smb_set_info_standard: file %s\n",
5333 fname ? fname : fsp->fsp_name ));
5335 return smb_set_file_time(conn,
5343 /****************************************************************************
5344 Deal with SMB_SET_FILE_BASIC_INFO.
5345 ****************************************************************************/
5347 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5352 SMB_STRUCT_STAT *psbuf)
5354 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5355 struct timespec write_time;
5356 struct timespec changed_time;
5358 struct timespec ts[2];
5359 NTSTATUS status = NT_STATUS_OK;
5360 bool setting_write_time = true;
5362 if (total_data < 36) {
5363 return NT_STATUS_INVALID_PARAMETER;
5366 /* Set the attributes */
5367 dosmode = IVAL(pdata,32);
5368 status = smb_set_file_dosmode(conn,
5372 if (!NT_STATUS_IS_OK(status)) {
5376 /* Ignore create time at offset pdata. */
5379 ts[0] = interpret_long_date(pdata+8);
5381 write_time = interpret_long_date(pdata+16);
5382 changed_time = interpret_long_date(pdata+24);
5385 ts[1] = timespec_min(&write_time, &changed_time);
5387 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5391 /* Prefer a defined time to an undefined one. */
5392 if (null_timespec(ts[1])) {
5393 if (null_timespec(write_time)) {
5394 ts[1] = changed_time;
5395 setting_write_time = false;
5401 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5402 fname ? fname : fsp->fsp_name ));
5404 return smb_set_file_time(conn,
5409 setting_write_time);
5412 /****************************************************************************
5413 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5414 ****************************************************************************/
5416 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5417 struct smb_request *req,
5422 SMB_STRUCT_STAT *psbuf)
5424 SMB_BIG_UINT allocation_size = 0;
5425 NTSTATUS status = NT_STATUS_OK;
5426 files_struct *new_fsp = NULL;
5428 if (!VALID_STAT(*psbuf)) {
5429 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5432 if (total_data < 8) {
5433 return NT_STATUS_INVALID_PARAMETER;
5436 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5437 #ifdef LARGE_SMB_OFF_T
5438 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5439 #else /* LARGE_SMB_OFF_T */
5440 if (IVAL(pdata,4) != 0) {
5441 /* more than 32 bits? */
5442 return NT_STATUS_INVALID_PARAMETER;
5444 #endif /* LARGE_SMB_OFF_T */
5446 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5447 fname, (double)allocation_size ));
5449 if (allocation_size) {
5450 allocation_size = smb_roundup(conn, allocation_size);
5453 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5454 fname, (double)allocation_size ));
5456 if (fsp && fsp->fh->fd != -1) {
5457 /* Open file handle. */
5458 /* Only change if needed. */
5459 if (allocation_size != get_file_size(*psbuf)) {
5460 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5461 return map_nt_error_from_unix(errno);
5464 /* But always update the time. */
5465 if (null_timespec(fsp->pending_modtime)) {
5467 * This is equivalent to a write. Ensure it's seen immediately
5468 * if there are no pending writes.
5470 set_filetime(fsp->conn, fsp->fsp_name,
5471 timespec_current());
5473 return NT_STATUS_OK;
5476 /* Pathname or stat or directory file. */
5478 status = open_file_ntcreate(conn, req, fname, psbuf,
5480 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5483 FILE_ATTRIBUTE_NORMAL,
5484 FORCE_OPLOCK_BREAK_TO_NONE,
5487 if (!NT_STATUS_IS_OK(status)) {
5488 /* NB. We check for open_was_deferred in the caller. */
5492 /* Only change if needed. */
5493 if (allocation_size != get_file_size(*psbuf)) {
5494 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5495 status = map_nt_error_from_unix(errno);
5496 close_file(new_fsp,NORMAL_CLOSE);
5501 /* Changing the allocation size should set the last mod time. */
5502 /* Don't need to call set_filetime as this will be flushed on
5505 fsp_set_pending_modtime(new_fsp, timespec_current());
5507 close_file(new_fsp,NORMAL_CLOSE);
5508 return NT_STATUS_OK;
5511 /****************************************************************************
5512 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5513 ****************************************************************************/
5515 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5516 struct smb_request *req,
5521 SMB_STRUCT_STAT *psbuf)
5525 if (total_data < 8) {
5526 return NT_STATUS_INVALID_PARAMETER;
5529 size = IVAL(pdata,0);
5530 #ifdef LARGE_SMB_OFF_T
5531 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5532 #else /* LARGE_SMB_OFF_T */
5533 if (IVAL(pdata,4) != 0) {
5534 /* more than 32 bits? */
5535 return NT_STATUS_INVALID_PARAMETER;
5537 #endif /* LARGE_SMB_OFF_T */
5538 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5539 "file %s to %.0f\n", fname, (double)size ));
5541 return smb_set_file_size(conn, req,
5548 /****************************************************************************
5549 Allow a UNIX info mknod.
5550 ****************************************************************************/
5552 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5556 SMB_STRUCT_STAT *psbuf)
5558 uint32 file_type = IVAL(pdata,56);
5559 #if defined(HAVE_MAKEDEV)
5560 uint32 dev_major = IVAL(pdata,60);
5561 uint32 dev_minor = IVAL(pdata,68);
5563 SMB_DEV_T dev = (SMB_DEV_T)0;
5564 uint32 raw_unixmode = IVAL(pdata,84);
5568 if (total_data < 100) {
5569 return NT_STATUS_INVALID_PARAMETER;
5572 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5573 if (!NT_STATUS_IS_OK(status)) {
5577 #if defined(HAVE_MAKEDEV)
5578 dev = makedev(dev_major, dev_minor);
5581 switch (file_type) {
5582 #if defined(S_IFIFO)
5583 case UNIX_TYPE_FIFO:
5584 unixmode |= S_IFIFO;
5587 #if defined(S_IFSOCK)
5588 case UNIX_TYPE_SOCKET:
5589 unixmode |= S_IFSOCK;
5592 #if defined(S_IFCHR)
5593 case UNIX_TYPE_CHARDEV:
5594 unixmode |= S_IFCHR;
5597 #if defined(S_IFBLK)
5598 case UNIX_TYPE_BLKDEV:
5599 unixmode |= S_IFBLK;
5603 return NT_STATUS_INVALID_PARAMETER;
5606 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5607 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5609 /* Ok - do the mknod. */
5610 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5611 return map_nt_error_from_unix(errno);
5614 /* If any of the other "set" calls fail we
5615 * don't want to end up with a half-constructed mknod.
5618 if (lp_inherit_perms(SNUM(conn))) {
5620 conn, parent_dirname(fname),
5624 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5625 status = map_nt_error_from_unix(errno);
5626 SMB_VFS_UNLINK(conn,fname);
5629 return NT_STATUS_OK;
5632 /****************************************************************************
5633 Deal with SMB_SET_FILE_UNIX_BASIC.
5634 ****************************************************************************/
5636 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5637 struct smb_request *req,
5642 SMB_STRUCT_STAT *psbuf)
5644 struct timespec ts[2];
5645 uint32 raw_unixmode;
5648 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5649 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5650 NTSTATUS status = NT_STATUS_OK;
5651 bool delete_on_fail = False;
5652 enum perm_type ptype;
5654 if (total_data < 100) {
5655 return NT_STATUS_INVALID_PARAMETER;
5658 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5659 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5660 size=IVAL(pdata,0); /* first 8 Bytes are size */
5661 #ifdef LARGE_SMB_OFF_T
5662 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5663 #else /* LARGE_SMB_OFF_T */
5664 if (IVAL(pdata,4) != 0) {
5665 /* more than 32 bits? */
5666 return NT_STATUS_INVALID_PARAMETER;
5668 #endif /* LARGE_SMB_OFF_T */
5671 ts[0] = interpret_long_date(pdata+24); /* access_time */
5672 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5673 set_owner = (uid_t)IVAL(pdata,40);
5674 set_grp = (gid_t)IVAL(pdata,48);
5675 raw_unixmode = IVAL(pdata,84);
5677 if (VALID_STAT(*psbuf)) {
5678 if (S_ISDIR(psbuf->st_mode)) {
5679 ptype = PERM_EXISTING_DIR;
5681 ptype = PERM_EXISTING_FILE;
5684 ptype = PERM_NEW_FILE;
5687 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5688 if (!NT_STATUS_IS_OK(status)) {
5692 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5693 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5694 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5696 if (!VALID_STAT(*psbuf)) {
5698 * The only valid use of this is to create character and block
5699 * devices, and named pipes. This is deprecated (IMHO) and
5700 * a new info level should be used for mknod. JRA.
5703 status = smb_unix_mknod(conn,
5708 if (!NT_STATUS_IS_OK(status)) {
5712 /* Ensure we don't try and change anything else. */
5713 raw_unixmode = SMB_MODE_NO_CHANGE;
5714 size = get_file_size(*psbuf);
5715 ts[0] = get_atimespec(psbuf);
5716 ts[1] = get_mtimespec(psbuf);
5718 * We continue here as we might want to change the
5721 delete_on_fail = True;
5725 /* Horrible backwards compatibility hack as an old server bug
5726 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5730 size = get_file_size(*psbuf);
5735 * Deal with the UNIX specific mode set.
5738 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5739 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5740 (unsigned int)unixmode, fname ));
5741 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5742 return map_nt_error_from_unix(errno);
5747 * Deal with the UNIX specific uid set.
5750 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5753 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5754 (unsigned int)set_owner, fname ));
5756 if (S_ISLNK(psbuf->st_mode)) {
5757 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5759 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5763 status = map_nt_error_from_unix(errno);
5764 if (delete_on_fail) {
5765 SMB_VFS_UNLINK(conn,fname);
5772 * Deal with the UNIX specific gid set.
5775 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5776 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5777 (unsigned int)set_owner, fname ));
5778 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5779 status = map_nt_error_from_unix(errno);
5780 if (delete_on_fail) {
5781 SMB_VFS_UNLINK(conn,fname);
5787 /* Deal with any size changes. */
5789 status = smb_set_file_size(conn, req,
5794 if (!NT_STATUS_IS_OK(status)) {
5798 /* Deal with any time changes. */
5800 return smb_set_file_time(conn,
5808 /****************************************************************************
5809 Deal with SMB_SET_FILE_UNIX_INFO2.
5810 ****************************************************************************/
5812 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5813 struct smb_request *req,
5818 SMB_STRUCT_STAT *psbuf)
5824 if (total_data < 116) {
5825 return NT_STATUS_INVALID_PARAMETER;
5828 /* Start by setting all the fields that are common between UNIX_BASIC
5831 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5833 if (!NT_STATUS_IS_OK(status)) {
5837 smb_fflags = IVAL(pdata, 108);
5838 smb_fmask = IVAL(pdata, 112);
5840 /* NB: We should only attempt to alter the file flags if the client
5841 * sends a non-zero mask.
5843 if (smb_fmask != 0) {
5844 int stat_fflags = 0;
5846 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5848 /* Client asked to alter a flag we don't understand. */
5849 return NT_STATUS_INVALID_PARAMETER;
5852 if (fsp && fsp->fh->fd != -1) {
5853 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5854 return NT_STATUS_NOT_SUPPORTED;
5856 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5857 return map_nt_error_from_unix(errno);
5862 /* XXX: need to add support for changing the create_time here. You
5863 * can do this for paths on Darwin with setattrlist(2). The right way
5864 * to hook this up is probably by extending the VFS utimes interface.
5867 return NT_STATUS_OK;
5870 /****************************************************************************
5871 Create a directory with POSIX semantics.
5872 ****************************************************************************/
5874 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5875 struct smb_request *req,
5879 SMB_STRUCT_STAT *psbuf,
5880 int *pdata_return_size)
5882 NTSTATUS status = NT_STATUS_OK;
5883 uint32 raw_unixmode = 0;
5884 uint32 mod_unixmode = 0;
5885 mode_t unixmode = (mode_t)0;
5886 files_struct *fsp = NULL;
5887 uint16 info_level_return = 0;
5889 char *pdata = *ppdata;
5891 if (total_data < 18) {
5892 return NT_STATUS_INVALID_PARAMETER;
5895 raw_unixmode = IVAL(pdata,8);
5896 /* Next 4 bytes are not yet defined. */
5898 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5899 if (!NT_STATUS_IS_OK(status)) {
5903 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5905 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5906 fname, (unsigned int)unixmode ));
5908 status = open_directory(conn, req,
5911 FILE_READ_ATTRIBUTES, /* Just a stat open */
5912 FILE_SHARE_NONE, /* Ignored for stat opens */
5919 if (NT_STATUS_IS_OK(status)) {
5920 close_file(fsp, NORMAL_CLOSE);
5923 info_level_return = SVAL(pdata,16);
5925 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5926 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5927 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5928 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5930 *pdata_return_size = 12;
5933 /* Realloc the data size */
5934 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5935 if (*ppdata == NULL) {
5936 *pdata_return_size = 0;
5937 return NT_STATUS_NO_MEMORY;
5941 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5942 SSVAL(pdata,2,0); /* No fnum. */
5943 SIVAL(pdata,4,info); /* Was directory created. */
5945 switch (info_level_return) {
5946 case SMB_QUERY_FILE_UNIX_BASIC:
5947 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5948 SSVAL(pdata,10,0); /* Padding. */
5949 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5951 case SMB_QUERY_FILE_UNIX_INFO2:
5952 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5953 SSVAL(pdata,10,0); /* Padding. */
5954 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5957 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5958 SSVAL(pdata,10,0); /* Padding. */
5965 /****************************************************************************
5966 Open/Create a file with POSIX semantics.
5967 ****************************************************************************/
5969 static NTSTATUS smb_posix_open(connection_struct *conn,
5970 struct smb_request *req,
5974 SMB_STRUCT_STAT *psbuf,
5975 int *pdata_return_size)
5977 bool extended_oplock_granted = False;
5978 char *pdata = *ppdata;
5980 uint32 wire_open_mode = 0;
5981 uint32 raw_unixmode = 0;
5982 uint32 mod_unixmode = 0;
5983 uint32 create_disp = 0;
5984 uint32 access_mask = 0;
5985 uint32 create_options = 0;
5986 NTSTATUS status = NT_STATUS_OK;
5987 mode_t unixmode = (mode_t)0;
5988 files_struct *fsp = NULL;
5989 int oplock_request = 0;
5991 uint16 info_level_return = 0;
5993 if (total_data < 18) {
5994 return NT_STATUS_INVALID_PARAMETER;
5997 flags = IVAL(pdata,0);
5998 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5999 if (oplock_request) {
6000 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6003 wire_open_mode = IVAL(pdata,4);
6005 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6006 return smb_posix_mkdir(conn, req,
6014 switch (wire_open_mode & SMB_ACCMODE) {
6016 access_mask = FILE_READ_DATA;
6019 access_mask = FILE_WRITE_DATA;
6022 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6025 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6026 (unsigned int)wire_open_mode ));
6027 return NT_STATUS_INVALID_PARAMETER;
6030 wire_open_mode &= ~SMB_ACCMODE;
6032 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6033 create_disp = FILE_CREATE;
6034 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6035 create_disp = FILE_OVERWRITE_IF;
6036 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6037 create_disp = FILE_OPEN_IF;
6039 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6040 (unsigned int)wire_open_mode ));
6041 return NT_STATUS_INVALID_PARAMETER;
6044 raw_unixmode = IVAL(pdata,8);
6045 /* Next 4 bytes are not yet defined. */
6047 status = unix_perms_from_wire(conn,
6050 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6053 if (!NT_STATUS_IS_OK(status)) {
6057 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6059 if (wire_open_mode & SMB_O_SYNC) {
6060 create_options |= FILE_WRITE_THROUGH;
6062 if (wire_open_mode & SMB_O_APPEND) {
6063 access_mask |= FILE_APPEND_DATA;
6065 if (wire_open_mode & SMB_O_DIRECT) {
6066 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6069 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6071 (unsigned int)wire_open_mode,
6072 (unsigned int)unixmode ));
6074 status = open_file_ntcreate(conn, req,
6078 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6080 0, /* no create options yet. */
6086 if (!NT_STATUS_IS_OK(status)) {
6090 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6091 extended_oplock_granted = True;
6094 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6095 extended_oplock_granted = True;
6098 info_level_return = SVAL(pdata,16);
6100 /* Allocate the correct return size. */
6102 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6103 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6104 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6105 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6107 *pdata_return_size = 12;
6110 /* Realloc the data size */
6111 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6112 if (*ppdata == NULL) {
6113 close_file(fsp,ERROR_CLOSE);
6114 *pdata_return_size = 0;
6115 return NT_STATUS_NO_MEMORY;
6119 if (extended_oplock_granted) {
6120 if (flags & REQUEST_BATCH_OPLOCK) {
6121 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6123 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6125 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6126 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6128 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6131 SSVAL(pdata,2,fsp->fnum);
6132 SIVAL(pdata,4,info); /* Was file created etc. */
6134 switch (info_level_return) {
6135 case SMB_QUERY_FILE_UNIX_BASIC:
6136 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6137 SSVAL(pdata,10,0); /* padding. */
6138 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6140 case SMB_QUERY_FILE_UNIX_INFO2:
6141 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6142 SSVAL(pdata,10,0); /* padding. */
6143 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6146 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6147 SSVAL(pdata,10,0); /* padding. */
6150 return NT_STATUS_OK;
6153 /****************************************************************************
6154 Delete a file with POSIX semantics.
6155 ****************************************************************************/
6157 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6158 struct smb_request *req,
6162 SMB_STRUCT_STAT *psbuf)
6164 NTSTATUS status = NT_STATUS_OK;
6165 files_struct *fsp = NULL;
6170 struct share_mode_lock *lck = NULL;
6172 if (total_data < 2) {
6173 return NT_STATUS_INVALID_PARAMETER;
6176 flags = SVAL(pdata,0);
6178 if (!VALID_STAT(*psbuf)) {
6179 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6182 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6183 !VALID_STAT_OF_DIR(*psbuf)) {
6184 return NT_STATUS_NOT_A_DIRECTORY;
6187 DEBUG(10,("smb_posix_unlink: %s %s\n",
6188 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6191 if (VALID_STAT_OF_DIR(*psbuf)) {
6192 status = open_directory(conn, req,
6196 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6199 FILE_FLAG_POSIX_SEMANTICS|0777,
6204 status = open_file_ntcreate(conn, req,
6208 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6211 FILE_FLAG_POSIX_SEMANTICS|0777,
6212 0, /* No oplock, but break existing ones. */
6217 if (!NT_STATUS_IS_OK(status)) {
6222 * Don't lie to client. If we can't really delete due to
6223 * non-POSIX opens return SHARING_VIOLATION.
6226 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
6228 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6229 "lock for file %s\n", fsp->fsp_name));
6230 close_file(fsp, NORMAL_CLOSE);
6231 return NT_STATUS_INVALID_PARAMETER;
6235 * See if others still have the file open. If this is the case, then
6236 * don't delete. If all opens are POSIX delete we can set the delete
6237 * on close disposition.
6239 for (i=0; i<lck->num_share_modes; i++) {
6240 struct share_mode_entry *e = &lck->share_modes[i];
6241 if (is_valid_share_mode_entry(e)) {
6242 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6245 /* Fail with sharing violation. */
6246 close_file(fsp, NORMAL_CLOSE);
6248 return NT_STATUS_SHARING_VIOLATION;
6253 * Set the delete on close.
6255 status = smb_set_file_disposition_info(conn,
6262 if (!NT_STATUS_IS_OK(status)) {
6263 close_file(fsp, NORMAL_CLOSE);
6268 return close_file(fsp, NORMAL_CLOSE);
6271 /****************************************************************************
6272 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6273 ****************************************************************************/
6275 static void call_trans2setfilepathinfo(connection_struct *conn,
6276 struct smb_request *req,
6277 unsigned int tran_call,
6278 char **pparams, int total_params,
6279 char **ppdata, int total_data,
6280 unsigned int max_data_bytes)
6282 char *params = *pparams;
6283 char *pdata = *ppdata;
6285 SMB_STRUCT_STAT sbuf;
6287 files_struct *fsp = NULL;
6288 NTSTATUS status = NT_STATUS_OK;
6289 int data_return_size = 0;
6290 TALLOC_CTX *ctx = talloc_tos();
6293 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6299 if (tran_call == TRANSACT2_SETFILEINFO) {
6300 if (total_params < 4) {
6301 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6305 fsp = file_fsp(SVAL(params,0));
6306 /* Basic check for non-null fsp. */
6307 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
6310 info_level = SVAL(params,2);
6312 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6314 reply_nterror(req, NT_STATUS_NO_MEMORY);
6318 if(fsp->is_directory || fsp->fh->fd == -1) {
6320 * This is actually a SETFILEINFO on a directory
6321 * handle (returned from an NT SMB). NT5.0 seems
6322 * to do this call. JRA.
6324 if (INFO_LEVEL_IS_UNIX(info_level)) {
6325 /* Always do lstat for UNIX calls. */
6326 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6327 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6328 reply_unixerror(req,ERRDOS,ERRbadpath);
6332 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6333 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6334 reply_unixerror(req,ERRDOS,ERRbadpath);
6338 } else if (fsp->print_file) {
6340 * Doing a DELETE_ON_CLOSE should cancel a print job.
6342 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6343 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6345 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6348 send_trans2_replies(req, params, 2,
6353 reply_unixerror(req, ERRDOS, ERRbadpath);
6358 * Original code - this is an open file.
6360 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6364 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6365 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6366 reply_unixerror(req, ERRDOS, ERRbadfid);
6372 if (total_params < 7) {
6373 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6377 info_level = SVAL(params,0);
6378 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6379 total_params - 6, STR_TERMINATE,
6381 if (!NT_STATUS_IS_OK(status)) {
6382 reply_nterror(req, status);
6386 status = resolve_dfspath(ctx, conn,
6387 req->flags2 & FLAGS2_DFS_PATHNAMES,
6390 if (!NT_STATUS_IS_OK(status)) {
6391 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6392 reply_botherror(req,
6393 NT_STATUS_PATH_NOT_COVERED,
6394 ERRSRV, ERRbadpath);
6397 reply_nterror(req, status);
6401 status = unix_convert(ctx, conn, fname, False,
6402 &fname, NULL, &sbuf);
6403 if (!NT_STATUS_IS_OK(status)) {
6404 reply_nterror(req, status);
6408 status = check_name(conn, fname);
6409 if (!NT_STATUS_IS_OK(status)) {
6410 reply_nterror(req, status);
6414 if (INFO_LEVEL_IS_UNIX(info_level)) {
6416 * For CIFS UNIX extensions the target name may not exist.
6419 /* Always do lstat for UNIX calls. */
6420 SMB_VFS_LSTAT(conn,fname,&sbuf);
6422 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6423 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6424 reply_unixerror(req, ERRDOS, ERRbadpath);
6429 if (!CAN_WRITE(conn)) {
6430 reply_doserror(req, ERRSRV, ERRaccess);
6434 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6435 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6439 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6440 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6442 /* Realloc the parameter size */
6443 *pparams = (char *)SMB_REALLOC(*pparams,2);
6444 if (*pparams == NULL) {
6445 reply_nterror(req, NT_STATUS_NO_MEMORY);
6452 if (fsp && !null_timespec(fsp->pending_modtime)) {
6453 /* the pending modtime overrides the current modtime */
6454 set_mtimespec(&sbuf, fsp->pending_modtime);
6457 switch (info_level) {
6459 case SMB_INFO_STANDARD:
6461 status = smb_set_info_standard(conn,
6470 case SMB_INFO_SET_EA:
6472 status = smb_info_set_ea(conn,
6480 case SMB_SET_FILE_BASIC_INFO:
6481 case SMB_FILE_BASIC_INFORMATION:
6483 status = smb_set_file_basic_info(conn,
6492 case SMB_FILE_ALLOCATION_INFORMATION:
6493 case SMB_SET_FILE_ALLOCATION_INFO:
6495 status = smb_set_file_allocation_info(conn, req,
6504 case SMB_FILE_END_OF_FILE_INFORMATION:
6505 case SMB_SET_FILE_END_OF_FILE_INFO:
6507 status = smb_set_file_end_of_file_info(conn, req,
6516 case SMB_FILE_DISPOSITION_INFORMATION:
6517 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6520 /* JRA - We used to just ignore this on a path ?
6521 * Shouldn't this be invalid level on a pathname
6524 if (tran_call != TRANSACT2_SETFILEINFO) {
6525 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6528 status = smb_set_file_disposition_info(conn,
6537 case SMB_FILE_POSITION_INFORMATION:
6539 status = smb_file_position_information(conn,
6546 /* From tridge Samba4 :
6547 * MODE_INFORMATION in setfileinfo (I have no
6548 * idea what "mode information" on a file is - it takes a value of 0,
6549 * 2, 4 or 6. What could it be?).
6552 case SMB_FILE_MODE_INFORMATION:
6554 status = smb_file_mode_information(conn,
6561 * CIFS UNIX extensions.
6564 case SMB_SET_FILE_UNIX_BASIC:
6566 status = smb_set_file_unix_basic(conn, req,
6575 case SMB_SET_FILE_UNIX_INFO2:
6577 status = smb_set_file_unix_info2(conn, req,
6586 case SMB_SET_FILE_UNIX_LINK:
6588 if (tran_call != TRANSACT2_SETPATHINFO) {
6589 /* We must have a pathname for this. */
6590 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6593 status = smb_set_file_unix_link(conn, req, pdata,
6598 case SMB_SET_FILE_UNIX_HLINK:
6600 if (tran_call != TRANSACT2_SETPATHINFO) {
6601 /* We must have a pathname for this. */
6602 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6605 status = smb_set_file_unix_hlink(conn, req,
6611 case SMB_FILE_RENAME_INFORMATION:
6613 status = smb_file_rename_information(conn, req,
6619 #if defined(HAVE_POSIX_ACLS)
6620 case SMB_SET_POSIX_ACL:
6622 status = smb_set_posix_acl(conn,
6632 case SMB_SET_POSIX_LOCK:
6634 if (tran_call != TRANSACT2_SETFILEINFO) {
6635 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6638 status = smb_set_posix_lock(conn, req->inbuf,
6639 smb_len(req->inbuf) + 4,
6640 pdata, total_data, fsp);
6644 case SMB_POSIX_PATH_OPEN:
6646 if (tran_call != TRANSACT2_SETPATHINFO) {
6647 /* We must have a pathname for this. */
6648 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6652 status = smb_posix_open(conn, req,
6661 case SMB_POSIX_PATH_UNLINK:
6663 if (tran_call != TRANSACT2_SETPATHINFO) {
6664 /* We must have a pathname for this. */
6665 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6669 status = smb_posix_unlink(conn, req,
6678 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6683 if (!NT_STATUS_IS_OK(status)) {
6684 if (open_was_deferred(req->mid)) {
6685 /* We have re-scheduled this call. */
6688 if (blocking_lock_was_deferred(req->mid)) {
6689 /* We have re-scheduled this call. */
6692 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6693 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6694 ERRSRV, ERRbadpath);
6697 if (info_level == SMB_POSIX_PATH_OPEN) {
6698 reply_openerror(req, status);
6702 reply_nterror(req, status);
6707 send_trans2_replies(req, params, 2, *ppdata, data_return_size,
6713 /****************************************************************************
6714 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6715 ****************************************************************************/
6717 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6718 char **pparams, int total_params,
6719 char **ppdata, int total_data,
6720 unsigned int max_data_bytes)
6722 char *params = *pparams;
6723 char *pdata = *ppdata;
6724 char *directory = NULL;
6725 SMB_STRUCT_STAT sbuf;
6726 NTSTATUS status = NT_STATUS_OK;
6727 struct ea_list *ea_list = NULL;
6728 TALLOC_CTX *ctx = talloc_tos();
6730 if (!CAN_WRITE(conn)) {
6731 reply_doserror(req, ERRSRV, ERRaccess);
6735 if (total_params < 5) {
6736 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6740 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
6741 total_params - 4, STR_TERMINATE,
6743 if (!NT_STATUS_IS_OK(status)) {
6744 reply_nterror(req, status);
6748 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6750 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6751 if (!NT_STATUS_IS_OK(status)) {
6752 reply_nterror(req, status);
6756 status = check_name(conn, directory);
6757 if (!NT_STATUS_IS_OK(status)) {
6758 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6759 reply_nterror(req, status);
6763 /* Any data in this call is an EA list. */
6764 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6765 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6770 * OS/2 workplace shell seems to send SET_EA requests of "null"
6771 * length (4 bytes containing IVAL 4).
6772 * They seem to have no effect. Bug #3212. JRA.
6775 if (total_data != 4) {
6776 if (total_data < 10) {
6777 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6781 if (IVAL(pdata,0) > total_data) {
6782 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6783 IVAL(pdata,0), (unsigned int)total_data));
6784 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6788 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6791 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6794 } else if (IVAL(pdata,0) != 4) {
6795 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6799 status = create_directory(conn, directory);
6801 if (!NT_STATUS_IS_OK(status)) {
6802 reply_nterror(req, status);
6806 /* Try and set any given EA. */
6808 status = set_ea(conn, NULL, directory, ea_list);
6809 if (!NT_STATUS_IS_OK(status)) {
6810 reply_nterror(req, status);
6815 /* Realloc the parameter and data sizes */
6816 *pparams = (char *)SMB_REALLOC(*pparams,2);
6817 if(*pparams == NULL) {
6818 reply_nterror(req, NT_STATUS_NO_MEMORY);
6825 send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
6830 /****************************************************************************
6831 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6832 We don't actually do this - we just send a null response.
6833 ****************************************************************************/
6835 static void call_trans2findnotifyfirst(connection_struct *conn,
6836 struct smb_request *req,
6837 char **pparams, int total_params,
6838 char **ppdata, int total_data,
6839 unsigned int max_data_bytes)
6841 static uint16 fnf_handle = 257;
6842 char *params = *pparams;
6845 if (total_params < 6) {
6846 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6850 info_level = SVAL(params,4);
6851 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6853 switch (info_level) {
6858 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6862 /* Realloc the parameter and data sizes */
6863 *pparams = (char *)SMB_REALLOC(*pparams,6);
6864 if (*pparams == NULL) {
6865 reply_nterror(req, NT_STATUS_NO_MEMORY);
6870 SSVAL(params,0,fnf_handle);
6871 SSVAL(params,2,0); /* No changes */
6872 SSVAL(params,4,0); /* No EA errors */
6879 send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
6884 /****************************************************************************
6885 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6886 changes). Currently this does nothing.
6887 ****************************************************************************/
6889 static void call_trans2findnotifynext(connection_struct *conn,
6890 struct smb_request *req,
6891 char **pparams, int total_params,
6892 char **ppdata, int total_data,
6893 unsigned int max_data_bytes)
6895 char *params = *pparams;
6897 DEBUG(3,("call_trans2findnotifynext\n"));
6899 /* Realloc the parameter and data sizes */
6900 *pparams = (char *)SMB_REALLOC(*pparams,4);
6901 if (*pparams == NULL) {
6902 reply_nterror(req, NT_STATUS_NO_MEMORY);
6907 SSVAL(params,0,0); /* No changes */
6908 SSVAL(params,2,0); /* No EA errors */
6910 send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes);
6915 /****************************************************************************
6916 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6917 ****************************************************************************/
6919 static void call_trans2getdfsreferral(connection_struct *conn,
6920 struct smb_request *req,
6921 char **pparams, int total_params,
6922 char **ppdata, int total_data,
6923 unsigned int max_data_bytes)
6925 char *params = *pparams;
6926 char *pathname = NULL;
6928 int max_referral_level;
6929 NTSTATUS status = NT_STATUS_OK;
6930 TALLOC_CTX *ctx = talloc_tos();
6932 DEBUG(10,("call_trans2getdfsreferral\n"));
6934 if (total_params < 3) {
6935 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6939 max_referral_level = SVAL(params,0);
6941 if(!lp_host_msdfs()) {
6942 reply_doserror(req, ERRDOS, ERRbadfunc);
6946 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
6947 total_params - 2, STR_TERMINATE);
6949 reply_nterror(req, NT_STATUS_NOT_FOUND);
6952 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6953 ppdata,&status)) < 0) {
6954 reply_nterror(req, status);
6958 SSVAL(req->inbuf, smb_flg2,
6959 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6960 send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes);
6965 #define LMCAT_SPL 0x53
6966 #define LMFUNC_GETJOBID 0x60
6968 /****************************************************************************
6969 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6970 ****************************************************************************/
6972 static void call_trans2ioctl(connection_struct *conn,
6973 struct smb_request *req,
6974 char **pparams, int total_params,
6975 char **ppdata, int total_data,
6976 unsigned int max_data_bytes)
6978 char *pdata = *ppdata;
6979 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6981 /* check for an invalid fid before proceeding */
6984 reply_doserror(req, ERRDOS, ERRbadfid);
6988 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6989 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6990 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6991 if (*ppdata == NULL) {
6992 reply_nterror(req, NT_STATUS_NO_MEMORY);
6997 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6998 CAN ACCEPT THIS IN UNICODE. JRA. */
7000 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7001 srvstr_push(pdata, req->flags2, pdata + 2,
7002 global_myname(), 15,
7003 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7004 srvstr_push(pdata, req->flags2, pdata+18,
7005 lp_servicename(SNUM(conn)), 13,
7006 STR_ASCII|STR_TERMINATE); /* Service name */
7007 send_trans2_replies(req, *pparams, 0, *ppdata, 32,
7012 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7013 reply_doserror(req, ERRSRV, ERRerror);
7016 /****************************************************************************
7017 Reply to a SMBfindclose (stop trans2 directory search).
7018 ****************************************************************************/
7020 void reply_findclose(connection_struct *conn, struct smb_request *req)
7024 START_PROFILE(SMBfindclose);
7027 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7028 END_PROFILE(SMBfindclose);
7032 dptr_num = SVALS(req->inbuf,smb_vwv0);
7034 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7036 dptr_close(&dptr_num);
7038 reply_outbuf(req, 0, 0);
7040 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7042 END_PROFILE(SMBfindclose);
7046 /****************************************************************************
7047 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7048 ****************************************************************************/
7050 void reply_findnclose(connection_struct *conn, struct smb_request *req)
7054 START_PROFILE(SMBfindnclose);
7057 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7058 END_PROFILE(SMBfindnclose);
7062 dptr_num = SVAL(req->inbuf,smb_vwv0);
7064 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7066 /* We never give out valid handles for a
7067 findnotifyfirst - so any dptr_num is ok here.
7070 reply_outbuf(req, 0, 0);
7072 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7074 END_PROFILE(SMBfindnclose);
7078 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7079 struct trans_state *state)
7081 if (Protocol >= PROTOCOL_NT1) {
7082 req->flags2 |= 0x40; /* IS_LONG_NAME */
7083 SSVAL(req->inbuf,smb_flg2,req->flags2);
7086 if (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF ) {
7087 if (state->call != TRANSACT2_QFSINFO &&
7088 state->call != TRANSACT2_SETFSINFO) {
7089 DEBUG(0,("handle_trans2: encryption required "
7091 (unsigned int)state->call));
7092 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7097 /* Now we must call the relevant TRANS2 function */
7098 switch(state->call) {
7099 case TRANSACT2_OPEN:
7101 START_PROFILE(Trans2_open);
7102 call_trans2open(conn, req,
7103 &state->param, state->total_param,
7104 &state->data, state->total_data,
7105 state->max_data_return);
7106 END_PROFILE(Trans2_open);
7110 case TRANSACT2_FINDFIRST:
7112 START_PROFILE(Trans2_findfirst);
7113 call_trans2findfirst(conn, req,
7114 &state->param, state->total_param,
7115 &state->data, state->total_data,
7116 state->max_data_return);
7117 END_PROFILE(Trans2_findfirst);
7121 case TRANSACT2_FINDNEXT:
7123 START_PROFILE(Trans2_findnext);
7124 call_trans2findnext(conn, req,
7125 &state->param, state->total_param,
7126 &state->data, state->total_data,
7127 state->max_data_return);
7128 END_PROFILE(Trans2_findnext);
7132 case TRANSACT2_QFSINFO:
7134 START_PROFILE(Trans2_qfsinfo);
7135 call_trans2qfsinfo(conn, req,
7136 &state->param, state->total_param,
7137 &state->data, state->total_data,
7138 state->max_data_return);
7139 END_PROFILE(Trans2_qfsinfo);
7143 case TRANSACT2_SETFSINFO:
7145 START_PROFILE(Trans2_setfsinfo);
7146 call_trans2setfsinfo(conn, req,
7147 &state->param, state->total_param,
7148 &state->data, state->total_data,
7149 state->max_data_return);
7150 END_PROFILE(Trans2_setfsinfo);
7154 case TRANSACT2_QPATHINFO:
7155 case TRANSACT2_QFILEINFO:
7157 START_PROFILE(Trans2_qpathinfo);
7158 call_trans2qfilepathinfo(conn, req, state->call,
7159 &state->param, state->total_param,
7160 &state->data, state->total_data,
7161 state->max_data_return);
7162 END_PROFILE(Trans2_qpathinfo);
7166 case TRANSACT2_SETPATHINFO:
7167 case TRANSACT2_SETFILEINFO:
7169 START_PROFILE(Trans2_setpathinfo);
7170 call_trans2setfilepathinfo(conn, req, state->call,
7171 &state->param, state->total_param,
7172 &state->data, state->total_data,
7173 state->max_data_return);
7174 END_PROFILE(Trans2_setpathinfo);
7178 case TRANSACT2_FINDNOTIFYFIRST:
7180 START_PROFILE(Trans2_findnotifyfirst);
7181 call_trans2findnotifyfirst(conn, req,
7182 &state->param, state->total_param,
7183 &state->data, state->total_data,
7184 state->max_data_return);
7185 END_PROFILE(Trans2_findnotifyfirst);
7189 case TRANSACT2_FINDNOTIFYNEXT:
7191 START_PROFILE(Trans2_findnotifynext);
7192 call_trans2findnotifynext(conn, req,
7193 &state->param, state->total_param,
7194 &state->data, state->total_data,
7195 state->max_data_return);
7196 END_PROFILE(Trans2_findnotifynext);
7200 case TRANSACT2_MKDIR:
7202 START_PROFILE(Trans2_mkdir);
7203 call_trans2mkdir(conn, req,
7204 &state->param, state->total_param,
7205 &state->data, state->total_data,
7206 state->max_data_return);
7207 END_PROFILE(Trans2_mkdir);
7211 case TRANSACT2_GET_DFS_REFERRAL:
7213 START_PROFILE(Trans2_get_dfs_referral);
7214 call_trans2getdfsreferral(conn, req,
7215 &state->param, state->total_param,
7216 &state->data, state->total_data,
7217 state->max_data_return);
7218 END_PROFILE(Trans2_get_dfs_referral);
7222 case TRANSACT2_IOCTL:
7224 START_PROFILE(Trans2_ioctl);
7225 call_trans2ioctl(conn, req,
7226 &state->param, state->total_param,
7227 &state->data, state->total_data,
7228 state->max_data_return);
7229 END_PROFILE(Trans2_ioctl);
7234 /* Error in request */
7235 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7236 reply_doserror(req, ERRSRV,ERRerror);
7240 /****************************************************************************
7241 Reply to a SMBtrans2.
7242 ****************************************************************************/
7244 void reply_trans2(connection_struct *conn, struct smb_request *req)
7250 unsigned int tran_call;
7252 struct trans_state *state;
7255 START_PROFILE(SMBtrans2);
7257 if (req->wct < 14) {
7258 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7259 END_PROFILE(SMBtrans2);
7263 dsoff = SVAL(req->inbuf, smb_dsoff);
7264 dscnt = SVAL(req->inbuf, smb_dscnt);
7265 psoff = SVAL(req->inbuf, smb_psoff);
7266 pscnt = SVAL(req->inbuf, smb_pscnt);
7267 tran_call = SVAL(req->inbuf, smb_setup0);
7268 size = smb_len(req->inbuf) + 4;
7270 result = allow_new_trans(conn->pending_trans, req->mid);
7271 if (!NT_STATUS_IS_OK(result)) {
7272 DEBUG(2, ("Got invalid trans2 request: %s\n",
7273 nt_errstr(result)));
7274 reply_nterror(req, result);
7275 END_PROFILE(SMBtrans2);
7279 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
7280 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
7281 && (tran_call != TRANSACT2_QFILEINFO)) {
7282 reply_doserror(req, ERRSRV, ERRaccess);
7283 END_PROFILE(SMBtrans2);
7287 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7288 DEBUG(0, ("talloc failed\n"));
7289 reply_nterror(req, NT_STATUS_NO_MEMORY);
7290 END_PROFILE(SMBtrans2);
7294 state->cmd = SMBtrans2;
7296 state->mid = req->mid;
7297 state->vuid = req->vuid;
7298 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7299 state->setup = NULL;
7300 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7301 state->param = NULL;
7302 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7304 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7305 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7306 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7307 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7308 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7310 state->call = tran_call;
7312 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7313 is so as a sanity check */
7314 if (state->setup_count != 1) {
7316 * Need to have rc=0 for ioctl to get job id for OS/2.
7317 * Network printing will fail if function is not successful.
7318 * Similar function in reply.c will be used if protocol
7319 * is LANMAN1.0 instead of LM1.2X002.
7320 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7321 * outbuf doesn't have to be set(only job id is used).
7323 if ( (state->setup_count == 4)
7324 && (tran_call == TRANSACT2_IOCTL)
7325 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7326 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7327 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7329 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7330 DEBUG(2,("Transaction is %d\n",tran_call));
7332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7333 END_PROFILE(SMBtrans2);
7338 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7341 if (state->total_data) {
7342 /* Can't use talloc here, the core routines do realloc on the
7343 * params and data. */
7344 state->data = (char *)SMB_MALLOC(state->total_data);
7345 if (state->data == NULL) {
7346 DEBUG(0,("reply_trans2: data malloc fail for %u "
7347 "bytes !\n", (unsigned int)state->total_data));
7349 reply_nterror(req, NT_STATUS_NO_MEMORY);
7350 END_PROFILE(SMBtrans2);
7353 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7355 if ((smb_base(req->inbuf)+dsoff+dscnt
7356 > (char *)req->inbuf + size) ||
7357 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7360 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7363 if (state->total_param) {
7364 /* Can't use talloc here, the core routines do realloc on the
7365 * params and data. */
7366 state->param = (char *)SMB_MALLOC(state->total_param);
7367 if (state->param == NULL) {
7368 DEBUG(0,("reply_trans: param malloc fail for %u "
7369 "bytes !\n", (unsigned int)state->total_param));
7370 SAFE_FREE(state->data);
7372 reply_nterror(req, NT_STATUS_NO_MEMORY);
7373 END_PROFILE(SMBtrans2);
7376 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7378 if ((smb_base(req->inbuf)+psoff+pscnt
7379 > (char *)req->inbuf + size) ||
7380 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7383 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7386 state->received_data = dscnt;
7387 state->received_param = pscnt;
7389 if ((state->received_param == state->total_param) &&
7390 (state->received_data == state->total_data)) {
7392 handle_trans2(conn, req, state);
7394 SAFE_FREE(state->data);
7395 SAFE_FREE(state->param);
7397 END_PROFILE(SMBtrans2);
7401 DLIST_ADD(conn->pending_trans, state);
7403 /* We need to send an interim response then receive the rest
7404 of the parameter/data bytes */
7405 reply_outbuf(req, 0, 0);
7406 show_msg((char *)req->outbuf);
7407 END_PROFILE(SMBtrans2);
7412 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7413 SAFE_FREE(state->data);
7414 SAFE_FREE(state->param);
7416 END_PROFILE(SMBtrans2);
7417 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7421 /****************************************************************************
7422 Reply to a SMBtranss2
7423 ****************************************************************************/
7425 void reply_transs2(connection_struct *conn, struct smb_request *req)
7427 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7428 struct trans_state *state;
7431 START_PROFILE(SMBtranss2);
7433 show_msg((char *)req->inbuf);
7436 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7437 END_PROFILE(SMBtranss2);
7441 size = smb_len(req->inbuf)+4;
7443 for (state = conn->pending_trans; state != NULL;
7444 state = state->next) {
7445 if (state->mid == req->mid) {
7450 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7451 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7452 END_PROFILE(SMBtranss2);
7456 /* Revise state->total_param and state->total_data in case they have
7457 changed downwards */
7459 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7460 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7461 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7462 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7464 pcnt = SVAL(req->inbuf, smb_spscnt);
7465 poff = SVAL(req->inbuf, smb_spsoff);
7466 pdisp = SVAL(req->inbuf, smb_spsdisp);
7468 dcnt = SVAL(req->inbuf, smb_sdscnt);
7469 doff = SVAL(req->inbuf, smb_sdsoff);
7470 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7472 state->received_param += pcnt;
7473 state->received_data += dcnt;
7475 if ((state->received_data > state->total_data) ||
7476 (state->received_param > state->total_param))
7480 if (pdisp+pcnt > state->total_param)
7482 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7484 if (pdisp > state->total_param)
7486 if ((smb_base(req->inbuf) + poff + pcnt
7487 > (char *)req->inbuf + size) ||
7488 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7490 if (state->param + pdisp < state->param)
7493 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7498 if (ddisp+dcnt > state->total_data)
7500 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7502 if (ddisp > state->total_data)
7504 if ((smb_base(req->inbuf) + doff + dcnt
7505 > (char *)req->inbuf + size) ||
7506 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7508 if (state->data + ddisp < state->data)
7511 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7515 if ((state->received_param < state->total_param) ||
7516 (state->received_data < state->total_data)) {
7517 END_PROFILE(SMBtranss2);
7522 * construct_reply_common will copy smb_com from inbuf to
7523 * outbuf. SMBtranss2 is wrong here.
7525 SCVAL(req->inbuf,smb_com,SMBtrans2);
7527 handle_trans2(conn, req, state);
7529 DLIST_REMOVE(conn->pending_trans, state);
7530 SAFE_FREE(state->data);
7531 SAFE_FREE(state->param);
7534 END_PROFILE(SMBtranss2);
7539 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7540 DLIST_REMOVE(conn->pending_trans, state);
7541 SAFE_FREE(state->data);
7542 SAFE_FREE(state->param);
7544 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7545 END_PROFILE(SMBtranss2);