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, 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, 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_tos();
301 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
305 /****************************************************************************
306 Ensure the EA name is case insensitive by matching any existing EA name.
307 ****************************************************************************/
309 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
312 TALLOC_CTX *mem_ctx = talloc_tos();
313 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
315 for (; ea_list; ea_list = ea_list->next) {
316 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
317 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
318 &unix_ea_name[5], ea_list->ea.name));
319 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
325 /****************************************************************************
326 Set or delete an extended attribute.
327 ****************************************************************************/
329 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
331 if (!lp_ea_support(SNUM(conn))) {
332 return NT_STATUS_EAS_NOT_SUPPORTED;
335 for (;ea_list; ea_list = ea_list->next) {
337 fstring unix_ea_name;
339 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
340 fstrcat(unix_ea_name, ea_list->ea.name);
342 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
344 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
346 if (samba_private_attr_name(unix_ea_name)) {
347 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
348 return NT_STATUS_ACCESS_DENIED;
351 if (ea_list->ea.value.length == 0) {
352 /* Remove the attribute. */
353 if (fsp && (fsp->fh->fd != -1)) {
354 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
355 unix_ea_name, fsp->fsp_name));
356 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
358 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
359 unix_ea_name, fname));
360 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
363 /* Removing a non existent attribute always succeeds. */
364 if (ret == -1 && errno == ENOATTR) {
365 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
371 if (fsp && (fsp->fh->fd != -1)) {
372 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
373 unix_ea_name, fsp->fsp_name));
374 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
375 ea_list->ea.value.data, ea_list->ea.value.length, 0);
377 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
378 unix_ea_name, fname));
379 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
380 ea_list->ea.value.data, ea_list->ea.value.length, 0);
386 if (errno == ENOTSUP) {
387 return NT_STATUS_EAS_NOT_SUPPORTED;
390 return map_nt_error_from_unix(errno);
396 /****************************************************************************
397 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
398 ****************************************************************************/
400 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
402 struct ea_list *ea_list_head = NULL;
405 while (offset + 2 < data_size) {
406 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
407 unsigned int namelen = CVAL(pdata,offset);
409 offset++; /* Go past the namelen byte. */
411 /* integer wrap paranioa. */
412 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
413 (offset > data_size) || (namelen > data_size) ||
414 (offset + namelen >= data_size)) {
417 /* Ensure the name is null terminated. */
418 if (pdata[offset + namelen] != '\0') {
421 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
426 offset += (namelen + 1); /* Go past the name + terminating zero. */
427 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
428 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
434 /****************************************************************************
435 Read one EA list entry from the buffer.
436 ****************************************************************************/
438 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
440 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
442 unsigned int namelen;
452 eal->ea.flags = CVAL(pdata,0);
453 namelen = CVAL(pdata,1);
454 val_len = SVAL(pdata,2);
456 if (4 + namelen + 1 + val_len > data_size) {
460 /* Ensure the name is null terminated. */
461 if (pdata[namelen + 4] != '\0') {
464 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
469 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
470 if (!eal->ea.value.data) {
474 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
476 /* Ensure we're null terminated just in case we print the value. */
477 eal->ea.value.data[val_len] = '\0';
478 /* But don't count the null. */
479 eal->ea.value.length--;
482 *pbytes_used = 4 + namelen + 1 + val_len;
485 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
486 dump_data(10, eal->ea.value.data, eal->ea.value.length);
491 /****************************************************************************
492 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
493 ****************************************************************************/
495 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
497 struct ea_list *ea_list_head = NULL;
499 size_t bytes_used = 0;
501 while (offset < data_size) {
502 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
508 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
509 offset += bytes_used;
515 /****************************************************************************
516 Count the total EA size needed.
517 ****************************************************************************/
519 static size_t ea_list_size(struct ea_list *ealist)
522 struct ea_list *listp;
525 for (listp = ealist; listp; listp = listp->next) {
526 push_ascii_fstring(dos_ea_name, listp->ea.name);
527 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
529 /* Add on 4 for total length. */
537 /****************************************************************************
538 Return a union of EA's from a file list and a list of names.
539 The TALLOC context for the two lists *MUST* be identical as we steal
540 memory from one list to add to another. JRA.
541 ****************************************************************************/
543 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
545 struct ea_list *nlistp, *flistp;
547 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
548 for (flistp = file_list; flistp; flistp = flistp->next) {
549 if (strequal(nlistp->ea.name, flistp->ea.name)) {
555 /* Copy the data from this entry. */
556 nlistp->ea.flags = flistp->ea.flags;
557 nlistp->ea.value = flistp->ea.value;
560 nlistp->ea.flags = 0;
561 ZERO_STRUCT(nlistp->ea.value);
565 *total_ea_len = ea_list_size(name_list);
569 /****************************************************************************
570 Send the required number of replies back.
571 We assume all fields other than the data fields are
572 set correctly for the type of call.
573 HACK ! Always assumes smb_setup field is zero.
574 ****************************************************************************/
576 void send_trans2_replies(connection_struct *conn,
577 struct smb_request *req,
584 /* As we are using a protocol > LANMAN1 then the max_send
585 variable must have been set in the sessetupX call.
586 This takes precedence over the max_xmit field in the
587 global struct. These different max_xmit variables should
588 be merged as this is now too confusing */
590 int data_to_send = datasize;
591 int params_to_send = paramsize;
593 const char *pp = params;
594 const char *pd = pdata;
595 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
596 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
597 int data_alignment_offset = 0;
598 bool overflow = False;
600 /* Modify the data_to_send and datasize and set the error if
601 we're trying to send more than max_data_bytes. We still send
602 the part of the packet(s) that fit. Strange, but needed
605 if (max_data_bytes > 0 && datasize > max_data_bytes) {
606 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
607 max_data_bytes, datasize ));
608 datasize = data_to_send = max_data_bytes;
612 /* If there genuinely are no parameters or data to send just send the empty packet */
614 if(params_to_send == 0 && data_to_send == 0) {
615 reply_outbuf(req, 10, 0);
616 show_msg((char *)req->outbuf);
620 /* When sending params and data ensure that both are nicely aligned */
621 /* Only do this alignment when there is also data to send - else
622 can cause NT redirector problems. */
624 if (((params_to_send % 4) != 0) && (data_to_send != 0))
625 data_alignment_offset = 4 - (params_to_send % 4);
627 /* Space is bufsize minus Netbios over TCP header minus SMB header */
628 /* The alignment_offset is to align the param bytes on an even byte
629 boundary. NT 4.0 Beta needs this to work correctly. */
631 useable_space = max_send - (smb_size
634 + data_alignment_offset);
636 /* useable_space can never be more than max_send minus the alignment offset. */
638 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
640 while (params_to_send || data_to_send) {
641 /* Calculate whether we will totally or partially fill this packet */
643 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
645 /* We can never send more than useable_space */
647 * Note that 'useable_space' does not include the alignment offsets,
648 * but we must include the alignment offsets in the calculation of
649 * the length of the data we send over the wire, as the alignment offsets
650 * are sent here. Fix from Marc_Jacobsen@hp.com.
653 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
655 reply_outbuf(req, 10, total_sent_thistime);
657 /* Set total params and data to be sent */
658 SSVAL(req->outbuf,smb_tprcnt,paramsize);
659 SSVAL(req->outbuf,smb_tdrcnt,datasize);
661 /* Calculate how many parameters and data we can fit into
662 * this packet. Parameters get precedence
665 params_sent_thistime = MIN(params_to_send,useable_space);
666 data_sent_thistime = useable_space - params_sent_thistime;
667 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
669 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
671 /* smb_proff is the offset from the start of the SMB header to the
672 parameter bytes, however the first 4 bytes of outbuf are
673 the Netbios over TCP header. Thus use smb_base() to subtract
674 them from the calculation */
676 SSVAL(req->outbuf,smb_proff,
677 ((smb_buf(req->outbuf)+alignment_offset)
678 - smb_base(req->outbuf)));
680 if(params_sent_thistime == 0)
681 SSVAL(req->outbuf,smb_prdisp,0);
683 /* Absolute displacement of param bytes sent in this packet */
684 SSVAL(req->outbuf,smb_prdisp,pp - params);
686 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
687 if(data_sent_thistime == 0) {
688 SSVAL(req->outbuf,smb_droff,0);
689 SSVAL(req->outbuf,smb_drdisp, 0);
691 /* The offset of the data bytes is the offset of the
692 parameter bytes plus the number of parameters being sent this time */
693 SSVAL(req->outbuf, smb_droff,
694 ((smb_buf(req->outbuf)+alignment_offset)
695 - smb_base(req->outbuf))
696 + params_sent_thistime + data_alignment_offset);
697 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
700 /* Initialize the padding for alignment */
702 if (alignment_offset != 0) {
703 memset(smb_buf(req->outbuf), 0, alignment_offset);
706 /* Copy the param bytes into the packet */
708 if(params_sent_thistime) {
709 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
710 params_sent_thistime);
713 /* Copy in the data bytes */
714 if(data_sent_thistime) {
715 if (data_alignment_offset != 0) {
716 memset((smb_buf(req->outbuf)+alignment_offset+
717 params_sent_thistime), 0,
718 data_alignment_offset);
720 memcpy(smb_buf(req->outbuf)+alignment_offset
721 +params_sent_thistime+data_alignment_offset,
722 pd,data_sent_thistime);
725 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
726 params_sent_thistime, data_sent_thistime, useable_space));
727 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
728 params_to_send, data_to_send, paramsize, datasize));
731 error_packet_set((char *)req->outbuf,
732 ERRDOS,ERRbufferoverflow,
733 STATUS_BUFFER_OVERFLOW,
737 /* Send the packet */
738 show_msg((char *)req->outbuf);
739 if (!srv_send_smb(smbd_server_fd(),
741 IS_CONN_ENCRYPTED(conn)))
742 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
744 TALLOC_FREE(req->outbuf);
746 pp += params_sent_thistime;
747 pd += data_sent_thistime;
749 params_to_send -= params_sent_thistime;
750 data_to_send -= data_sent_thistime;
753 if(params_to_send < 0 || data_to_send < 0) {
754 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
755 params_to_send, data_to_send));
763 /****************************************************************************
764 Reply to a TRANSACT2_OPEN.
765 ****************************************************************************/
767 static void call_trans2open(connection_struct *conn,
768 struct smb_request *req,
769 char **pparams, int total_params,
770 char **ppdata, int total_data,
771 unsigned int max_data_bytes)
773 char *params = *pparams;
774 char *pdata = *ppdata;
779 bool return_additional_info;
790 SMB_STRUCT_STAT sbuf;
793 struct ea_list *ea_list = NULL;
798 uint32 create_disposition;
799 uint32 create_options = 0;
800 TALLOC_CTX *ctx = talloc_tos();
803 * Ensure we have enough parameters to perform the operation.
806 if (total_params < 29) {
807 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
811 flags = SVAL(params, 0);
812 deny_mode = SVAL(params, 2);
813 open_attr = SVAL(params,6);
814 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
815 if (oplock_request) {
816 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
820 return_additional_info = BITSETW(params,0);
821 open_sattr = SVAL(params, 4);
822 open_time = make_unix_date3(params+8);
824 open_ofun = SVAL(params,12);
825 open_size = IVAL(params,14);
829 reply_doserror(req, ERRSRV, ERRaccess);
833 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
834 total_params - 28, STR_TERMINATE,
836 if (!NT_STATUS_IS_OK(status)) {
837 reply_nterror(req, status);
841 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
842 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
843 (unsigned int)open_ofun, open_size));
845 if (open_ofun == 0) {
846 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
850 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
855 reply_doserror(req, ERRDOS, ERRbadaccess);
859 /* Any data in this call is an EA list. */
860 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
861 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
865 if (total_data != 4) {
866 if (total_data < 10) {
867 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
871 if (IVAL(pdata,0) > total_data) {
872 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
873 IVAL(pdata,0), (unsigned int)total_data));
874 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
878 ea_list = read_ea_list(talloc_tos(), pdata + 4,
881 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
884 } else if (IVAL(pdata,0) != 4) {
885 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
889 status = create_file(conn, /* conn */
891 0, /* root_dir_fid */
893 access_mask, /* access_mask */
894 share_mode, /* share_access */
895 create_disposition, /* create_disposition*/
896 create_options, /* create_options */
897 open_attr, /* file_attributes */
898 oplock_request, /* oplock_request */
899 open_size, /* allocation_size */
901 ea_list, /* ea_list */
903 &smb_action, /* pinfo */
906 if (!NT_STATUS_IS_OK(status)) {
907 if (open_was_deferred(req->mid)) {
908 /* We have re-scheduled this call. */
911 reply_openerror(req, status);
915 size = get_file_size(sbuf);
916 fattr = dos_mode(conn,fname,&sbuf);
917 mtime = sbuf.st_mtime;
920 close_file(fsp,ERROR_CLOSE);
921 reply_doserror(req, ERRDOS,ERRnoaccess);
925 /* Realloc the size of parameters and data we will return */
926 *pparams = (char *)SMB_REALLOC(*pparams, 30);
927 if(*pparams == NULL ) {
928 reply_nterror(req, NT_STATUS_NO_MEMORY);
933 SSVAL(params,0,fsp->fnum);
934 SSVAL(params,2,fattr);
935 srv_put_dos_date2(params,4, mtime);
936 SIVAL(params,8, (uint32)size);
937 SSVAL(params,12,deny_mode);
938 SSVAL(params,14,0); /* open_type - file or directory. */
939 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
941 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
942 smb_action |= EXTENDED_OPLOCK_GRANTED;
945 SSVAL(params,18,smb_action);
948 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
950 SIVAL(params,20,inode);
951 SSVAL(params,24,0); /* Padding. */
953 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
954 SIVAL(params, 26, ea_size);
956 SIVAL(params, 26, 0);
959 /* Send the required number of replies */
960 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
963 /*********************************************************
964 Routine to check if a given string matches exactly.
965 as a special case a mask of "." does NOT match. That
966 is required for correct wildcard semantics
967 Case can be significant or not.
968 **********************************************************/
970 static bool exact_match(connection_struct *conn,
974 if (mask[0] == '.' && mask[1] == 0)
976 if (conn->case_sensitive)
977 return strcmp(str,mask)==0;
978 if (StrCaseCmp(str,mask) != 0) {
981 if (dptr_has_wild(conn->dirptr)) {
987 /****************************************************************************
988 Return the filetype for UNIX extensions.
989 ****************************************************************************/
991 static uint32 unix_filetype(mode_t mode)
994 return UNIX_TYPE_FILE;
995 else if(S_ISDIR(mode))
996 return UNIX_TYPE_DIR;
998 else if(S_ISLNK(mode))
999 return UNIX_TYPE_SYMLINK;
1002 else if(S_ISCHR(mode))
1003 return UNIX_TYPE_CHARDEV;
1006 else if(S_ISBLK(mode))
1007 return UNIX_TYPE_BLKDEV;
1010 else if(S_ISFIFO(mode))
1011 return UNIX_TYPE_FIFO;
1014 else if(S_ISSOCK(mode))
1015 return UNIX_TYPE_SOCKET;
1018 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1019 return UNIX_TYPE_UNKNOWN;
1022 /****************************************************************************
1023 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1024 ****************************************************************************/
1026 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1028 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1029 SMB_STRUCT_STAT *psbuf,
1031 enum perm_type ptype,
1036 if (perms == SMB_MODE_NO_CHANGE) {
1037 if (!VALID_STAT(*psbuf)) {
1038 return NT_STATUS_INVALID_PARAMETER;
1040 *ret_perms = psbuf->st_mode;
1041 return NT_STATUS_OK;
1045 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1046 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1047 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1048 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1049 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1050 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1051 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1052 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1053 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1055 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1058 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1061 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1066 /* Apply mode mask */
1067 ret &= lp_create_mask(SNUM(conn));
1068 /* Add in force bits */
1069 ret |= lp_force_create_mode(SNUM(conn));
1072 ret &= lp_dir_mask(SNUM(conn));
1073 /* Add in force bits */
1074 ret |= lp_force_dir_mode(SNUM(conn));
1076 case PERM_EXISTING_FILE:
1077 /* Apply mode mask */
1078 ret &= lp_security_mask(SNUM(conn));
1079 /* Add in force bits */
1080 ret |= lp_force_security_mode(SNUM(conn));
1082 case PERM_EXISTING_DIR:
1083 /* Apply mode mask */
1084 ret &= lp_dir_security_mask(SNUM(conn));
1085 /* Add in force bits */
1086 ret |= lp_force_dir_security_mode(SNUM(conn));
1091 return NT_STATUS_OK;
1094 /****************************************************************************
1095 Get a level dependent lanman2 dir entry.
1096 ****************************************************************************/
1098 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1099 connection_struct *conn,
1101 const char *path_mask,
1104 int requires_resume_key,
1109 int space_remaining,
1111 bool *got_exact_match,
1112 int *last_entry_off,
1113 struct ea_list *name_list)
1117 SMB_STRUCT_STAT sbuf;
1118 const char *mask = NULL;
1119 char *pathreal = NULL;
1120 const char *fname = NULL;
1121 char *p, *q, *pdata = *ppdata;
1125 SMB_OFF_T file_size = 0;
1126 SMB_BIG_UINT allocation_size = 0;
1128 struct timespec mdate_ts, adate_ts, create_date_ts;
1129 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1131 char *last_entry_ptr;
1133 uint32 nt_extmode; /* Used for NT connections instead of mode */
1134 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1135 bool check_mangled_names = lp_manglednames(conn->params);
1136 char mangled_name[13]; /* mangled 8.3 name. */
1138 *out_of_space = False;
1139 *got_exact_match = False;
1141 ZERO_STRUCT(mdate_ts);
1142 ZERO_STRUCT(adate_ts);
1143 ZERO_STRUCT(create_date_ts);
1145 if (!conn->dirptr) {
1149 p = strrchr_m(path_mask,'/');
1152 mask = talloc_strdup(ctx,"*.*");
1162 bool ms_dfs_link = False;
1164 /* Needed if we run out of space */
1165 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1166 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1169 * Due to bugs in NT client redirectors we are not using
1170 * resume keys any more - set them to zero.
1171 * Check out the related comments in findfirst/findnext.
1177 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1178 (long)conn->dirptr,curr_dirpos));
1185 * fname may get mangled, dname is never mangled.
1186 * Whenever we're accessing the filesystem we use
1187 * pathreal which is composed from dname.
1193 /* Mangle fname if it's an illegal name. */
1194 if (mangle_must_mangle(dname,conn->params)) {
1195 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1196 continue; /* Error - couldn't mangle. */
1198 fname = mangled_name;
1201 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1202 got_match = mask_match(fname, mask, conn->case_sensitive);
1205 if(!got_match && check_mangled_names &&
1206 !mangle_is_8_3(fname, False, conn->params)) {
1208 * It turns out that NT matches wildcards against
1209 * both long *and* short names. This may explain some
1210 * of the wildcard wierdness from old DOS clients
1211 * that some people have been seeing.... JRA.
1213 /* Force the mangling into 8.3. */
1214 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1215 continue; /* Error - couldn't mangle. */
1218 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1219 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1224 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1226 if (dont_descend && !isdots) {
1232 pathreal = talloc_asprintf(ctx,
1237 pathreal = talloc_asprintf(ctx,
1247 if (INFO_LEVEL_IS_UNIX(info_level)) {
1248 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1249 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1250 pathreal,strerror(errno)));
1251 TALLOC_FREE(pathreal);
1254 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1255 /* Needed to show the msdfs symlinks as
1258 if(lp_host_msdfs() &&
1259 lp_msdfs_root(SNUM(conn)) &&
1260 ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) {
1261 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1264 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1268 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1269 pathreal,strerror(errno)));
1270 TALLOC_FREE(pathreal);
1276 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1278 mode = dos_mode(conn,pathreal,&sbuf);
1281 if (!dir_check_ftype(conn,mode,dirtype)) {
1282 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1283 TALLOC_FREE(pathreal);
1287 if (!(mode & aDIR)) {
1288 file_size = get_file_size(sbuf);
1290 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1292 mdate_ts = get_mtimespec(&sbuf);
1293 adate_ts = get_atimespec(&sbuf);
1294 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1296 if (lp_dos_filetime_resolution(SNUM(conn))) {
1297 dos_filetime_timespec(&create_date_ts);
1298 dos_filetime_timespec(&mdate_ts);
1299 dos_filetime_timespec(&adate_ts);
1302 create_date = convert_timespec_to_time_t(create_date_ts);
1303 mdate = convert_timespec_to_time_t(mdate_ts);
1304 adate = convert_timespec_to_time_t(adate_ts);
1306 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1310 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1317 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1319 switch (info_level) {
1320 case SMB_FIND_INFO_STANDARD:
1321 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1322 if(requires_resume_key) {
1326 srv_put_dos_date2(p,0,create_date);
1327 srv_put_dos_date2(p,4,adate);
1328 srv_put_dos_date2(p,8,mdate);
1329 SIVAL(p,12,(uint32)file_size);
1330 SIVAL(p,16,(uint32)allocation_size);
1334 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1335 p += ucs2_align(base_data, p, 0);
1337 len = srvstr_push(base_data, flags2, p,
1338 fname, PTR_DIFF(end_data, p),
1340 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1342 SCVAL(nameptr, -1, len - 2);
1344 SCVAL(nameptr, -1, 0);
1348 SCVAL(nameptr, -1, len - 1);
1350 SCVAL(nameptr, -1, 0);
1356 case SMB_FIND_EA_SIZE:
1357 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1358 if(requires_resume_key) {
1362 srv_put_dos_date2(p,0,create_date);
1363 srv_put_dos_date2(p,4,adate);
1364 srv_put_dos_date2(p,8,mdate);
1365 SIVAL(p,12,(uint32)file_size);
1366 SIVAL(p,16,(uint32)allocation_size);
1369 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1370 SIVAL(p,22,ea_size); /* Extended attributes */
1374 len = srvstr_push(base_data, flags2,
1375 p, fname, PTR_DIFF(end_data, p),
1376 STR_TERMINATE | STR_NOALIGN);
1377 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1390 SCVAL(nameptr,0,len);
1392 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1395 case SMB_FIND_EA_LIST:
1397 struct ea_list *file_list = NULL;
1400 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1404 if(requires_resume_key) {
1408 srv_put_dos_date2(p,0,create_date);
1409 srv_put_dos_date2(p,4,adate);
1410 srv_put_dos_date2(p,8,mdate);
1411 SIVAL(p,12,(uint32)file_size);
1412 SIVAL(p,16,(uint32)allocation_size);
1414 p += 22; /* p now points to the EA area. */
1416 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1417 name_list = ea_list_union(name_list, file_list, &ea_len);
1419 /* We need to determine if this entry will fit in the space available. */
1420 /* Max string size is 255 bytes. */
1421 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1422 /* Move the dirptr back to prev_dirpos */
1423 dptr_SeekDir(conn->dirptr, prev_dirpos);
1424 *out_of_space = True;
1425 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1426 return False; /* Not finished - just out of space */
1429 /* Push the ea_data followed by the name. */
1430 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1432 len = srvstr_push(base_data, flags2,
1433 p + 1, fname, PTR_DIFF(end_data, p+1),
1434 STR_TERMINATE | STR_NOALIGN);
1435 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1448 SCVAL(nameptr,0,len);
1450 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1454 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1455 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1456 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1458 SIVAL(p,0,reskey); p += 4;
1459 put_long_date_timespec(p,create_date_ts); p += 8;
1460 put_long_date_timespec(p,adate_ts); p += 8;
1461 put_long_date_timespec(p,mdate_ts); p += 8;
1462 put_long_date_timespec(p,mdate_ts); p += 8;
1463 SOFF_T(p,0,file_size); p += 8;
1464 SOFF_T(p,0,allocation_size); p += 8;
1465 SIVAL(p,0,nt_extmode); p += 4;
1466 q = p; p += 4; /* q is placeholder for name length. */
1468 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1469 SIVAL(p,0,ea_size); /* Extended attributes */
1472 /* Clear the short name buffer. This is
1473 * IMPORTANT as not doing so will trigger
1474 * a Win2k client bug. JRA.
1476 if (!was_8_3 && check_mangled_names) {
1477 if (!name_to_8_3(fname,mangled_name,True,
1479 /* Error - mangle failed ! */
1480 memset(mangled_name,'\0',12);
1482 mangled_name[12] = 0;
1483 len = srvstr_push(base_data, flags2,
1484 p+2, mangled_name, 24,
1485 STR_UPPER|STR_UNICODE);
1487 memset(p + 2 + len,'\0',24 - len);
1494 len = srvstr_push(base_data, flags2, p,
1495 fname, PTR_DIFF(end_data, p),
1496 STR_TERMINATE_ASCII);
1499 SIVAL(p,0,0); /* Ensure any padding is null. */
1500 len = PTR_DIFF(p, pdata);
1501 len = (len + 3) & ~3;
1506 case SMB_FIND_FILE_DIRECTORY_INFO:
1507 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1509 SIVAL(p,0,reskey); p += 4;
1510 put_long_date_timespec(p,create_date_ts); p += 8;
1511 put_long_date_timespec(p,adate_ts); p += 8;
1512 put_long_date_timespec(p,mdate_ts); p += 8;
1513 put_long_date_timespec(p,mdate_ts); p += 8;
1514 SOFF_T(p,0,file_size); p += 8;
1515 SOFF_T(p,0,allocation_size); p += 8;
1516 SIVAL(p,0,nt_extmode); p += 4;
1517 len = srvstr_push(base_data, flags2,
1518 p + 4, fname, PTR_DIFF(end_data, p+4),
1519 STR_TERMINATE_ASCII);
1522 SIVAL(p,0,0); /* Ensure any padding is null. */
1523 len = PTR_DIFF(p, pdata);
1524 len = (len + 3) & ~3;
1529 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1530 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1532 SIVAL(p,0,reskey); p += 4;
1533 put_long_date_timespec(p,create_date_ts); p += 8;
1534 put_long_date_timespec(p,adate_ts); p += 8;
1535 put_long_date_timespec(p,mdate_ts); p += 8;
1536 put_long_date_timespec(p,mdate_ts); p += 8;
1537 SOFF_T(p,0,file_size); p += 8;
1538 SOFF_T(p,0,allocation_size); p += 8;
1539 SIVAL(p,0,nt_extmode); p += 4;
1540 q = p; p += 4; /* q is placeholder for name length. */
1542 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1543 SIVAL(p,0,ea_size); /* Extended attributes */
1546 len = srvstr_push(base_data, flags2, p,
1547 fname, PTR_DIFF(end_data, p),
1548 STR_TERMINATE_ASCII);
1552 SIVAL(p,0,0); /* Ensure any padding is null. */
1553 len = PTR_DIFF(p, pdata);
1554 len = (len + 3) & ~3;
1559 case SMB_FIND_FILE_NAMES_INFO:
1560 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1562 SIVAL(p,0,reskey); p += 4;
1564 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1565 acl on a dir (tridge) */
1566 len = srvstr_push(base_data, flags2, p,
1567 fname, PTR_DIFF(end_data, p),
1568 STR_TERMINATE_ASCII);
1571 SIVAL(p,0,0); /* Ensure any padding is null. */
1572 len = PTR_DIFF(p, pdata);
1573 len = (len + 3) & ~3;
1578 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1579 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1581 SIVAL(p,0,reskey); p += 4;
1582 put_long_date_timespec(p,create_date_ts); p += 8;
1583 put_long_date_timespec(p,adate_ts); p += 8;
1584 put_long_date_timespec(p,mdate_ts); p += 8;
1585 put_long_date_timespec(p,mdate_ts); p += 8;
1586 SOFF_T(p,0,file_size); p += 8;
1587 SOFF_T(p,0,allocation_size); p += 8;
1588 SIVAL(p,0,nt_extmode); p += 4;
1589 q = p; p += 4; /* q is placeholder for name length. */
1591 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1592 SIVAL(p,0,ea_size); /* Extended attributes */
1595 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1596 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1597 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1598 len = srvstr_push(base_data, flags2, p,
1599 fname, PTR_DIFF(end_data, p),
1600 STR_TERMINATE_ASCII);
1603 SIVAL(p,0,0); /* Ensure any padding is null. */
1604 len = PTR_DIFF(p, pdata);
1605 len = (len + 3) & ~3;
1610 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1611 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1612 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1614 SIVAL(p,0,reskey); p += 4;
1615 put_long_date_timespec(p,create_date_ts); p += 8;
1616 put_long_date_timespec(p,adate_ts); p += 8;
1617 put_long_date_timespec(p,mdate_ts); p += 8;
1618 put_long_date_timespec(p,mdate_ts); p += 8;
1619 SOFF_T(p,0,file_size); p += 8;
1620 SOFF_T(p,0,allocation_size); p += 8;
1621 SIVAL(p,0,nt_extmode); p += 4;
1622 q = p; p += 4; /* q is placeholder for name length */
1624 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1625 SIVAL(p,0,ea_size); /* Extended attributes */
1628 /* Clear the short name buffer. This is
1629 * IMPORTANT as not doing so will trigger
1630 * a Win2k client bug. JRA.
1632 if (!was_8_3 && check_mangled_names) {
1633 if (!name_to_8_3(fname,mangled_name,True,
1635 /* Error - mangle failed ! */
1636 memset(mangled_name,'\0',12);
1638 mangled_name[12] = 0;
1639 len = srvstr_push(base_data, flags2,
1640 p+2, mangled_name, 24,
1641 STR_UPPER|STR_UNICODE);
1644 memset(p + 2 + len,'\0',24 - len);
1651 SSVAL(p,0,0); p += 2; /* Reserved ? */
1652 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1653 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1654 len = srvstr_push(base_data, flags2, p,
1655 fname, PTR_DIFF(end_data, p),
1656 STR_TERMINATE_ASCII);
1659 SIVAL(p,0,0); /* Ensure any padding is null. */
1660 len = PTR_DIFF(p, pdata);
1661 len = (len + 3) & ~3;
1666 /* CIFS UNIX Extension. */
1668 case SMB_FIND_FILE_UNIX:
1669 case SMB_FIND_FILE_UNIX_INFO2:
1671 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1673 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1675 if (info_level == SMB_FIND_FILE_UNIX) {
1676 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1677 p = store_file_unix_basic(conn, p,
1679 len = srvstr_push(base_data, flags2, p,
1680 fname, PTR_DIFF(end_data, p),
1683 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1684 p = store_file_unix_basic_info2(conn, p,
1688 len = srvstr_push(base_data, flags2, p, fname,
1689 PTR_DIFF(end_data, p), 0);
1690 SIVAL(nameptr, 0, len);
1694 SIVAL(p,0,0); /* Ensure any padding is null. */
1696 len = PTR_DIFF(p, pdata);
1697 len = (len + 3) & ~3;
1698 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1700 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1709 if (PTR_DIFF(p,pdata) > space_remaining) {
1710 /* Move the dirptr back to prev_dirpos */
1711 dptr_SeekDir(conn->dirptr, prev_dirpos);
1712 *out_of_space = True;
1713 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1714 return False; /* Not finished - just out of space */
1717 /* Setup the last entry pointer, as an offset from base_data */
1718 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1719 /* Advance the data pointer to the next slot */
1725 /****************************************************************************
1726 Reply to a TRANS2_FINDFIRST.
1727 ****************************************************************************/
1729 static void call_trans2findfirst(connection_struct *conn,
1730 struct smb_request *req,
1731 char **pparams, int total_params,
1732 char **ppdata, int total_data,
1733 unsigned int max_data_bytes)
1735 /* We must be careful here that we don't return more than the
1736 allowed number of data bytes. If this means returning fewer than
1737 maxentries then so be it. We assume that the redirector has
1738 enough room for the fixed number of parameter bytes it has
1740 char *params = *pparams;
1741 char *pdata = *ppdata;
1745 uint16 findfirst_flags;
1746 bool close_after_first;
1748 bool requires_resume_key;
1750 char *directory = NULL;
1751 const char *mask = NULL;
1753 int last_entry_off=0;
1757 bool finished = False;
1758 bool dont_descend = False;
1759 bool out_of_space = False;
1760 int space_remaining;
1761 bool mask_contains_wcard = False;
1762 SMB_STRUCT_STAT sbuf;
1763 struct ea_list *ea_list = NULL;
1764 NTSTATUS ntstatus = NT_STATUS_OK;
1765 TALLOC_CTX *ctx = talloc_tos();
1767 if (total_params < 13) {
1768 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1772 dirtype = SVAL(params,0);
1773 maxentries = SVAL(params,2);
1774 findfirst_flags = SVAL(params,4);
1775 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1776 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1777 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1778 info_level = SVAL(params,6);
1780 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1781 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1782 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1783 info_level, max_data_bytes));
1786 /* W2K3 seems to treat zero as 1. */
1790 switch (info_level) {
1791 case SMB_FIND_INFO_STANDARD:
1792 case SMB_FIND_EA_SIZE:
1793 case SMB_FIND_EA_LIST:
1794 case SMB_FIND_FILE_DIRECTORY_INFO:
1795 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1796 case SMB_FIND_FILE_NAMES_INFO:
1797 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1798 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1799 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1801 case SMB_FIND_FILE_UNIX:
1802 case SMB_FIND_FILE_UNIX_INFO2:
1803 if (!lp_unix_extensions()) {
1804 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1809 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1813 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1814 params+12, total_params - 12,
1815 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1816 if (!NT_STATUS_IS_OK(ntstatus)) {
1817 reply_nterror(req, ntstatus);
1821 ntstatus = resolve_dfspath_wcard(ctx, conn,
1822 req->flags2 & FLAGS2_DFS_PATHNAMES,
1825 &mask_contains_wcard);
1826 if (!NT_STATUS_IS_OK(ntstatus)) {
1827 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1828 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1829 ERRSRV, ERRbadpath);
1832 reply_nterror(req, ntstatus);
1836 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1837 if (!NT_STATUS_IS_OK(ntstatus)) {
1838 reply_nterror(req, ntstatus);
1842 ntstatus = check_name(conn, directory);
1843 if (!NT_STATUS_IS_OK(ntstatus)) {
1844 reply_nterror(req, ntstatus);
1848 p = strrchr_m(directory,'/');
1850 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1851 if((directory[0] == '.') && (directory[1] == '\0')) {
1853 mask_contains_wcard = True;
1857 directory = talloc_strdup(talloc_tos(), "./");
1859 reply_nterror(req, NT_STATUS_NO_MEMORY);
1867 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1869 if (info_level == SMB_FIND_EA_LIST) {
1872 if (total_data < 4) {
1873 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1877 ea_size = IVAL(pdata,0);
1878 if (ea_size != total_data) {
1879 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1880 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1881 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1885 if (!lp_ea_support(SNUM(conn))) {
1886 reply_doserror(req, ERRDOS, ERReasnotsupported);
1890 /* Pull out the list of names. */
1891 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1893 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1898 *ppdata = (char *)SMB_REALLOC(
1899 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1900 if(*ppdata == NULL ) {
1901 reply_nterror(req, NT_STATUS_NO_MEMORY);
1905 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1907 /* Realloc the params space */
1908 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1909 if (*pparams == NULL) {
1910 reply_nterror(req, NT_STATUS_NO_MEMORY);
1915 /* Save the wildcard match and attribs we are using on this directory -
1916 needed as lanman2 assumes these are being saved between calls */
1918 ntstatus = dptr_create(conn,
1924 mask_contains_wcard,
1928 if (!NT_STATUS_IS_OK(ntstatus)) {
1929 reply_nterror(req, ntstatus);
1933 dptr_num = dptr_dnum(conn->dirptr);
1934 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1936 /* We don't need to check for VOL here as this is returned by
1937 a different TRANS2 call. */
1939 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1940 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1941 dont_descend = True;
1944 space_remaining = max_data_bytes;
1945 out_of_space = False;
1947 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1948 bool got_exact_match = False;
1950 /* this is a heuristic to avoid seeking the dirptr except when
1951 absolutely necessary. It allows for a filename of about 40 chars */
1952 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1953 out_of_space = True;
1956 finished = !get_lanman2_dir_entry(ctx,
1959 mask,dirtype,info_level,
1960 requires_resume_key,dont_descend,
1962 space_remaining, &out_of_space,
1964 &last_entry_off, ea_list);
1967 if (finished && out_of_space)
1970 if (!finished && !out_of_space)
1974 * As an optimisation if we know we aren't looking
1975 * for a wildcard name (ie. the name matches the wildcard exactly)
1976 * then we can finish on any (first) match.
1977 * This speeds up large directory searches. JRA.
1983 /* Ensure space_remaining never goes -ve. */
1984 if (PTR_DIFF(p,pdata) > max_data_bytes) {
1985 space_remaining = 0;
1986 out_of_space = true;
1988 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1992 /* Check if we can close the dirptr */
1993 if(close_after_first || (finished && close_if_end)) {
1994 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1995 dptr_close(&dptr_num);
1999 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2000 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2001 * the protocol level is less than NT1. Tested with smbclient. JRA.
2002 * This should fix the OS/2 client bug #2335.
2005 if(numentries == 0) {
2006 dptr_close(&dptr_num);
2007 if (Protocol < PROTOCOL_NT1) {
2008 reply_doserror(req, ERRDOS, ERRnofiles);
2011 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2012 ERRDOS, ERRbadfile);
2017 /* At this point pdata points to numentries directory entries. */
2019 /* Set up the return parameter block */
2020 SSVAL(params,0,dptr_num);
2021 SSVAL(params,2,numentries);
2022 SSVAL(params,4,finished);
2023 SSVAL(params,6,0); /* Never an EA error */
2024 SSVAL(params,8,last_entry_off);
2026 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2029 if ((! *directory) && dptr_path(dptr_num)) {
2030 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2032 reply_nterror(req, NT_STATUS_NO_MEMORY);
2036 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2037 smb_fn_name(CVAL(req->inbuf,smb_com)),
2038 mask, directory, dirtype, numentries ) );
2041 * Force a name mangle here to ensure that the
2042 * mask as an 8.3 name is top of the mangled cache.
2043 * The reasons for this are subtle. Don't remove
2044 * this code unless you know what you are doing
2045 * (see PR#13758). JRA.
2048 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2049 char mangled_name[13];
2050 name_to_8_3(mask, mangled_name, True, conn->params);
2056 /****************************************************************************
2057 Reply to a TRANS2_FINDNEXT.
2058 ****************************************************************************/
2060 static void call_trans2findnext(connection_struct *conn,
2061 struct smb_request *req,
2062 char **pparams, int total_params,
2063 char **ppdata, int total_data,
2064 unsigned int max_data_bytes)
2066 /* We must be careful here that we don't return more than the
2067 allowed number of data bytes. If this means returning fewer than
2068 maxentries then so be it. We assume that the redirector has
2069 enough room for the fixed number of parameter bytes it has
2071 char *params = *pparams;
2072 char *pdata = *ppdata;
2078 uint16 findnext_flags;
2079 bool close_after_request;
2081 bool requires_resume_key;
2083 bool mask_contains_wcard = False;
2084 char *resume_name = NULL;
2085 const char *mask = NULL;
2086 const char *directory = NULL;
2090 int i, last_entry_off=0;
2091 bool finished = False;
2092 bool dont_descend = False;
2093 bool out_of_space = False;
2094 int space_remaining;
2095 struct ea_list *ea_list = NULL;
2096 NTSTATUS ntstatus = NT_STATUS_OK;
2097 TALLOC_CTX *ctx = talloc_tos();
2099 if (total_params < 13) {
2100 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2104 dptr_num = SVAL(params,0);
2105 maxentries = SVAL(params,2);
2106 info_level = SVAL(params,4);
2107 resume_key = IVAL(params,6);
2108 findnext_flags = SVAL(params,10);
2109 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2110 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2111 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2112 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2114 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2116 total_params - 12, STR_TERMINATE, &ntstatus,
2117 &mask_contains_wcard);
2118 if (!NT_STATUS_IS_OK(ntstatus)) {
2119 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2120 complain (it thinks we're asking for the directory above the shared
2121 path or an invalid name). Catch this as the resume name is only compared, never used in
2122 a file access. JRA. */
2123 srvstr_pull_talloc(ctx, params, req->flags2,
2124 &resume_name, params+12,
2128 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2129 reply_nterror(req, ntstatus);
2134 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2135 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2136 resume_key = %d resume name = %s continue=%d level = %d\n",
2137 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2138 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2141 /* W2K3 seems to treat zero as 1. */
2145 switch (info_level) {
2146 case SMB_FIND_INFO_STANDARD:
2147 case SMB_FIND_EA_SIZE:
2148 case SMB_FIND_EA_LIST:
2149 case SMB_FIND_FILE_DIRECTORY_INFO:
2150 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2151 case SMB_FIND_FILE_NAMES_INFO:
2152 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2153 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2154 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2156 case SMB_FIND_FILE_UNIX:
2157 case SMB_FIND_FILE_UNIX_INFO2:
2158 if (!lp_unix_extensions()) {
2159 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2164 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2168 if (info_level == SMB_FIND_EA_LIST) {
2171 if (total_data < 4) {
2172 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2176 ea_size = IVAL(pdata,0);
2177 if (ea_size != total_data) {
2178 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2179 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2180 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2184 if (!lp_ea_support(SNUM(conn))) {
2185 reply_doserror(req, ERRDOS, ERReasnotsupported);
2189 /* Pull out the list of names. */
2190 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2192 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2197 *ppdata = (char *)SMB_REALLOC(
2198 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2199 if(*ppdata == NULL) {
2200 reply_nterror(req, NT_STATUS_NO_MEMORY);
2205 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2207 /* Realloc the params space */
2208 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2209 if(*pparams == NULL ) {
2210 reply_nterror(req, NT_STATUS_NO_MEMORY);
2216 /* Check that the dptr is valid */
2217 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2218 reply_doserror(req, ERRDOS, ERRnofiles);
2222 string_set(&conn->dirpath,dptr_path(dptr_num));
2224 /* Get the wildcard mask from the dptr */
2225 if((p = dptr_wcard(dptr_num))== NULL) {
2226 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2227 reply_doserror(req, ERRDOS, ERRnofiles);
2232 directory = conn->dirpath;
2234 /* Get the attr mask from the dptr */
2235 dirtype = dptr_attr(dptr_num);
2237 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2238 dptr_num, mask, dirtype,
2240 dptr_TellDir(conn->dirptr)));
2242 /* We don't need to check for VOL here as this is returned by
2243 a different TRANS2 call. */
2245 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2246 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2247 dont_descend = True;
2250 space_remaining = max_data_bytes;
2251 out_of_space = False;
2254 * Seek to the correct position. We no longer use the resume key but
2255 * depend on the last file name instead.
2258 if(*resume_name && !continue_bit) {
2261 long current_pos = 0;
2263 * Remember, name_to_8_3 is called by
2264 * get_lanman2_dir_entry(), so the resume name
2265 * could be mangled. Ensure we check the unmangled name.
2268 if (mangle_is_mangled(resume_name, conn->params)) {
2269 char *new_resume_name = NULL;
2270 mangle_lookup_name_from_8_3(ctx,
2274 if (new_resume_name) {
2275 resume_name = new_resume_name;
2280 * Fix for NT redirector problem triggered by resume key indexes
2281 * changing between directory scans. We now return a resume key of 0
2282 * and instead look for the filename to continue from (also given
2283 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2284 * findfirst/findnext (as is usual) then the directory pointer
2285 * should already be at the correct place.
2288 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2289 } /* end if resume_name && !continue_bit */
2291 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2292 bool got_exact_match = False;
2294 /* this is a heuristic to avoid seeking the dirptr except when
2295 absolutely necessary. It allows for a filename of about 40 chars */
2296 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2297 out_of_space = True;
2300 finished = !get_lanman2_dir_entry(ctx,
2303 mask,dirtype,info_level,
2304 requires_resume_key,dont_descend,
2306 space_remaining, &out_of_space,
2308 &last_entry_off, ea_list);
2311 if (finished && out_of_space)
2314 if (!finished && !out_of_space)
2318 * As an optimisation if we know we aren't looking
2319 * for a wildcard name (ie. the name matches the wildcard exactly)
2320 * then we can finish on any (first) match.
2321 * This speeds up large directory searches. JRA.
2327 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2330 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2331 smb_fn_name(CVAL(req->inbuf,smb_com)),
2332 mask, directory, dirtype, numentries ) );
2334 /* Check if we can close the dirptr */
2335 if(close_after_request || (finished && close_if_end)) {
2336 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2337 dptr_close(&dptr_num); /* This frees up the saved mask */
2340 /* Set up the return parameter block */
2341 SSVAL(params,0,numentries);
2342 SSVAL(params,2,finished);
2343 SSVAL(params,4,0); /* Never an EA error */
2344 SSVAL(params,6,last_entry_off);
2346 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2352 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2354 E_md4hash(lp_servicename(SNUM(conn)),objid);
2358 /****************************************************************************
2359 Reply to a TRANS2_QFSINFO (query filesystem info).
2360 ****************************************************************************/
2362 static void call_trans2qfsinfo(connection_struct *conn,
2363 struct smb_request *req,
2364 char **pparams, int total_params,
2365 char **ppdata, int total_data,
2366 unsigned int max_data_bytes)
2368 char *pdata, *end_data;
2369 char *params = *pparams;
2373 const char *vname = volume_label(SNUM(conn));
2374 int snum = SNUM(conn);
2375 char *fstype = lp_fstype(SNUM(conn));
2376 uint32 additional_flags = 0;
2378 if (total_params < 2) {
2379 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2383 info_level = SVAL(params,0);
2386 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2387 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2388 "info level (0x%x) on IPC$.\n",
2389 (unsigned int)info_level));
2390 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2395 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2396 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2397 DEBUG(0,("call_trans2qfsinfo: encryption required "
2398 "and info level 0x%x sent.\n",
2399 (unsigned int)info_level));
2400 exit_server_cleanly("encryption required "
2406 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2408 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2409 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2410 reply_doserror(req, ERRSRV, ERRinvdevice);
2414 *ppdata = (char *)SMB_REALLOC(
2415 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2416 if (*ppdata == NULL ) {
2417 reply_nterror(req, NT_STATUS_NO_MEMORY);
2422 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2423 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2425 switch (info_level) {
2426 case SMB_INFO_ALLOCATION:
2428 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2430 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2431 reply_unixerror(req, ERRHRD, ERRgeneral);
2435 block_size = lp_block_size(snum);
2436 if (bsize < block_size) {
2437 SMB_BIG_UINT factor = block_size/bsize;
2442 if (bsize > block_size) {
2443 SMB_BIG_UINT factor = bsize/block_size;
2448 bytes_per_sector = 512;
2449 sectors_per_unit = bsize/bytes_per_sector;
2451 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2452 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2453 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2455 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2456 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2457 SIVAL(pdata,l1_cUnit,dsize);
2458 SIVAL(pdata,l1_cUnitAvail,dfree);
2459 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2463 case SMB_INFO_VOLUME:
2464 /* Return volume name */
2466 * Add volume serial number - hash of a combination of
2467 * the called hostname and the service name.
2469 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2471 * Win2k3 and previous mess this up by sending a name length
2472 * one byte short. I believe only older clients (OS/2 Win9x) use
2473 * this call so try fixing this by adding a terminating null to
2474 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2478 pdata+l2_vol_szVolLabel, vname,
2479 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2480 STR_NOALIGN|STR_TERMINATE);
2481 SCVAL(pdata,l2_vol_cch,len);
2482 data_len = l2_vol_szVolLabel + len;
2483 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2484 (unsigned)st.st_ctime, len, vname));
2487 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2488 case SMB_FS_ATTRIBUTE_INFORMATION:
2490 additional_flags = 0;
2491 #if defined(HAVE_SYS_QUOTAS)
2492 additional_flags |= FILE_VOLUME_QUOTAS;
2495 if(lp_nt_acl_support(SNUM(conn))) {
2496 additional_flags |= FILE_PERSISTENT_ACLS;
2499 /* Capabilities are filled in at connection time through STATVFS call */
2500 additional_flags |= conn->fs_capabilities;
2502 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2503 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2504 additional_flags); /* FS ATTRIBUTES */
2506 SIVAL(pdata,4,255); /* Max filename component length */
2507 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2508 and will think we can't do long filenames */
2509 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2510 PTR_DIFF(end_data, pdata+12),
2513 data_len = 12 + len;
2516 case SMB_QUERY_FS_LABEL_INFO:
2517 case SMB_FS_LABEL_INFORMATION:
2518 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2519 PTR_DIFF(end_data, pdata+4), 0);
2524 case SMB_QUERY_FS_VOLUME_INFO:
2525 case SMB_FS_VOLUME_INFORMATION:
2528 * Add volume serial number - hash of a combination of
2529 * the called hostname and the service name.
2531 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2532 (str_checksum(get_local_machine_name())<<16));
2534 /* Max label len is 32 characters. */
2535 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2536 PTR_DIFF(end_data, pdata+18),
2538 SIVAL(pdata,12,len);
2541 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2542 (int)strlen(vname),vname, lp_servicename(snum)));
2545 case SMB_QUERY_FS_SIZE_INFO:
2546 case SMB_FS_SIZE_INFORMATION:
2548 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2550 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2551 reply_unixerror(req, ERRHRD, ERRgeneral);
2554 block_size = lp_block_size(snum);
2555 if (bsize < block_size) {
2556 SMB_BIG_UINT factor = block_size/bsize;
2561 if (bsize > block_size) {
2562 SMB_BIG_UINT factor = bsize/block_size;
2567 bytes_per_sector = 512;
2568 sectors_per_unit = bsize/bytes_per_sector;
2569 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2570 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2571 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2572 SBIG_UINT(pdata,0,dsize);
2573 SBIG_UINT(pdata,8,dfree);
2574 SIVAL(pdata,16,sectors_per_unit);
2575 SIVAL(pdata,20,bytes_per_sector);
2579 case SMB_FS_FULL_SIZE_INFORMATION:
2581 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2583 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2584 reply_unixerror(req, ERRHRD, ERRgeneral);
2587 block_size = lp_block_size(snum);
2588 if (bsize < block_size) {
2589 SMB_BIG_UINT factor = block_size/bsize;
2594 if (bsize > block_size) {
2595 SMB_BIG_UINT factor = bsize/block_size;
2600 bytes_per_sector = 512;
2601 sectors_per_unit = bsize/bytes_per_sector;
2602 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2603 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2604 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2605 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2606 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2607 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2608 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2609 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2613 case SMB_QUERY_FS_DEVICE_INFO:
2614 case SMB_FS_DEVICE_INFORMATION:
2616 SIVAL(pdata,0,0); /* dev type */
2617 SIVAL(pdata,4,0); /* characteristics */
2620 #ifdef HAVE_SYS_QUOTAS
2621 case SMB_FS_QUOTA_INFORMATION:
2623 * what we have to send --metze:
2625 * Unknown1: 24 NULL bytes
2626 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2627 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2628 * Quota Flags: 2 byte :
2629 * Unknown3: 6 NULL bytes
2633 * details for Quota Flags:
2635 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2636 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2637 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2638 * 0x0001 Enable Quotas: enable quota for this fs
2642 /* we need to fake up a fsp here,
2643 * because its not send in this call
2646 SMB_NTQUOTA_STRUCT quotas;
2649 ZERO_STRUCT(quotas);
2655 if (current_user.ut.uid != 0) {
2656 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2657 lp_servicename(SNUM(conn)),conn->user));
2658 reply_doserror(req, ERRDOS, ERRnoaccess);
2662 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2663 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2664 reply_doserror(req, ERRSRV, ERRerror);
2670 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2672 /* Unknown1 24 NULL bytes*/
2673 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2674 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2675 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2677 /* Default Soft Quota 8 bytes */
2678 SBIG_UINT(pdata,24,quotas.softlim);
2680 /* Default Hard Quota 8 bytes */
2681 SBIG_UINT(pdata,32,quotas.hardlim);
2683 /* Quota flag 2 bytes */
2684 SSVAL(pdata,40,quotas.qflags);
2686 /* Unknown3 6 NULL bytes */
2692 #endif /* HAVE_SYS_QUOTAS */
2693 case SMB_FS_OBJECTID_INFORMATION:
2695 unsigned char objid[16];
2696 memcpy(pdata,create_volume_objectid(conn, objid),16);
2702 * Query the version and capabilities of the CIFS UNIX extensions
2706 case SMB_QUERY_CIFS_UNIX_INFO:
2708 bool large_write = lp_min_receive_file_size() &&
2709 !srv_is_signing_active();
2710 bool large_read = !srv_is_signing_active();
2711 int encrypt_caps = 0;
2713 if (!lp_unix_extensions()) {
2714 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2718 switch (conn->encrypt_level) {
2724 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2727 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2728 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2729 large_write = false;
2735 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2736 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2738 /* We have POSIX ACLs, pathname, encryption,
2739 * large read/write, and locking capability. */
2741 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2742 CIFS_UNIX_POSIX_ACLS_CAP|
2743 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2744 CIFS_UNIX_FCNTL_LOCKS_CAP|
2745 CIFS_UNIX_EXTATTR_CAP|
2746 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2748 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2750 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2754 case SMB_QUERY_POSIX_FS_INFO:
2757 vfs_statvfs_struct svfs;
2759 if (!lp_unix_extensions()) {
2760 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2764 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2768 SIVAL(pdata,0,svfs.OptimalTransferSize);
2769 SIVAL(pdata,4,svfs.BlockSize);
2770 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2771 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2772 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2773 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2774 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2775 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2776 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2778 } else if (rc == EOPNOTSUPP) {
2779 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2781 #endif /* EOPNOTSUPP */
2783 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2784 reply_doserror(req, ERRSRV, ERRerror);
2790 case SMB_QUERY_POSIX_WHOAMI:
2796 if (!lp_unix_extensions()) {
2797 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2801 if (max_data_bytes < 40) {
2802 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2806 /* We ARE guest if global_sid_Builtin_Guests is
2807 * in our list of SIDs.
2809 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2810 current_user.nt_user_token)) {
2811 flags |= SMB_WHOAMI_GUEST;
2814 /* We are NOT guest if global_sid_Authenticated_Users
2815 * is in our list of SIDs.
2817 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2818 current_user.nt_user_token)) {
2819 flags &= ~SMB_WHOAMI_GUEST;
2822 /* NOTE: 8 bytes for UID/GID, irrespective of native
2823 * platform size. This matches
2824 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2826 data_len = 4 /* flags */
2833 + 4 /* pad/reserved */
2834 + (current_user.ut.ngroups * 8)
2836 + (current_user.nt_user_token->num_sids *
2840 SIVAL(pdata, 0, flags);
2841 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2842 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2843 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2846 if (data_len >= max_data_bytes) {
2847 /* Potential overflow, skip the GIDs and SIDs. */
2849 SIVAL(pdata, 24, 0); /* num_groups */
2850 SIVAL(pdata, 28, 0); /* num_sids */
2851 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2852 SIVAL(pdata, 36, 0); /* reserved */
2858 SIVAL(pdata, 24, current_user.ut.ngroups);
2860 current_user.nt_user_token->num_sids);
2862 /* We walk the SID list twice, but this call is fairly
2863 * infrequent, and I don't expect that it's performance
2864 * sensitive -- jpeach
2866 for (i = 0, sid_bytes = 0;
2867 i < current_user.nt_user_token->num_sids; ++i) {
2868 sid_bytes += ndr_size_dom_sid(
2869 ¤t_user.nt_user_token->user_sids[i], 0);
2872 /* SID list byte count */
2873 SIVAL(pdata, 32, sid_bytes);
2875 /* 4 bytes pad/reserved - must be zero */
2876 SIVAL(pdata, 36, 0);
2880 for (i = 0; i < current_user.ut.ngroups; ++i) {
2881 SBIG_UINT(pdata, data_len,
2882 (SMB_BIG_UINT)current_user.ut.groups[i]);
2888 i < current_user.nt_user_token->num_sids; ++i) {
2889 int sid_len = ndr_size_dom_sid(
2890 ¤t_user.nt_user_token->user_sids[i], 0);
2892 sid_linearize(pdata + data_len, sid_len,
2893 ¤t_user.nt_user_token->user_sids[i]);
2894 data_len += sid_len;
2900 case SMB_MAC_QUERY_FS_INFO:
2902 * Thursby MAC extension... ONLY on NTFS filesystems
2903 * once we do streams then we don't need this
2905 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2907 SIVAL(pdata,84,0x100); /* Don't support mac... */
2912 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2917 send_trans2_replies(conn, req, params, 0, pdata, data_len,
2920 DEBUG( 4, ( "%s info_level = %d\n",
2921 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2926 /****************************************************************************
2927 Reply to a TRANS2_SETFSINFO (set filesystem info).
2928 ****************************************************************************/
2930 static void call_trans2setfsinfo(connection_struct *conn,
2931 struct smb_request *req,
2932 char **pparams, int total_params,
2933 char **ppdata, int total_data,
2934 unsigned int max_data_bytes)
2936 char *pdata = *ppdata;
2937 char *params = *pparams;
2940 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2943 if (total_params < 4) {
2944 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2946 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2950 info_level = SVAL(params,2);
2953 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
2954 info_level != SMB_SET_CIFS_UNIX_INFO) {
2955 DEBUG(0,("call_trans2setfsinfo: not an allowed "
2956 "info level (0x%x) on IPC$.\n",
2957 (unsigned int)info_level));
2958 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2963 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2964 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
2965 DEBUG(0,("call_trans2setfsinfo: encryption required "
2966 "and info level 0x%x sent.\n",
2967 (unsigned int)info_level));
2968 exit_server_cleanly("encryption required "
2974 switch(info_level) {
2975 case SMB_SET_CIFS_UNIX_INFO:
2977 uint16 client_unix_major;
2978 uint16 client_unix_minor;
2979 uint32 client_unix_cap_low;
2980 uint32 client_unix_cap_high;
2982 if (!lp_unix_extensions()) {
2984 NT_STATUS_INVALID_LEVEL);
2988 /* There should be 12 bytes of capabilities set. */
2989 if (total_data < 8) {
2992 NT_STATUS_INVALID_PARAMETER);
2995 client_unix_major = SVAL(pdata,0);
2996 client_unix_minor = SVAL(pdata,2);
2997 client_unix_cap_low = IVAL(pdata,4);
2998 client_unix_cap_high = IVAL(pdata,8);
2999 /* Just print these values for now. */
3000 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3001 cap_low = 0x%x, cap_high = 0x%x\n",
3002 (unsigned int)client_unix_major,
3003 (unsigned int)client_unix_minor,
3004 (unsigned int)client_unix_cap_low,
3005 (unsigned int)client_unix_cap_high ));
3007 /* Here is where we must switch to posix pathname processing... */
3008 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3009 lp_set_posix_pathnames();
3010 mangle_change_to_posix();
3013 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3014 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3015 /* Client that knows how to do posix locks,
3016 * but not posix open/mkdir operations. Set a
3017 * default type for read/write checks. */
3019 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3025 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3028 size_t param_len = 0;
3029 size_t data_len = total_data;
3031 if (!lp_unix_extensions()) {
3034 NT_STATUS_INVALID_LEVEL);
3038 if (lp_smb_encrypt(SNUM(conn)) == false) {
3041 NT_STATUS_NOT_SUPPORTED);
3045 DEBUG( 4,("call_trans2setfsinfo: "
3046 "request transport encrption.\n"));
3048 status = srv_request_encryption_setup(conn,
3049 (unsigned char **)ppdata,
3051 (unsigned char **)pparams,
3054 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3055 !NT_STATUS_IS_OK(status)) {
3056 reply_nterror(req, status);
3060 send_trans2_replies(conn, req,
3067 if (NT_STATUS_IS_OK(status)) {
3068 /* Server-side transport
3069 * encryption is now *on*. */
3070 status = srv_encryption_start(conn);
3071 if (!NT_STATUS_IS_OK(status)) {
3072 exit_server_cleanly(
3073 "Failure in setting "
3074 "up encrypted transport");
3080 case SMB_FS_QUOTA_INFORMATION:
3082 files_struct *fsp = NULL;
3083 SMB_NTQUOTA_STRUCT quotas;
3085 ZERO_STRUCT(quotas);
3088 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3089 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3090 lp_servicename(SNUM(conn)),conn->user));
3091 reply_doserror(req, ERRSRV, ERRaccess);
3095 /* note: normaly there're 48 bytes,
3096 * but we didn't use the last 6 bytes for now
3099 fsp = file_fsp(SVAL(params,0));
3100 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3101 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3103 req, NT_STATUS_INVALID_HANDLE);
3107 if (total_data < 42) {
3108 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3112 NT_STATUS_INVALID_PARAMETER);
3116 /* unknown_1 24 NULL bytes in pdata*/
3118 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3119 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3120 #ifdef LARGE_SMB_OFF_T
3121 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3122 #else /* LARGE_SMB_OFF_T */
3123 if ((IVAL(pdata,28) != 0)&&
3124 ((quotas.softlim != 0xFFFFFFFF)||
3125 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3126 /* more than 32 bits? */
3129 NT_STATUS_INVALID_PARAMETER);
3132 #endif /* LARGE_SMB_OFF_T */
3134 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3135 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3136 #ifdef LARGE_SMB_OFF_T
3137 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3138 #else /* LARGE_SMB_OFF_T */
3139 if ((IVAL(pdata,36) != 0)&&
3140 ((quotas.hardlim != 0xFFFFFFFF)||
3141 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3142 /* more than 32 bits? */
3145 NT_STATUS_INVALID_PARAMETER);
3148 #endif /* LARGE_SMB_OFF_T */
3150 /* quota_flags 2 bytes **/
3151 quotas.qflags = SVAL(pdata,40);
3153 /* unknown_2 6 NULL bytes follow*/
3155 /* now set the quotas */
3156 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3157 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3158 reply_doserror(req, ERRSRV, ERRerror);
3165 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3167 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3173 * sending this reply works fine,
3174 * but I'm not sure it's the same
3175 * like windows do...
3178 reply_outbuf(req, 10, 0);
3181 #if defined(HAVE_POSIX_ACLS)
3182 /****************************************************************************
3183 Utility function to count the number of entries in a POSIX acl.
3184 ****************************************************************************/
3186 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3188 unsigned int ace_count = 0;
3189 int entry_id = SMB_ACL_FIRST_ENTRY;
3190 SMB_ACL_ENTRY_T entry;
3192 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3194 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3195 entry_id = SMB_ACL_NEXT_ENTRY;
3202 /****************************************************************************
3203 Utility function to marshall a POSIX acl into wire format.
3204 ****************************************************************************/
3206 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3208 int entry_id = SMB_ACL_FIRST_ENTRY;
3209 SMB_ACL_ENTRY_T entry;
3211 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3212 SMB_ACL_TAG_T tagtype;
3213 SMB_ACL_PERMSET_T permset;
3214 unsigned char perms = 0;
3215 unsigned int own_grp;
3218 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3219 entry_id = SMB_ACL_NEXT_ENTRY;
3222 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3223 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3227 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3228 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3232 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3233 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3234 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3236 SCVAL(pdata,1,perms);
3239 case SMB_ACL_USER_OBJ:
3240 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3241 own_grp = (unsigned int)pst->st_uid;
3242 SIVAL(pdata,2,own_grp);
3247 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3249 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3252 own_grp = (unsigned int)*puid;
3253 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3254 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3255 SIVAL(pdata,2,own_grp);
3259 case SMB_ACL_GROUP_OBJ:
3260 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3261 own_grp = (unsigned int)pst->st_gid;
3262 SIVAL(pdata,2,own_grp);
3267 gid_t *pgid= (gid_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)*pgid;
3273 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3274 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3275 SIVAL(pdata,2,own_grp);
3280 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3281 SIVAL(pdata,2,0xFFFFFFFF);
3282 SIVAL(pdata,6,0xFFFFFFFF);
3285 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3286 SIVAL(pdata,2,0xFFFFFFFF);
3287 SIVAL(pdata,6,0xFFFFFFFF);
3290 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3293 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3300 /****************************************************************************
3301 Store the FILE_UNIX_BASIC info.
3302 ****************************************************************************/
3304 static char *store_file_unix_basic(connection_struct *conn,
3307 const SMB_STRUCT_STAT *psbuf)
3309 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3310 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3312 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3315 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3318 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3319 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3320 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3323 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3327 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3331 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3334 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3338 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3342 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3345 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3349 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3356 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3357 * the chflags(2) (or equivalent) flags.
3359 * XXX: this really should be behind the VFS interface. To do this, we would
3360 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3361 * Each VFS module could then implement its own mapping as appropriate for the
3362 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3364 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3368 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3372 { UF_IMMUTABLE, EXT_IMMUTABLE },
3376 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3380 { UF_HIDDEN, EXT_HIDDEN },
3383 /* Do not remove. We need to guarantee that this array has at least one
3384 * entry to build on HP-UX.
3390 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3391 uint32 *smb_fflags, uint32 *smb_fmask)
3393 #ifdef HAVE_STAT_ST_FLAGS
3396 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3397 *smb_fmask |= info2_flags_map[i].smb_fflag;
3398 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3399 *smb_fflags |= info2_flags_map[i].smb_fflag;
3402 #endif /* HAVE_STAT_ST_FLAGS */
3405 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3406 const uint32 smb_fflags,
3407 const uint32 smb_fmask,
3410 #ifdef HAVE_STAT_ST_FLAGS
3411 uint32 max_fmask = 0;
3414 *stat_fflags = psbuf->st_flags;
3416 /* For each flags requested in smb_fmask, check the state of the
3417 * corresponding flag in smb_fflags and set or clear the matching
3421 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3422 max_fmask |= info2_flags_map[i].smb_fflag;
3423 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3424 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3425 *stat_fflags |= info2_flags_map[i].stat_fflag;
3427 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3432 /* If smb_fmask is asking to set any bits that are not supported by
3433 * our flag mappings, we should fail.
3435 if ((smb_fmask & max_fmask) != smb_fmask) {
3442 #endif /* HAVE_STAT_ST_FLAGS */
3446 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3447 * of file flags and birth (create) time.
3449 static char *store_file_unix_basic_info2(connection_struct *conn,
3452 const SMB_STRUCT_STAT *psbuf)
3454 uint32 file_flags = 0;
3455 uint32 flags_mask = 0;
3457 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3459 /* Create (birth) time 64 bit */
3460 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3463 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3464 SIVAL(pdata, 0, file_flags); /* flags */
3465 SIVAL(pdata, 4, flags_mask); /* mask */
3471 /****************************************************************************
3472 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3473 ****************************************************************************/
3475 static void call_trans2qpipeinfo(connection_struct *conn,
3476 struct smb_request *req,
3477 unsigned int tran_call,
3478 char **pparams, int total_params,
3479 char **ppdata, int total_data,
3480 unsigned int max_data_bytes)
3482 char *params = *pparams;
3483 char *pdata = *ppdata;
3484 unsigned int data_size = 0;
3485 unsigned int param_size = 2;
3487 smb_np_struct *p_pipe = NULL;
3490 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3494 if (total_params < 4) {
3495 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3499 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3500 if (p_pipe == NULL) {
3501 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3505 info_level = SVAL(params,2);
3507 *pparams = (char *)SMB_REALLOC(*pparams,2);
3508 if (*pparams == NULL) {
3509 reply_nterror(req, NT_STATUS_NO_MEMORY);
3514 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3515 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3516 if (*ppdata == NULL ) {
3517 reply_nterror(req, NT_STATUS_NO_MEMORY);
3522 switch (info_level) {
3523 case SMB_FILE_STANDARD_INFORMATION:
3525 SOFF_T(pdata,0,4096LL);
3532 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3536 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3542 /****************************************************************************
3543 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3544 file name or file id).
3545 ****************************************************************************/
3547 static void call_trans2qfilepathinfo(connection_struct *conn,
3548 struct smb_request *req,
3549 unsigned int tran_call,
3550 char **pparams, int total_params,
3551 char **ppdata, int total_data,
3552 unsigned int max_data_bytes)
3554 char *params = *pparams;
3555 char *pdata = *ppdata;
3556 char *dstart, *dend;
3560 SMB_OFF_T file_size=0;
3561 SMB_BIG_UINT allocation_size=0;
3562 unsigned int data_size = 0;
3563 unsigned int param_size = 2;
3564 SMB_STRUCT_STAT sbuf;
3565 char *dos_fname = NULL;
3571 bool delete_pending = False;
3573 time_t create_time, mtime, atime;
3574 struct timespec create_time_ts, mtime_ts, atime_ts;
3575 files_struct *fsp = NULL;
3576 struct file_id fileid;
3577 struct ea_list *ea_list = NULL;
3578 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3579 char *lock_data = NULL;
3580 TALLOC_CTX *ctx = talloc_tos();
3583 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3589 if (tran_call == TRANSACT2_QFILEINFO) {
3590 if (total_params < 4) {
3591 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3596 call_trans2qpipeinfo(conn, req, tran_call,
3597 pparams, total_params,
3603 fsp = file_fsp(SVAL(params,0));
3604 info_level = SVAL(params,2);
3606 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3608 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3609 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3613 /* Initial check for valid fsp ptr. */
3614 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
3618 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3620 reply_nterror(req, NT_STATUS_NO_MEMORY);
3624 if(fsp->fake_file_handle) {
3626 * This is actually for the QUOTA_FAKE_FILE --metze
3629 /* We know this name is ok, it's already passed the checks. */
3631 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3633 * This is actually a QFILEINFO on a directory
3634 * handle (returned from an NT SMB). NT5.0 seems
3635 * to do this call. JRA.
3638 if (INFO_LEVEL_IS_UNIX(info_level)) {
3639 /* Always do lstat for UNIX calls. */
3640 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3641 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3642 reply_unixerror(req,ERRDOS,ERRbadpath);
3645 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3646 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3647 reply_unixerror(req, ERRDOS, ERRbadpath);
3651 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3652 delete_pending = get_delete_on_close_flag(fileid);
3655 * Original code - this is an open file.
3657 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3661 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3662 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3663 reply_unixerror(req, ERRDOS, ERRbadfid);
3666 pos = fsp->fh->position_information;
3667 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3668 delete_pending = get_delete_on_close_flag(fileid);
3669 access_mask = fsp->access_mask;
3673 NTSTATUS status = NT_STATUS_OK;
3676 if (total_params < 7) {
3677 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3681 info_level = SVAL(params,0);
3683 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3685 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3686 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3690 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3692 STR_TERMINATE, &status);
3693 if (!NT_STATUS_IS_OK(status)) {
3694 reply_nterror(req, status);
3698 status = resolve_dfspath(ctx,
3700 req->flags2 & FLAGS2_DFS_PATHNAMES,
3703 if (!NT_STATUS_IS_OK(status)) {
3704 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3705 reply_botherror(req,
3706 NT_STATUS_PATH_NOT_COVERED,
3707 ERRSRV, ERRbadpath);
3709 reply_nterror(req, status);
3713 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3714 if (!NT_STATUS_IS_OK(status)) {
3715 reply_nterror(req, status);
3718 status = check_name(conn, fname);
3719 if (!NT_STATUS_IS_OK(status)) {
3720 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3721 reply_nterror(req, status);
3725 if (INFO_LEVEL_IS_UNIX(info_level)) {
3726 /* Always do lstat for UNIX calls. */
3727 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3728 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3729 reply_unixerror(req, ERRDOS, ERRbadpath);
3732 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3733 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3734 reply_unixerror(req, ERRDOS, ERRbadpath);
3738 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3739 delete_pending = get_delete_on_close_flag(fileid);
3740 if (delete_pending) {
3741 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3746 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3747 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3751 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3752 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3754 p = strrchr_m(fname,'/');
3760 mode = dos_mode(conn,fname,&sbuf);
3762 mode = FILE_ATTRIBUTE_NORMAL;
3764 nlink = sbuf.st_nlink;
3766 if (nlink && (mode&aDIR)) {
3770 if ((nlink > 0) && delete_pending) {
3774 fullpathname = fname;
3776 file_size = get_file_size(sbuf);
3778 /* Pull out any data sent here before we realloc. */
3779 switch (info_level) {
3780 case SMB_INFO_QUERY_EAS_FROM_LIST:
3782 /* Pull any EA list from the data portion. */
3785 if (total_data < 4) {
3787 req, NT_STATUS_INVALID_PARAMETER);
3790 ea_size = IVAL(pdata,0);
3792 if (total_data > 0 && ea_size != total_data) {
3793 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3794 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3796 req, NT_STATUS_INVALID_PARAMETER);
3800 if (!lp_ea_support(SNUM(conn))) {
3801 reply_doserror(req, ERRDOS,
3802 ERReasnotsupported);
3806 /* Pull out the list of names. */
3807 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3810 req, NT_STATUS_INVALID_PARAMETER);
3816 case SMB_QUERY_POSIX_LOCK:
3818 if (fsp == NULL || fsp->fh->fd == -1) {
3819 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3823 if (total_data != POSIX_LOCK_DATA_SIZE) {
3825 req, NT_STATUS_INVALID_PARAMETER);
3829 /* Copy the lock range data. */
3830 lock_data = (char *)TALLOC_MEMDUP(
3831 ctx, pdata, total_data);
3833 reply_nterror(req, NT_STATUS_NO_MEMORY);
3841 *pparams = (char *)SMB_REALLOC(*pparams,2);
3842 if (*pparams == NULL) {
3843 reply_nterror(req, NT_STATUS_NO_MEMORY);
3848 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3849 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3850 if (*ppdata == NULL ) {
3851 reply_nterror(req, NT_STATUS_NO_MEMORY);
3856 dend = dstart + data_size - 1;
3858 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3859 mtime_ts = get_mtimespec(&sbuf);
3860 atime_ts = get_atimespec(&sbuf);
3862 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3865 if (!null_timespec(fsp->pending_modtime)) {
3866 /* the pending modtime overrides the current modtime */
3867 mtime_ts = fsp->pending_modtime;
3871 /* Do we have this path open ? */
3872 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3873 fsp1 = file_find_di_first(fileid);
3874 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3875 /* the pending modtime overrides the current modtime */
3876 mtime_ts = fsp1->pending_modtime;
3878 if (fsp1 && fsp1->initial_allocation_size) {
3879 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3883 if (lp_dos_filetime_resolution(SNUM(conn))) {
3884 dos_filetime_timespec(&create_time_ts);
3885 dos_filetime_timespec(&mtime_ts);
3886 dos_filetime_timespec(&atime_ts);
3889 create_time = convert_timespec_to_time_t(create_time_ts);
3890 mtime = convert_timespec_to_time_t(mtime_ts);
3891 atime = convert_timespec_to_time_t(atime_ts);
3893 /* NT expects the name to be in an exact form of the *full*
3894 filename. See the trans2 torture test */
3895 if (ISDOT(base_name)) {
3896 dos_fname = talloc_strdup(ctx, "\\");
3898 reply_nterror(req, NT_STATUS_NO_MEMORY);
3902 dos_fname = talloc_asprintf(ctx,
3906 reply_nterror(req, NT_STATUS_NO_MEMORY);
3909 string_replace(dos_fname, '/', '\\');
3912 switch (info_level) {
3913 case SMB_INFO_STANDARD:
3914 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3916 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3917 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3918 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3919 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3920 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3921 SSVAL(pdata,l1_attrFile,mode);
3924 case SMB_INFO_QUERY_EA_SIZE:
3926 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3927 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3929 srv_put_dos_date2(pdata,0,create_time);
3930 srv_put_dos_date2(pdata,4,atime);
3931 srv_put_dos_date2(pdata,8,mtime); /* write time */
3932 SIVAL(pdata,12,(uint32)file_size);
3933 SIVAL(pdata,16,(uint32)allocation_size);
3934 SSVAL(pdata,20,mode);
3935 SIVAL(pdata,22,ea_size);
3939 case SMB_INFO_IS_NAME_VALID:
3940 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3941 if (tran_call == TRANSACT2_QFILEINFO) {
3942 /* os/2 needs this ? really ?*/
3943 reply_doserror(req, ERRDOS, ERRbadfunc);
3950 case SMB_INFO_QUERY_EAS_FROM_LIST:
3952 size_t total_ea_len = 0;
3953 struct ea_list *ea_file_list = NULL;
3955 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3957 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3958 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3960 if (!ea_list || (total_ea_len > data_size)) {
3962 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3966 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3970 case SMB_INFO_QUERY_ALL_EAS:
3972 /* We have data_size bytes to put EA's into. */
3973 size_t total_ea_len = 0;
3975 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3977 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3978 if (!ea_list || (total_ea_len > data_size)) {
3980 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3984 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3988 case SMB_FILE_BASIC_INFORMATION:
3989 case SMB_QUERY_FILE_BASIC_INFO:
3991 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3992 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3993 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3995 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3999 put_long_date_timespec(pdata,create_time_ts);
4000 put_long_date_timespec(pdata+8,atime_ts);
4001 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4002 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4003 SIVAL(pdata,32,mode);
4005 DEBUG(5,("SMB_QFBI - "));
4006 DEBUG(5,("create: %s ", ctime(&create_time)));
4007 DEBUG(5,("access: %s ", ctime(&atime)));
4008 DEBUG(5,("write: %s ", ctime(&mtime)));
4009 DEBUG(5,("change: %s ", ctime(&mtime)));
4010 DEBUG(5,("mode: %x\n", mode));
4013 case SMB_FILE_STANDARD_INFORMATION:
4014 case SMB_QUERY_FILE_STANDARD_INFO:
4016 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4018 SOFF_T(pdata,0,allocation_size);
4019 SOFF_T(pdata,8,file_size);
4020 SIVAL(pdata,16,nlink);
4021 SCVAL(pdata,20,delete_pending?1:0);
4022 SCVAL(pdata,21,(mode&aDIR)?1:0);
4023 SSVAL(pdata,22,0); /* Padding. */
4026 case SMB_FILE_EA_INFORMATION:
4027 case SMB_QUERY_FILE_EA_INFO:
4029 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4030 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4032 SIVAL(pdata,0,ea_size);
4036 /* Get the 8.3 name - used if NT SMB was negotiated. */
4037 case SMB_QUERY_FILE_ALT_NAME_INFO:
4038 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4040 char mangled_name[13];
4041 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4042 if (!name_to_8_3(base_name,mangled_name,
4043 True,conn->params)) {
4046 NT_STATUS_NO_MEMORY);
4048 len = srvstr_push(dstart, req->flags2,
4049 pdata+4, mangled_name,
4050 PTR_DIFF(dend, pdata+4),
4052 data_size = 4 + len;
4057 case SMB_QUERY_FILE_NAME_INFO:
4059 this must be *exactly* right for ACLs on mapped drives to work
4061 len = srvstr_push(dstart, req->flags2,
4063 PTR_DIFF(dend, pdata+4),
4065 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4066 data_size = 4 + len;
4070 case SMB_FILE_ALLOCATION_INFORMATION:
4071 case SMB_QUERY_FILE_ALLOCATION_INFO:
4072 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4074 SOFF_T(pdata,0,allocation_size);
4077 case SMB_FILE_END_OF_FILE_INFORMATION:
4078 case SMB_QUERY_FILE_END_OF_FILEINFO:
4079 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4081 SOFF_T(pdata,0,file_size);
4084 case SMB_QUERY_FILE_ALL_INFO:
4085 case SMB_FILE_ALL_INFORMATION:
4087 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4088 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4089 put_long_date_timespec(pdata,create_time_ts);
4090 put_long_date_timespec(pdata+8,atime_ts);
4091 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4092 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4093 SIVAL(pdata,32,mode);
4094 SIVAL(pdata,36,0); /* padding. */
4096 SOFF_T(pdata,0,allocation_size);
4097 SOFF_T(pdata,8,file_size);
4098 SIVAL(pdata,16,nlink);
4099 SCVAL(pdata,20,delete_pending);
4100 SCVAL(pdata,21,(mode&aDIR)?1:0);
4103 SIVAL(pdata,0,ea_size);
4104 pdata += 4; /* EA info */
4105 len = srvstr_push(dstart, req->flags2,
4107 PTR_DIFF(dend, pdata+4),
4111 data_size = PTR_DIFF(pdata,(*ppdata));
4114 case SMB_FILE_INTERNAL_INFORMATION:
4115 /* This should be an index number - looks like
4118 I think this causes us to fail the IFSKIT
4119 BasicFileInformationTest. -tpot */
4121 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4122 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4123 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4127 case SMB_FILE_ACCESS_INFORMATION:
4128 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4129 SIVAL(pdata,0,access_mask);
4133 case SMB_FILE_NAME_INFORMATION:
4134 /* Pathname with leading '\'. */
4137 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4138 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4139 SIVAL(pdata,0,byte_len);
4140 data_size = 4 + byte_len;
4144 case SMB_FILE_DISPOSITION_INFORMATION:
4145 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4147 SCVAL(pdata,0,delete_pending);
4150 case SMB_FILE_POSITION_INFORMATION:
4151 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4153 SOFF_T(pdata,0,pos);
4156 case SMB_FILE_MODE_INFORMATION:
4157 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4158 SIVAL(pdata,0,mode);
4162 case SMB_FILE_ALIGNMENT_INFORMATION:
4163 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4164 SIVAL(pdata,0,0); /* No alignment needed. */
4170 * NT4 server just returns "invalid query" to this - if we try to answer
4171 * it then NTws gets a BSOD! (tridge).
4172 * W2K seems to want this. JRA.
4174 case SMB_QUERY_FILE_STREAM_INFO:
4176 case SMB_FILE_STREAM_INFORMATION:
4177 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4181 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4182 SIVAL(pdata,0,0); /* ??? */
4183 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4184 SOFF_T(pdata,8,file_size);
4185 SOFF_T(pdata,16,allocation_size);
4186 data_size = 24 + byte_len;
4190 case SMB_QUERY_COMPRESSION_INFO:
4191 case SMB_FILE_COMPRESSION_INFORMATION:
4192 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4193 SOFF_T(pdata,0,file_size);
4194 SIVAL(pdata,8,0); /* ??? */
4195 SIVAL(pdata,12,0); /* ??? */
4199 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4200 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4201 put_long_date_timespec(pdata,create_time_ts);
4202 put_long_date_timespec(pdata+8,atime_ts);
4203 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4204 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4205 SOFF_T(pdata,32,allocation_size);
4206 SOFF_T(pdata,40,file_size);
4207 SIVAL(pdata,48,mode);
4208 SIVAL(pdata,52,0); /* ??? */
4212 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4213 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4214 SIVAL(pdata,0,mode);
4220 * CIFS UNIX Extensions.
4223 case SMB_QUERY_FILE_UNIX_BASIC:
4225 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4226 data_size = PTR_DIFF(pdata,(*ppdata));
4230 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4232 for (i=0; i<100; i++)
4233 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4239 case SMB_QUERY_FILE_UNIX_INFO2:
4241 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4242 data_size = PTR_DIFF(pdata,(*ppdata));
4246 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4248 for (i=0; i<100; i++)
4249 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4255 case SMB_QUERY_FILE_UNIX_LINK:
4257 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4260 reply_nterror(req, NT_STATUS_NO_MEMORY);
4264 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4266 if(!S_ISLNK(sbuf.st_mode)) {
4267 reply_unixerror(req, ERRSRV,
4272 reply_unixerror(req, ERRDOS, ERRbadlink);
4275 len = SMB_VFS_READLINK(conn,fullpathname,
4278 reply_unixerror(req, ERRDOS,
4283 len = srvstr_push(dstart, req->flags2,
4285 PTR_DIFF(dend, pdata),
4288 data_size = PTR_DIFF(pdata,(*ppdata));
4293 #if defined(HAVE_POSIX_ACLS)
4294 case SMB_QUERY_POSIX_ACL:
4296 SMB_ACL_T file_acl = NULL;
4297 SMB_ACL_T def_acl = NULL;
4298 uint16 num_file_acls = 0;
4299 uint16 num_def_acls = 0;
4301 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4302 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4304 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4307 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4308 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4312 NT_STATUS_NOT_IMPLEMENTED);
4316 if (S_ISDIR(sbuf.st_mode)) {
4317 if (fsp && fsp->is_directory) {
4318 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4320 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4322 def_acl = free_empty_sys_acl(conn, def_acl);
4325 num_file_acls = count_acl_entries(conn, file_acl);
4326 num_def_acls = count_acl_entries(conn, def_acl);
4328 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4329 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4331 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4332 SMB_POSIX_ACL_HEADER_SIZE) ));
4334 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4337 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4341 NT_STATUS_BUFFER_TOO_SMALL);
4345 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4346 SSVAL(pdata,2,num_file_acls);
4347 SSVAL(pdata,4,num_def_acls);
4348 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4350 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4353 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4356 req, NT_STATUS_INTERNAL_ERROR);
4359 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4361 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4364 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4368 NT_STATUS_INTERNAL_ERROR);
4373 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4376 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4378 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4384 case SMB_QUERY_POSIX_LOCK:
4386 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4388 SMB_BIG_UINT offset;
4390 enum brl_type lock_type;
4392 if (total_data != POSIX_LOCK_DATA_SIZE) {
4394 req, NT_STATUS_INVALID_PARAMETER);
4398 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4399 case POSIX_LOCK_TYPE_READ:
4400 lock_type = READ_LOCK;
4402 case POSIX_LOCK_TYPE_WRITE:
4403 lock_type = WRITE_LOCK;
4405 case POSIX_LOCK_TYPE_UNLOCK:
4407 /* There's no point in asking for an unlock... */
4410 NT_STATUS_INVALID_PARAMETER);
4414 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4415 #if defined(HAVE_LONGLONG)
4416 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4417 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4418 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4419 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4420 #else /* HAVE_LONGLONG */
4421 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4422 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4423 #endif /* HAVE_LONGLONG */
4425 status = query_lock(fsp,
4432 if (ERROR_WAS_LOCK_DENIED(status)) {
4433 /* Here we need to report who has it locked... */
4434 data_size = POSIX_LOCK_DATA_SIZE;
4436 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4437 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4438 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4439 #if defined(HAVE_LONGLONG)
4440 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4441 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4442 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4443 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4444 #else /* HAVE_LONGLONG */
4445 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4446 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4447 #endif /* HAVE_LONGLONG */
4449 } else if (NT_STATUS_IS_OK(status)) {
4450 /* For success we just return a copy of what we sent
4451 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4452 data_size = POSIX_LOCK_DATA_SIZE;
4453 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4454 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4456 reply_nterror(req, status);
4463 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4467 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4473 /****************************************************************************
4474 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4476 ****************************************************************************/
4478 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4479 connection_struct *conn,
4480 const char *oldname_in,
4481 const char *newname_in)
4483 SMB_STRUCT_STAT sbuf1, sbuf2;
4484 char *last_component_oldname = NULL;
4485 char *last_component_newname = NULL;
4486 char *oldname = NULL;
4487 char *newname = NULL;
4488 NTSTATUS status = NT_STATUS_OK;
4493 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4494 &last_component_oldname, &sbuf1);
4495 if (!NT_STATUS_IS_OK(status)) {
4499 status = check_name(conn, oldname);
4500 if (!NT_STATUS_IS_OK(status)) {
4504 /* source must already exist. */
4505 if (!VALID_STAT(sbuf1)) {
4506 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4509 status = unix_convert(ctx, conn, newname_in, False, &newname,
4510 &last_component_newname, &sbuf2);
4511 if (!NT_STATUS_IS_OK(status)) {
4515 status = check_name(conn, newname);
4516 if (!NT_STATUS_IS_OK(status)) {
4520 /* Disallow if newname already exists. */
4521 if (VALID_STAT(sbuf2)) {
4522 return NT_STATUS_OBJECT_NAME_COLLISION;
4525 /* No links from a directory. */
4526 if (S_ISDIR(sbuf1.st_mode)) {
4527 return NT_STATUS_FILE_IS_A_DIRECTORY;
4530 /* Ensure this is within the share. */
4531 status = check_reduced_name(conn, oldname);
4532 if (!NT_STATUS_IS_OK(status)) {
4536 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4538 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4539 status = map_nt_error_from_unix(errno);
4540 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4541 nt_errstr(status), newname, oldname));
4547 /****************************************************************************
4548 Deal with setting the time from any of the setfilepathinfo functions.
4549 ****************************************************************************/
4551 static NTSTATUS smb_set_file_time(connection_struct *conn,
4554 const SMB_STRUCT_STAT *psbuf,
4555 struct timespec ts[2],
4556 bool setting_write_time)
4559 FILE_NOTIFY_CHANGE_LAST_ACCESS
4560 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4562 if (!VALID_STAT(*psbuf)) {
4563 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4566 /* get some defaults (no modifications) if any info is zero or -1. */
4567 if (null_timespec(ts[0])) {
4568 ts[0] = get_atimespec(psbuf);
4569 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4572 if (null_timespec(ts[1])) {
4573 ts[1] = get_mtimespec(psbuf);
4574 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4577 if (!setting_write_time) {
4578 /* ts[1] comes from change time, not write time. */
4579 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4582 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4583 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4586 * Try and set the times of this file if
4587 * they are different from the current values.
4591 struct timespec mts = get_mtimespec(psbuf);
4592 struct timespec ats = get_atimespec(psbuf);
4593 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4594 return NT_STATUS_OK;
4600 * This was a setfileinfo on an open file.
4601 * NT does this a lot. We also need to
4602 * set the time here, as it can be read by
4603 * FindFirst/FindNext and with the patch for bug #2045
4604 * in smbd/fileio.c it ensures that this timestamp is
4605 * kept sticky even after a write. We save the request
4606 * away and will set it on file close and after a write. JRA.
4609 if (!null_timespec(ts[1])) {
4610 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4611 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4612 fsp_set_pending_modtime(fsp, ts[1]);
4616 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4618 if(file_ntimes(conn, fname, ts)!=0) {
4619 return map_nt_error_from_unix(errno);
4621 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4623 return NT_STATUS_OK;
4626 /****************************************************************************
4627 Deal with setting the dosmode from any of the setfilepathinfo functions.
4628 ****************************************************************************/
4630 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4632 SMB_STRUCT_STAT *psbuf,
4635 if (!VALID_STAT(*psbuf)) {
4636 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4640 if (S_ISDIR(psbuf->st_mode)) {
4647 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4649 /* check the mode isn't different, before changing it */
4650 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4652 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4653 fname, (unsigned int)dosmode ));
4655 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4656 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4657 fname, strerror(errno)));
4658 return map_nt_error_from_unix(errno);
4661 return NT_STATUS_OK;
4664 /****************************************************************************
4665 Deal with setting the size from any of the setfilepathinfo functions.
4666 ****************************************************************************/
4668 static NTSTATUS smb_set_file_size(connection_struct *conn,
4669 struct smb_request *req,
4672 SMB_STRUCT_STAT *psbuf,
4675 NTSTATUS status = NT_STATUS_OK;
4676 files_struct *new_fsp = NULL;
4678 if (!VALID_STAT(*psbuf)) {
4679 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4682 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4684 if (size == get_file_size(*psbuf)) {
4685 return NT_STATUS_OK;
4688 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4689 fname, (double)size ));
4691 if (fsp && fsp->fh->fd != -1) {
4692 /* Handle based call. */
4693 if (vfs_set_filelen(fsp, size) == -1) {
4694 return map_nt_error_from_unix(errno);
4696 return NT_STATUS_OK;
4699 status = open_file_ntcreate(conn, req, fname, psbuf,
4701 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4704 FILE_ATTRIBUTE_NORMAL,
4705 FORCE_OPLOCK_BREAK_TO_NONE,
4708 if (!NT_STATUS_IS_OK(status)) {
4709 /* NB. We check for open_was_deferred in the caller. */
4713 if (vfs_set_filelen(new_fsp, size) == -1) {
4714 status = map_nt_error_from_unix(errno);
4715 close_file(new_fsp,NORMAL_CLOSE);
4719 close_file(new_fsp,NORMAL_CLOSE);
4720 return NT_STATUS_OK;
4723 /****************************************************************************
4724 Deal with SMB_INFO_SET_EA.
4725 ****************************************************************************/
4727 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4733 struct ea_list *ea_list = NULL;
4734 TALLOC_CTX *ctx = NULL;
4735 NTSTATUS status = NT_STATUS_OK;
4737 if (total_data < 10) {
4739 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4740 length. They seem to have no effect. Bug #3212. JRA */
4742 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4743 /* We're done. We only get EA info in this call. */
4744 return NT_STATUS_OK;
4747 return NT_STATUS_INVALID_PARAMETER;
4750 if (IVAL(pdata,0) > total_data) {
4751 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4752 IVAL(pdata,0), (unsigned int)total_data));
4753 return NT_STATUS_INVALID_PARAMETER;
4757 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4759 return NT_STATUS_INVALID_PARAMETER;
4761 status = set_ea(conn, fsp, fname, ea_list);
4766 /****************************************************************************
4767 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4768 ****************************************************************************/
4770 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4775 SMB_STRUCT_STAT *psbuf)
4777 NTSTATUS status = NT_STATUS_OK;
4778 bool delete_on_close;
4781 if (total_data < 1) {
4782 return NT_STATUS_INVALID_PARAMETER;
4786 return NT_STATUS_INVALID_HANDLE;
4789 delete_on_close = (CVAL(pdata,0) ? True : False);
4790 dosmode = dos_mode(conn, fname, psbuf);
4792 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4793 "delete_on_close = %u\n",
4795 (unsigned int)dosmode,
4796 (unsigned int)delete_on_close ));
4798 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4800 if (!NT_STATUS_IS_OK(status)) {
4804 /* The set is across all open files on this dev/inode pair. */
4805 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4806 return NT_STATUS_ACCESS_DENIED;
4808 return NT_STATUS_OK;
4811 /****************************************************************************
4812 Deal with SMB_FILE_POSITION_INFORMATION.
4813 ****************************************************************************/
4815 static NTSTATUS smb_file_position_information(connection_struct *conn,
4820 SMB_BIG_UINT position_information;
4822 if (total_data < 8) {
4823 return NT_STATUS_INVALID_PARAMETER;
4827 /* Ignore on pathname based set. */
4828 return NT_STATUS_OK;
4831 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4832 #ifdef LARGE_SMB_OFF_T
4833 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4834 #else /* LARGE_SMB_OFF_T */
4835 if (IVAL(pdata,4) != 0) {
4836 /* more than 32 bits? */
4837 return NT_STATUS_INVALID_PARAMETER;
4839 #endif /* LARGE_SMB_OFF_T */
4841 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4842 fsp->fsp_name, (double)position_information ));
4843 fsp->fh->position_information = position_information;
4844 return NT_STATUS_OK;
4847 /****************************************************************************
4848 Deal with SMB_FILE_MODE_INFORMATION.
4849 ****************************************************************************/
4851 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4857 if (total_data < 4) {
4858 return NT_STATUS_INVALID_PARAMETER;
4860 mode = IVAL(pdata,0);
4861 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4862 return NT_STATUS_INVALID_PARAMETER;
4864 return NT_STATUS_OK;
4867 /****************************************************************************
4868 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4869 ****************************************************************************/
4871 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4872 struct smb_request *req,
4877 char *link_target = NULL;
4878 const char *newname = fname;
4879 NTSTATUS status = NT_STATUS_OK;
4880 TALLOC_CTX *ctx = talloc_tos();
4882 /* Set a symbolic link. */
4883 /* Don't allow this if follow links is false. */
4885 if (total_data == 0) {
4886 return NT_STATUS_INVALID_PARAMETER;
4889 if (!lp_symlinks(SNUM(conn))) {
4890 return NT_STATUS_ACCESS_DENIED;
4893 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
4894 total_data, STR_TERMINATE);
4897 return NT_STATUS_INVALID_PARAMETER;
4900 /* !widelinks forces the target path to be within the share. */
4901 /* This means we can interpret the target as a pathname. */
4902 if (!lp_widelinks(SNUM(conn))) {
4903 char *rel_name = NULL;
4904 char *last_dirp = NULL;
4906 if (*link_target == '/') {
4907 /* No absolute paths allowed. */
4908 return NT_STATUS_ACCESS_DENIED;
4910 rel_name = talloc_strdup(ctx,newname);
4912 return NT_STATUS_NO_MEMORY;
4914 last_dirp = strrchr_m(rel_name, '/');
4916 last_dirp[1] = '\0';
4918 rel_name = talloc_strdup(ctx,"./");
4920 return NT_STATUS_NO_MEMORY;
4923 rel_name = talloc_asprintf_append(rel_name,
4927 return NT_STATUS_NO_MEMORY;
4930 status = check_name(conn, rel_name);
4931 if (!NT_STATUS_IS_OK(status)) {
4936 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4937 newname, link_target ));
4939 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4940 return map_nt_error_from_unix(errno);
4943 return NT_STATUS_OK;
4946 /****************************************************************************
4947 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4948 ****************************************************************************/
4950 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4951 struct smb_request *req,
4952 const char *pdata, int total_data,
4955 char *oldname = NULL;
4956 TALLOC_CTX *ctx = talloc_tos();
4957 NTSTATUS status = NT_STATUS_OK;
4959 /* Set a hard link. */
4960 if (total_data == 0) {
4961 return NT_STATUS_INVALID_PARAMETER;
4964 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
4965 total_data, STR_TERMINATE, &status);
4966 if (!NT_STATUS_IS_OK(status)) {
4970 status = resolve_dfspath(ctx, conn,
4971 req->flags2 & FLAGS2_DFS_PATHNAMES,
4974 if (!NT_STATUS_IS_OK(status)) {
4978 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4981 return hardlink_internals(ctx, conn, oldname, fname);
4984 /****************************************************************************
4985 Deal with SMB_FILE_RENAME_INFORMATION.
4986 ****************************************************************************/
4988 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4989 struct smb_request *req,
4998 char *newname = NULL;
4999 char *base_name = NULL;
5000 bool dest_has_wcard = False;
5001 NTSTATUS status = NT_STATUS_OK;
5003 TALLOC_CTX *ctx = talloc_tos();
5005 if (total_data < 13) {
5006 return NT_STATUS_INVALID_PARAMETER;
5009 overwrite = (CVAL(pdata,0) ? True : False);
5010 root_fid = IVAL(pdata,4);
5011 len = IVAL(pdata,8);
5013 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5014 return NT_STATUS_INVALID_PARAMETER;
5017 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5020 if (!NT_STATUS_IS_OK(status)) {
5024 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5027 status = resolve_dfspath_wcard(ctx, conn,
5028 req->flags2 & FLAGS2_DFS_PATHNAMES,
5032 if (!NT_STATUS_IS_OK(status)) {
5036 /* Check the new name has no '/' characters. */
5037 if (strchr_m(newname, '/')) {
5038 return NT_STATUS_NOT_SUPPORTED;
5041 /* Create the base directory. */
5042 base_name = talloc_strdup(ctx, fname);
5044 return NT_STATUS_NO_MEMORY;
5046 p = strrchr_m(base_name, '/');
5050 base_name = talloc_strdup(ctx, "./");
5052 return NT_STATUS_NO_MEMORY;
5055 /* Append the new name. */
5056 base_name = talloc_asprintf_append(base_name,
5060 return NT_STATUS_NO_MEMORY;
5064 SMB_STRUCT_STAT sbuf;
5065 char *newname_last_component = NULL;
5069 status = unix_convert(ctx, conn, newname, False,
5071 &newname_last_component,
5074 /* If an error we expect this to be
5075 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5077 if (!NT_STATUS_IS_OK(status)
5078 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5083 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5084 fsp->fnum, fsp->fsp_name, base_name ));
5085 status = rename_internals_fsp(conn, fsp, base_name,
5086 newname_last_component, 0,
5089 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5090 fname, base_name ));
5091 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5092 overwrite, False, dest_has_wcard);
5098 /****************************************************************************
5099 Deal with SMB_SET_POSIX_ACL.
5100 ****************************************************************************/
5102 #if defined(HAVE_POSIX_ACLS)
5103 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5108 SMB_STRUCT_STAT *psbuf)
5110 uint16 posix_acl_version;
5111 uint16 num_file_acls;
5112 uint16 num_def_acls;
5113 bool valid_file_acls = True;
5114 bool valid_def_acls = True;
5116 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5117 return NT_STATUS_INVALID_PARAMETER;
5119 posix_acl_version = SVAL(pdata,0);
5120 num_file_acls = SVAL(pdata,2);
5121 num_def_acls = SVAL(pdata,4);
5123 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5124 valid_file_acls = False;
5128 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5129 valid_def_acls = False;
5133 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5134 return NT_STATUS_INVALID_PARAMETER;
5137 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5138 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5139 return NT_STATUS_INVALID_PARAMETER;
5142 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5143 fname ? fname : fsp->fsp_name,
5144 (unsigned int)num_file_acls,
5145 (unsigned int)num_def_acls));
5147 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5148 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5149 return map_nt_error_from_unix(errno);
5152 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5153 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5154 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5155 return map_nt_error_from_unix(errno);
5157 return NT_STATUS_OK;
5161 /****************************************************************************
5162 Deal with SMB_SET_POSIX_LOCK.
5163 ****************************************************************************/
5165 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5166 const struct smb_request *req,
5172 SMB_BIG_UINT offset;
5174 bool blocking_lock = False;
5175 enum brl_type lock_type;
5177 NTSTATUS status = NT_STATUS_OK;
5179 if (fsp == NULL || fsp->fh->fd == -1) {
5180 return NT_STATUS_INVALID_HANDLE;
5183 if (total_data != POSIX_LOCK_DATA_SIZE) {
5184 return NT_STATUS_INVALID_PARAMETER;
5187 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5188 case POSIX_LOCK_TYPE_READ:
5189 lock_type = READ_LOCK;
5191 case POSIX_LOCK_TYPE_WRITE:
5192 /* Return the right POSIX-mappable error code for files opened read-only. */
5193 if (!fsp->can_write) {
5194 return NT_STATUS_INVALID_HANDLE;
5196 lock_type = WRITE_LOCK;
5198 case POSIX_LOCK_TYPE_UNLOCK:
5199 lock_type = UNLOCK_LOCK;
5202 return NT_STATUS_INVALID_PARAMETER;
5205 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5206 blocking_lock = False;
5207 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5208 blocking_lock = True;
5210 return NT_STATUS_INVALID_PARAMETER;
5213 if (!lp_blocking_locks(SNUM(conn))) {
5214 blocking_lock = False;
5217 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5218 #if defined(HAVE_LONGLONG)
5219 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5220 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5221 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5222 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5223 #else /* HAVE_LONGLONG */
5224 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5225 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5226 #endif /* HAVE_LONGLONG */
5228 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5229 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5231 (unsigned int)lock_type,
5232 (unsigned int)lock_pid,
5236 if (lock_type == UNLOCK_LOCK) {
5237 status = do_unlock(smbd_messaging_context(),
5244 uint32 block_smbpid;
5246 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5257 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5259 * A blocking lock was requested. Package up
5260 * this smb into a queued request and push it
5261 * onto the blocking lock queue.
5263 if(push_blocking_lock_request(br_lck,
5266 -1, /* infinite timeout. */
5274 TALLOC_FREE(br_lck);
5278 TALLOC_FREE(br_lck);
5284 /****************************************************************************
5285 Deal with SMB_INFO_STANDARD.
5286 ****************************************************************************/
5288 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5293 const SMB_STRUCT_STAT *psbuf)
5295 struct timespec ts[2];
5297 if (total_data < 12) {
5298 return NT_STATUS_INVALID_PARAMETER;
5302 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5304 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5306 DEBUG(10,("smb_set_info_standard: file %s\n",
5307 fname ? fname : fsp->fsp_name ));
5309 return smb_set_file_time(conn,
5317 /****************************************************************************
5318 Deal with SMB_SET_FILE_BASIC_INFO.
5319 ****************************************************************************/
5321 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5326 SMB_STRUCT_STAT *psbuf)
5328 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5329 struct timespec write_time;
5330 struct timespec changed_time;
5332 struct timespec ts[2];
5333 NTSTATUS status = NT_STATUS_OK;
5334 bool setting_write_time = true;
5336 if (total_data < 36) {
5337 return NT_STATUS_INVALID_PARAMETER;
5340 /* Set the attributes */
5341 dosmode = IVAL(pdata,32);
5342 status = smb_set_file_dosmode(conn,
5346 if (!NT_STATUS_IS_OK(status)) {
5350 /* Ignore create time at offset pdata. */
5353 ts[0] = interpret_long_date(pdata+8);
5355 write_time = interpret_long_date(pdata+16);
5356 changed_time = interpret_long_date(pdata+24);
5359 ts[1] = timespec_min(&write_time, &changed_time);
5361 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5365 /* Prefer a defined time to an undefined one. */
5366 if (null_timespec(ts[1])) {
5367 if (null_timespec(write_time)) {
5368 ts[1] = changed_time;
5369 setting_write_time = false;
5375 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5376 fname ? fname : fsp->fsp_name ));
5378 return smb_set_file_time(conn,
5383 setting_write_time);
5386 /****************************************************************************
5387 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5388 ****************************************************************************/
5390 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5391 struct smb_request *req,
5396 SMB_STRUCT_STAT *psbuf)
5398 SMB_BIG_UINT allocation_size = 0;
5399 NTSTATUS status = NT_STATUS_OK;
5400 files_struct *new_fsp = NULL;
5402 if (!VALID_STAT(*psbuf)) {
5403 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5406 if (total_data < 8) {
5407 return NT_STATUS_INVALID_PARAMETER;
5410 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5411 #ifdef LARGE_SMB_OFF_T
5412 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5413 #else /* LARGE_SMB_OFF_T */
5414 if (IVAL(pdata,4) != 0) {
5415 /* more than 32 bits? */
5416 return NT_STATUS_INVALID_PARAMETER;
5418 #endif /* LARGE_SMB_OFF_T */
5420 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5421 fname, (double)allocation_size ));
5423 if (allocation_size) {
5424 allocation_size = smb_roundup(conn, allocation_size);
5427 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5428 fname, (double)allocation_size ));
5430 if (fsp && fsp->fh->fd != -1) {
5431 /* Open file handle. */
5432 /* Only change if needed. */
5433 if (allocation_size != get_file_size(*psbuf)) {
5434 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5435 return map_nt_error_from_unix(errno);
5438 /* But always update the time. */
5439 if (null_timespec(fsp->pending_modtime)) {
5441 * This is equivalent to a write. Ensure it's seen immediately
5442 * if there are no pending writes.
5444 set_filetime(fsp->conn, fsp->fsp_name,
5445 timespec_current());
5447 return NT_STATUS_OK;
5450 /* Pathname or stat or directory file. */
5452 status = open_file_ntcreate(conn, req, fname, psbuf,
5454 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5457 FILE_ATTRIBUTE_NORMAL,
5458 FORCE_OPLOCK_BREAK_TO_NONE,
5461 if (!NT_STATUS_IS_OK(status)) {
5462 /* NB. We check for open_was_deferred in the caller. */
5466 /* Only change if needed. */
5467 if (allocation_size != get_file_size(*psbuf)) {
5468 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5469 status = map_nt_error_from_unix(errno);
5470 close_file(new_fsp,NORMAL_CLOSE);
5475 /* Changing the allocation size should set the last mod time. */
5476 /* Don't need to call set_filetime as this will be flushed on
5479 fsp_set_pending_modtime(new_fsp, timespec_current());
5481 close_file(new_fsp,NORMAL_CLOSE);
5482 return NT_STATUS_OK;
5485 /****************************************************************************
5486 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5487 ****************************************************************************/
5489 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5490 struct smb_request *req,
5495 SMB_STRUCT_STAT *psbuf)
5499 if (total_data < 8) {
5500 return NT_STATUS_INVALID_PARAMETER;
5503 size = IVAL(pdata,0);
5504 #ifdef LARGE_SMB_OFF_T
5505 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5506 #else /* LARGE_SMB_OFF_T */
5507 if (IVAL(pdata,4) != 0) {
5508 /* more than 32 bits? */
5509 return NT_STATUS_INVALID_PARAMETER;
5511 #endif /* LARGE_SMB_OFF_T */
5512 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5513 "file %s to %.0f\n", fname, (double)size ));
5515 return smb_set_file_size(conn, req,
5522 /****************************************************************************
5523 Allow a UNIX info mknod.
5524 ****************************************************************************/
5526 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5530 SMB_STRUCT_STAT *psbuf)
5532 uint32 file_type = IVAL(pdata,56);
5533 #if defined(HAVE_MAKEDEV)
5534 uint32 dev_major = IVAL(pdata,60);
5535 uint32 dev_minor = IVAL(pdata,68);
5537 SMB_DEV_T dev = (SMB_DEV_T)0;
5538 uint32 raw_unixmode = IVAL(pdata,84);
5542 if (total_data < 100) {
5543 return NT_STATUS_INVALID_PARAMETER;
5546 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5547 if (!NT_STATUS_IS_OK(status)) {
5551 #if defined(HAVE_MAKEDEV)
5552 dev = makedev(dev_major, dev_minor);
5555 switch (file_type) {
5556 #if defined(S_IFIFO)
5557 case UNIX_TYPE_FIFO:
5558 unixmode |= S_IFIFO;
5561 #if defined(S_IFSOCK)
5562 case UNIX_TYPE_SOCKET:
5563 unixmode |= S_IFSOCK;
5566 #if defined(S_IFCHR)
5567 case UNIX_TYPE_CHARDEV:
5568 unixmode |= S_IFCHR;
5571 #if defined(S_IFBLK)
5572 case UNIX_TYPE_BLKDEV:
5573 unixmode |= S_IFBLK;
5577 return NT_STATUS_INVALID_PARAMETER;
5580 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5581 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5583 /* Ok - do the mknod. */
5584 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5585 return map_nt_error_from_unix(errno);
5588 /* If any of the other "set" calls fail we
5589 * don't want to end up with a half-constructed mknod.
5592 if (lp_inherit_perms(SNUM(conn))) {
5594 conn, parent_dirname(fname),
5598 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5599 status = map_nt_error_from_unix(errno);
5600 SMB_VFS_UNLINK(conn,fname);
5603 return NT_STATUS_OK;
5606 /****************************************************************************
5607 Deal with SMB_SET_FILE_UNIX_BASIC.
5608 ****************************************************************************/
5610 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5611 struct smb_request *req,
5616 SMB_STRUCT_STAT *psbuf)
5618 struct timespec ts[2];
5619 uint32 raw_unixmode;
5622 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5623 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5624 NTSTATUS status = NT_STATUS_OK;
5625 bool delete_on_fail = False;
5626 enum perm_type ptype;
5628 if (total_data < 100) {
5629 return NT_STATUS_INVALID_PARAMETER;
5632 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5633 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5634 size=IVAL(pdata,0); /* first 8 Bytes are size */
5635 #ifdef LARGE_SMB_OFF_T
5636 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5637 #else /* LARGE_SMB_OFF_T */
5638 if (IVAL(pdata,4) != 0) {
5639 /* more than 32 bits? */
5640 return NT_STATUS_INVALID_PARAMETER;
5642 #endif /* LARGE_SMB_OFF_T */
5645 ts[0] = interpret_long_date(pdata+24); /* access_time */
5646 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5647 set_owner = (uid_t)IVAL(pdata,40);
5648 set_grp = (gid_t)IVAL(pdata,48);
5649 raw_unixmode = IVAL(pdata,84);
5651 if (VALID_STAT(*psbuf)) {
5652 if (S_ISDIR(psbuf->st_mode)) {
5653 ptype = PERM_EXISTING_DIR;
5655 ptype = PERM_EXISTING_FILE;
5658 ptype = PERM_NEW_FILE;
5661 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5662 if (!NT_STATUS_IS_OK(status)) {
5666 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5667 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5668 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5670 if (!VALID_STAT(*psbuf)) {
5672 * The only valid use of this is to create character and block
5673 * devices, and named pipes. This is deprecated (IMHO) and
5674 * a new info level should be used for mknod. JRA.
5677 status = smb_unix_mknod(conn,
5682 if (!NT_STATUS_IS_OK(status)) {
5686 /* Ensure we don't try and change anything else. */
5687 raw_unixmode = SMB_MODE_NO_CHANGE;
5688 size = get_file_size(*psbuf);
5689 ts[0] = get_atimespec(psbuf);
5690 ts[1] = get_mtimespec(psbuf);
5692 * We continue here as we might want to change the
5695 delete_on_fail = True;
5699 /* Horrible backwards compatibility hack as an old server bug
5700 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5704 size = get_file_size(*psbuf);
5709 * Deal with the UNIX specific mode set.
5712 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5713 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5714 (unsigned int)unixmode, fname ));
5715 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5716 return map_nt_error_from_unix(errno);
5721 * Deal with the UNIX specific uid set.
5724 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5727 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5728 (unsigned int)set_owner, fname ));
5730 if (S_ISLNK(psbuf->st_mode)) {
5731 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5733 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5737 status = map_nt_error_from_unix(errno);
5738 if (delete_on_fail) {
5739 SMB_VFS_UNLINK(conn,fname);
5746 * Deal with the UNIX specific gid set.
5749 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5750 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5751 (unsigned int)set_owner, fname ));
5752 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5753 status = map_nt_error_from_unix(errno);
5754 if (delete_on_fail) {
5755 SMB_VFS_UNLINK(conn,fname);
5761 /* Deal with any size changes. */
5763 status = smb_set_file_size(conn, req,
5768 if (!NT_STATUS_IS_OK(status)) {
5772 /* Deal with any time changes. */
5774 return smb_set_file_time(conn,
5782 /****************************************************************************
5783 Deal with SMB_SET_FILE_UNIX_INFO2.
5784 ****************************************************************************/
5786 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5787 struct smb_request *req,
5792 SMB_STRUCT_STAT *psbuf)
5798 if (total_data < 116) {
5799 return NT_STATUS_INVALID_PARAMETER;
5802 /* Start by setting all the fields that are common between UNIX_BASIC
5805 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5807 if (!NT_STATUS_IS_OK(status)) {
5811 smb_fflags = IVAL(pdata, 108);
5812 smb_fmask = IVAL(pdata, 112);
5814 /* NB: We should only attempt to alter the file flags if the client
5815 * sends a non-zero mask.
5817 if (smb_fmask != 0) {
5818 int stat_fflags = 0;
5820 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5822 /* Client asked to alter a flag we don't understand. */
5823 return NT_STATUS_INVALID_PARAMETER;
5826 if (fsp && fsp->fh->fd != -1) {
5827 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5828 return NT_STATUS_NOT_SUPPORTED;
5830 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5831 return map_nt_error_from_unix(errno);
5836 /* XXX: need to add support for changing the create_time here. You
5837 * can do this for paths on Darwin with setattrlist(2). The right way
5838 * to hook this up is probably by extending the VFS utimes interface.
5841 return NT_STATUS_OK;
5844 /****************************************************************************
5845 Create a directory with POSIX semantics.
5846 ****************************************************************************/
5848 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5849 struct smb_request *req,
5853 SMB_STRUCT_STAT *psbuf,
5854 int *pdata_return_size)
5856 NTSTATUS status = NT_STATUS_OK;
5857 uint32 raw_unixmode = 0;
5858 uint32 mod_unixmode = 0;
5859 mode_t unixmode = (mode_t)0;
5860 files_struct *fsp = NULL;
5861 uint16 info_level_return = 0;
5863 char *pdata = *ppdata;
5865 if (total_data < 18) {
5866 return NT_STATUS_INVALID_PARAMETER;
5869 raw_unixmode = IVAL(pdata,8);
5870 /* Next 4 bytes are not yet defined. */
5872 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5873 if (!NT_STATUS_IS_OK(status)) {
5877 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5879 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5880 fname, (unsigned int)unixmode ));
5882 status = open_directory(conn, req,
5885 FILE_READ_ATTRIBUTES, /* Just a stat open */
5886 FILE_SHARE_NONE, /* Ignored for stat opens */
5893 if (NT_STATUS_IS_OK(status)) {
5894 close_file(fsp, NORMAL_CLOSE);
5897 info_level_return = SVAL(pdata,16);
5899 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5900 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5901 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5902 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5904 *pdata_return_size = 12;
5907 /* Realloc the data size */
5908 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5909 if (*ppdata == NULL) {
5910 *pdata_return_size = 0;
5911 return NT_STATUS_NO_MEMORY;
5915 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5916 SSVAL(pdata,2,0); /* No fnum. */
5917 SIVAL(pdata,4,info); /* Was directory created. */
5919 switch (info_level_return) {
5920 case SMB_QUERY_FILE_UNIX_BASIC:
5921 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5922 SSVAL(pdata,10,0); /* Padding. */
5923 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5925 case SMB_QUERY_FILE_UNIX_INFO2:
5926 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5927 SSVAL(pdata,10,0); /* Padding. */
5928 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5931 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5932 SSVAL(pdata,10,0); /* Padding. */
5939 /****************************************************************************
5940 Open/Create a file with POSIX semantics.
5941 ****************************************************************************/
5943 static NTSTATUS smb_posix_open(connection_struct *conn,
5944 struct smb_request *req,
5948 SMB_STRUCT_STAT *psbuf,
5949 int *pdata_return_size)
5951 bool extended_oplock_granted = False;
5952 char *pdata = *ppdata;
5954 uint32 wire_open_mode = 0;
5955 uint32 raw_unixmode = 0;
5956 uint32 mod_unixmode = 0;
5957 uint32 create_disp = 0;
5958 uint32 access_mask = 0;
5959 uint32 create_options = 0;
5960 NTSTATUS status = NT_STATUS_OK;
5961 mode_t unixmode = (mode_t)0;
5962 files_struct *fsp = NULL;
5963 int oplock_request = 0;
5965 uint16 info_level_return = 0;
5967 if (total_data < 18) {
5968 return NT_STATUS_INVALID_PARAMETER;
5971 flags = IVAL(pdata,0);
5972 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5973 if (oplock_request) {
5974 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5977 wire_open_mode = IVAL(pdata,4);
5979 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5980 return smb_posix_mkdir(conn, req,
5988 switch (wire_open_mode & SMB_ACCMODE) {
5990 access_mask = FILE_READ_DATA;
5993 access_mask = FILE_WRITE_DATA;
5996 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5999 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6000 (unsigned int)wire_open_mode ));
6001 return NT_STATUS_INVALID_PARAMETER;
6004 wire_open_mode &= ~SMB_ACCMODE;
6006 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6007 create_disp = FILE_CREATE;
6008 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6009 create_disp = FILE_OVERWRITE_IF;
6010 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6011 create_disp = FILE_OPEN_IF;
6013 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6014 (unsigned int)wire_open_mode ));
6015 return NT_STATUS_INVALID_PARAMETER;
6018 raw_unixmode = IVAL(pdata,8);
6019 /* Next 4 bytes are not yet defined. */
6021 status = unix_perms_from_wire(conn,
6024 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6027 if (!NT_STATUS_IS_OK(status)) {
6031 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6033 if (wire_open_mode & SMB_O_SYNC) {
6034 create_options |= FILE_WRITE_THROUGH;
6036 if (wire_open_mode & SMB_O_APPEND) {
6037 access_mask |= FILE_APPEND_DATA;
6039 if (wire_open_mode & SMB_O_DIRECT) {
6040 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6043 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6045 (unsigned int)wire_open_mode,
6046 (unsigned int)unixmode ));
6048 status = open_file_ntcreate(conn, req,
6052 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6054 0, /* no create options yet. */
6060 if (!NT_STATUS_IS_OK(status)) {
6064 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6065 extended_oplock_granted = True;
6068 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6069 extended_oplock_granted = True;
6072 info_level_return = SVAL(pdata,16);
6074 /* Allocate the correct return size. */
6076 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6077 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6078 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6079 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6081 *pdata_return_size = 12;
6084 /* Realloc the data size */
6085 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6086 if (*ppdata == NULL) {
6087 close_file(fsp,ERROR_CLOSE);
6088 *pdata_return_size = 0;
6089 return NT_STATUS_NO_MEMORY;
6093 if (extended_oplock_granted) {
6094 if (flags & REQUEST_BATCH_OPLOCK) {
6095 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6097 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6099 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6100 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6102 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6105 SSVAL(pdata,2,fsp->fnum);
6106 SIVAL(pdata,4,info); /* Was file created etc. */
6108 switch (info_level_return) {
6109 case SMB_QUERY_FILE_UNIX_BASIC:
6110 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6111 SSVAL(pdata,10,0); /* padding. */
6112 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6114 case SMB_QUERY_FILE_UNIX_INFO2:
6115 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6116 SSVAL(pdata,10,0); /* padding. */
6117 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6120 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6121 SSVAL(pdata,10,0); /* padding. */
6124 return NT_STATUS_OK;
6127 /****************************************************************************
6128 Delete a file with POSIX semantics.
6129 ****************************************************************************/
6131 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6132 struct smb_request *req,
6136 SMB_STRUCT_STAT *psbuf)
6138 NTSTATUS status = NT_STATUS_OK;
6139 files_struct *fsp = NULL;
6144 struct share_mode_lock *lck = NULL;
6146 if (total_data < 2) {
6147 return NT_STATUS_INVALID_PARAMETER;
6150 flags = SVAL(pdata,0);
6152 if (!VALID_STAT(*psbuf)) {
6153 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6156 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6157 !VALID_STAT_OF_DIR(*psbuf)) {
6158 return NT_STATUS_NOT_A_DIRECTORY;
6161 DEBUG(10,("smb_posix_unlink: %s %s\n",
6162 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6165 if (VALID_STAT_OF_DIR(*psbuf)) {
6166 status = open_directory(conn, req,
6170 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6173 FILE_FLAG_POSIX_SEMANTICS|0777,
6178 status = open_file_ntcreate(conn, req,
6182 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6185 FILE_FLAG_POSIX_SEMANTICS|0777,
6186 0, /* No oplock, but break existing ones. */
6191 if (!NT_STATUS_IS_OK(status)) {
6196 * Don't lie to client. If we can't really delete due to
6197 * non-POSIX opens return SHARING_VIOLATION.
6200 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL);
6202 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6203 "lock for file %s\n", fsp->fsp_name));
6204 close_file(fsp, NORMAL_CLOSE);
6205 return NT_STATUS_INVALID_PARAMETER;
6209 * See if others still have the file open. If this is the case, then
6210 * don't delete. If all opens are POSIX delete we can set the delete
6211 * on close disposition.
6213 for (i=0; i<lck->num_share_modes; i++) {
6214 struct share_mode_entry *e = &lck->share_modes[i];
6215 if (is_valid_share_mode_entry(e)) {
6216 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6219 /* Fail with sharing violation. */
6220 close_file(fsp, NORMAL_CLOSE);
6222 return NT_STATUS_SHARING_VIOLATION;
6227 * Set the delete on close.
6229 status = smb_set_file_disposition_info(conn,
6236 if (!NT_STATUS_IS_OK(status)) {
6237 close_file(fsp, NORMAL_CLOSE);
6242 return close_file(fsp, NORMAL_CLOSE);
6245 /****************************************************************************
6246 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6247 ****************************************************************************/
6249 static void call_trans2setfilepathinfo(connection_struct *conn,
6250 struct smb_request *req,
6251 unsigned int tran_call,
6252 char **pparams, int total_params,
6253 char **ppdata, int total_data,
6254 unsigned int max_data_bytes)
6256 char *params = *pparams;
6257 char *pdata = *ppdata;
6259 SMB_STRUCT_STAT sbuf;
6261 files_struct *fsp = NULL;
6262 NTSTATUS status = NT_STATUS_OK;
6263 int data_return_size = 0;
6264 TALLOC_CTX *ctx = talloc_tos();
6267 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6273 if (tran_call == TRANSACT2_SETFILEINFO) {
6274 if (total_params < 4) {
6275 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6279 fsp = file_fsp(SVAL(params,0));
6280 /* Basic check for non-null fsp. */
6281 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
6284 info_level = SVAL(params,2);
6286 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6288 reply_nterror(req, NT_STATUS_NO_MEMORY);
6292 if(fsp->is_directory || fsp->fh->fd == -1) {
6294 * This is actually a SETFILEINFO on a directory
6295 * handle (returned from an NT SMB). NT5.0 seems
6296 * to do this call. JRA.
6298 if (INFO_LEVEL_IS_UNIX(info_level)) {
6299 /* Always do lstat for UNIX calls. */
6300 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6301 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6302 reply_unixerror(req,ERRDOS,ERRbadpath);
6306 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6307 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6308 reply_unixerror(req,ERRDOS,ERRbadpath);
6312 } else if (fsp->print_file) {
6314 * Doing a DELETE_ON_CLOSE should cancel a print job.
6316 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6317 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6319 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6322 send_trans2_replies(conn, req, params, 2,
6327 reply_unixerror(req, ERRDOS, ERRbadpath);
6332 * Original code - this is an open file.
6334 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6338 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6339 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6340 reply_unixerror(req, ERRDOS, ERRbadfid);
6346 if (total_params < 7) {
6347 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6351 info_level = SVAL(params,0);
6352 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6353 total_params - 6, STR_TERMINATE,
6355 if (!NT_STATUS_IS_OK(status)) {
6356 reply_nterror(req, status);
6360 status = resolve_dfspath(ctx, conn,
6361 req->flags2 & FLAGS2_DFS_PATHNAMES,
6364 if (!NT_STATUS_IS_OK(status)) {
6365 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6366 reply_botherror(req,
6367 NT_STATUS_PATH_NOT_COVERED,
6368 ERRSRV, ERRbadpath);
6371 reply_nterror(req, status);
6375 status = unix_convert(ctx, conn, fname, False,
6376 &fname, NULL, &sbuf);
6377 if (!NT_STATUS_IS_OK(status)) {
6378 reply_nterror(req, status);
6382 status = check_name(conn, fname);
6383 if (!NT_STATUS_IS_OK(status)) {
6384 reply_nterror(req, status);
6388 if (INFO_LEVEL_IS_UNIX(info_level)) {
6390 * For CIFS UNIX extensions the target name may not exist.
6393 /* Always do lstat for UNIX calls. */
6394 SMB_VFS_LSTAT(conn,fname,&sbuf);
6396 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6397 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6398 reply_unixerror(req, ERRDOS, ERRbadpath);
6403 if (!CAN_WRITE(conn)) {
6404 reply_doserror(req, ERRSRV, ERRaccess);
6408 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6409 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6413 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6414 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6416 /* Realloc the parameter size */
6417 *pparams = (char *)SMB_REALLOC(*pparams,2);
6418 if (*pparams == NULL) {
6419 reply_nterror(req, NT_STATUS_NO_MEMORY);
6426 if (fsp && !null_timespec(fsp->pending_modtime)) {
6427 /* the pending modtime overrides the current modtime */
6428 set_mtimespec(&sbuf, fsp->pending_modtime);
6431 switch (info_level) {
6433 case SMB_INFO_STANDARD:
6435 status = smb_set_info_standard(conn,
6444 case SMB_INFO_SET_EA:
6446 status = smb_info_set_ea(conn,
6454 case SMB_SET_FILE_BASIC_INFO:
6455 case SMB_FILE_BASIC_INFORMATION:
6457 status = smb_set_file_basic_info(conn,
6466 case SMB_FILE_ALLOCATION_INFORMATION:
6467 case SMB_SET_FILE_ALLOCATION_INFO:
6469 status = smb_set_file_allocation_info(conn, req,
6478 case SMB_FILE_END_OF_FILE_INFORMATION:
6479 case SMB_SET_FILE_END_OF_FILE_INFO:
6481 status = smb_set_file_end_of_file_info(conn, req,
6490 case SMB_FILE_DISPOSITION_INFORMATION:
6491 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6494 /* JRA - We used to just ignore this on a path ?
6495 * Shouldn't this be invalid level on a pathname
6498 if (tran_call != TRANSACT2_SETFILEINFO) {
6499 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6502 status = smb_set_file_disposition_info(conn,
6511 case SMB_FILE_POSITION_INFORMATION:
6513 status = smb_file_position_information(conn,
6520 /* From tridge Samba4 :
6521 * MODE_INFORMATION in setfileinfo (I have no
6522 * idea what "mode information" on a file is - it takes a value of 0,
6523 * 2, 4 or 6. What could it be?).
6526 case SMB_FILE_MODE_INFORMATION:
6528 status = smb_file_mode_information(conn,
6535 * CIFS UNIX extensions.
6538 case SMB_SET_FILE_UNIX_BASIC:
6540 status = smb_set_file_unix_basic(conn, req,
6549 case SMB_SET_FILE_UNIX_INFO2:
6551 status = smb_set_file_unix_info2(conn, req,
6560 case SMB_SET_FILE_UNIX_LINK:
6562 if (tran_call != TRANSACT2_SETPATHINFO) {
6563 /* We must have a pathname for this. */
6564 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6567 status = smb_set_file_unix_link(conn, req, pdata,
6572 case SMB_SET_FILE_UNIX_HLINK:
6574 if (tran_call != TRANSACT2_SETPATHINFO) {
6575 /* We must have a pathname for this. */
6576 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6579 status = smb_set_file_unix_hlink(conn, req,
6585 case SMB_FILE_RENAME_INFORMATION:
6587 status = smb_file_rename_information(conn, req,
6593 #if defined(HAVE_POSIX_ACLS)
6594 case SMB_SET_POSIX_ACL:
6596 status = smb_set_posix_acl(conn,
6606 case SMB_SET_POSIX_LOCK:
6608 if (tran_call != TRANSACT2_SETFILEINFO) {
6609 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6612 status = smb_set_posix_lock(conn, req,
6613 pdata, total_data, fsp);
6617 case SMB_POSIX_PATH_OPEN:
6619 if (tran_call != TRANSACT2_SETPATHINFO) {
6620 /* We must have a pathname for this. */
6621 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6625 status = smb_posix_open(conn, req,
6634 case SMB_POSIX_PATH_UNLINK:
6636 if (tran_call != TRANSACT2_SETPATHINFO) {
6637 /* We must have a pathname for this. */
6638 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6642 status = smb_posix_unlink(conn, req,
6651 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6656 if (!NT_STATUS_IS_OK(status)) {
6657 if (open_was_deferred(req->mid)) {
6658 /* We have re-scheduled this call. */
6661 if (blocking_lock_was_deferred(req->mid)) {
6662 /* We have re-scheduled this call. */
6665 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6666 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6667 ERRSRV, ERRbadpath);
6670 if (info_level == SMB_POSIX_PATH_OPEN) {
6671 reply_openerror(req, status);
6675 reply_nterror(req, status);
6680 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
6686 /****************************************************************************
6687 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6688 ****************************************************************************/
6690 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6691 char **pparams, int total_params,
6692 char **ppdata, int total_data,
6693 unsigned int max_data_bytes)
6695 char *params = *pparams;
6696 char *pdata = *ppdata;
6697 char *directory = NULL;
6698 SMB_STRUCT_STAT sbuf;
6699 NTSTATUS status = NT_STATUS_OK;
6700 struct ea_list *ea_list = NULL;
6701 TALLOC_CTX *ctx = talloc_tos();
6703 if (!CAN_WRITE(conn)) {
6704 reply_doserror(req, ERRSRV, ERRaccess);
6708 if (total_params < 5) {
6709 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6713 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
6714 total_params - 4, STR_TERMINATE,
6716 if (!NT_STATUS_IS_OK(status)) {
6717 reply_nterror(req, status);
6721 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6723 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6724 if (!NT_STATUS_IS_OK(status)) {
6725 reply_nterror(req, status);
6729 status = check_name(conn, directory);
6730 if (!NT_STATUS_IS_OK(status)) {
6731 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6732 reply_nterror(req, status);
6736 /* Any data in this call is an EA list. */
6737 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6738 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6743 * OS/2 workplace shell seems to send SET_EA requests of "null"
6744 * length (4 bytes containing IVAL 4).
6745 * They seem to have no effect. Bug #3212. JRA.
6748 if (total_data != 4) {
6749 if (total_data < 10) {
6750 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6754 if (IVAL(pdata,0) > total_data) {
6755 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6756 IVAL(pdata,0), (unsigned int)total_data));
6757 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6761 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6764 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6767 } else if (IVAL(pdata,0) != 4) {
6768 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6772 status = create_directory(conn, req, directory);
6774 if (!NT_STATUS_IS_OK(status)) {
6775 reply_nterror(req, status);
6779 /* Try and set any given EA. */
6781 status = set_ea(conn, NULL, directory, ea_list);
6782 if (!NT_STATUS_IS_OK(status)) {
6783 reply_nterror(req, status);
6788 /* Realloc the parameter and data sizes */
6789 *pparams = (char *)SMB_REALLOC(*pparams,2);
6790 if(*pparams == NULL) {
6791 reply_nterror(req, NT_STATUS_NO_MEMORY);
6798 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
6803 /****************************************************************************
6804 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6805 We don't actually do this - we just send a null response.
6806 ****************************************************************************/
6808 static void call_trans2findnotifyfirst(connection_struct *conn,
6809 struct smb_request *req,
6810 char **pparams, int total_params,
6811 char **ppdata, int total_data,
6812 unsigned int max_data_bytes)
6814 static uint16 fnf_handle = 257;
6815 char *params = *pparams;
6818 if (total_params < 6) {
6819 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6823 info_level = SVAL(params,4);
6824 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6826 switch (info_level) {
6831 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6835 /* Realloc the parameter and data sizes */
6836 *pparams = (char *)SMB_REALLOC(*pparams,6);
6837 if (*pparams == NULL) {
6838 reply_nterror(req, NT_STATUS_NO_MEMORY);
6843 SSVAL(params,0,fnf_handle);
6844 SSVAL(params,2,0); /* No changes */
6845 SSVAL(params,4,0); /* No EA errors */
6852 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
6857 /****************************************************************************
6858 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6859 changes). Currently this does nothing.
6860 ****************************************************************************/
6862 static void call_trans2findnotifynext(connection_struct *conn,
6863 struct smb_request *req,
6864 char **pparams, int total_params,
6865 char **ppdata, int total_data,
6866 unsigned int max_data_bytes)
6868 char *params = *pparams;
6870 DEBUG(3,("call_trans2findnotifynext\n"));
6872 /* Realloc the parameter and data sizes */
6873 *pparams = (char *)SMB_REALLOC(*pparams,4);
6874 if (*pparams == NULL) {
6875 reply_nterror(req, NT_STATUS_NO_MEMORY);
6880 SSVAL(params,0,0); /* No changes */
6881 SSVAL(params,2,0); /* No EA errors */
6883 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
6888 /****************************************************************************
6889 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6890 ****************************************************************************/
6892 static void call_trans2getdfsreferral(connection_struct *conn,
6893 struct smb_request *req,
6894 char **pparams, int total_params,
6895 char **ppdata, int total_data,
6896 unsigned int max_data_bytes)
6898 char *params = *pparams;
6899 char *pathname = NULL;
6901 int max_referral_level;
6902 NTSTATUS status = NT_STATUS_OK;
6903 TALLOC_CTX *ctx = talloc_tos();
6905 DEBUG(10,("call_trans2getdfsreferral\n"));
6907 if (total_params < 3) {
6908 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6912 max_referral_level = SVAL(params,0);
6914 if(!lp_host_msdfs()) {
6915 reply_doserror(req, ERRDOS, ERRbadfunc);
6919 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
6920 total_params - 2, STR_TERMINATE);
6922 reply_nterror(req, NT_STATUS_NOT_FOUND);
6925 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6926 ppdata,&status)) < 0) {
6927 reply_nterror(req, status);
6931 SSVAL(req->inbuf, smb_flg2,
6932 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6933 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
6938 #define LMCAT_SPL 0x53
6939 #define LMFUNC_GETJOBID 0x60
6941 /****************************************************************************
6942 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6943 ****************************************************************************/
6945 static void call_trans2ioctl(connection_struct *conn,
6946 struct smb_request *req,
6947 char **pparams, int total_params,
6948 char **ppdata, int total_data,
6949 unsigned int max_data_bytes)
6951 char *pdata = *ppdata;
6952 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6954 /* check for an invalid fid before proceeding */
6957 reply_doserror(req, ERRDOS, ERRbadfid);
6961 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6962 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6963 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6964 if (*ppdata == NULL) {
6965 reply_nterror(req, NT_STATUS_NO_MEMORY);
6970 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6971 CAN ACCEPT THIS IN UNICODE. JRA. */
6973 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6974 srvstr_push(pdata, req->flags2, pdata + 2,
6975 global_myname(), 15,
6976 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6977 srvstr_push(pdata, req->flags2, pdata+18,
6978 lp_servicename(SNUM(conn)), 13,
6979 STR_ASCII|STR_TERMINATE); /* Service name */
6980 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
6985 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6986 reply_doserror(req, ERRSRV, ERRerror);
6989 /****************************************************************************
6990 Reply to a SMBfindclose (stop trans2 directory search).
6991 ****************************************************************************/
6993 void reply_findclose(struct smb_request *req)
6997 START_PROFILE(SMBfindclose);
7000 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7001 END_PROFILE(SMBfindclose);
7005 dptr_num = SVALS(req->inbuf,smb_vwv0);
7007 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7009 dptr_close(&dptr_num);
7011 reply_outbuf(req, 0, 0);
7013 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7015 END_PROFILE(SMBfindclose);
7019 /****************************************************************************
7020 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7021 ****************************************************************************/
7023 void reply_findnclose(struct smb_request *req)
7027 START_PROFILE(SMBfindnclose);
7030 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7031 END_PROFILE(SMBfindnclose);
7035 dptr_num = SVAL(req->inbuf,smb_vwv0);
7037 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7039 /* We never give out valid handles for a
7040 findnotifyfirst - so any dptr_num is ok here.
7043 reply_outbuf(req, 0, 0);
7045 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7047 END_PROFILE(SMBfindnclose);
7051 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7052 struct trans_state *state)
7054 if (Protocol >= PROTOCOL_NT1) {
7055 req->flags2 |= 0x40; /* IS_LONG_NAME */
7056 SSVAL(req->inbuf,smb_flg2,req->flags2);
7059 if (conn->encrypt_level == Required && !req->encrypted) {
7060 if (state->call != TRANSACT2_QFSINFO &&
7061 state->call != TRANSACT2_SETFSINFO) {
7062 DEBUG(0,("handle_trans2: encryption required "
7064 (unsigned int)state->call));
7065 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7070 /* Now we must call the relevant TRANS2 function */
7071 switch(state->call) {
7072 case TRANSACT2_OPEN:
7074 START_PROFILE(Trans2_open);
7075 call_trans2open(conn, req,
7076 &state->param, state->total_param,
7077 &state->data, state->total_data,
7078 state->max_data_return);
7079 END_PROFILE(Trans2_open);
7083 case TRANSACT2_FINDFIRST:
7085 START_PROFILE(Trans2_findfirst);
7086 call_trans2findfirst(conn, req,
7087 &state->param, state->total_param,
7088 &state->data, state->total_data,
7089 state->max_data_return);
7090 END_PROFILE(Trans2_findfirst);
7094 case TRANSACT2_FINDNEXT:
7096 START_PROFILE(Trans2_findnext);
7097 call_trans2findnext(conn, req,
7098 &state->param, state->total_param,
7099 &state->data, state->total_data,
7100 state->max_data_return);
7101 END_PROFILE(Trans2_findnext);
7105 case TRANSACT2_QFSINFO:
7107 START_PROFILE(Trans2_qfsinfo);
7108 call_trans2qfsinfo(conn, req,
7109 &state->param, state->total_param,
7110 &state->data, state->total_data,
7111 state->max_data_return);
7112 END_PROFILE(Trans2_qfsinfo);
7116 case TRANSACT2_SETFSINFO:
7118 START_PROFILE(Trans2_setfsinfo);
7119 call_trans2setfsinfo(conn, req,
7120 &state->param, state->total_param,
7121 &state->data, state->total_data,
7122 state->max_data_return);
7123 END_PROFILE(Trans2_setfsinfo);
7127 case TRANSACT2_QPATHINFO:
7128 case TRANSACT2_QFILEINFO:
7130 START_PROFILE(Trans2_qpathinfo);
7131 call_trans2qfilepathinfo(conn, req, state->call,
7132 &state->param, state->total_param,
7133 &state->data, state->total_data,
7134 state->max_data_return);
7135 END_PROFILE(Trans2_qpathinfo);
7139 case TRANSACT2_SETPATHINFO:
7140 case TRANSACT2_SETFILEINFO:
7142 START_PROFILE(Trans2_setpathinfo);
7143 call_trans2setfilepathinfo(conn, req, state->call,
7144 &state->param, state->total_param,
7145 &state->data, state->total_data,
7146 state->max_data_return);
7147 END_PROFILE(Trans2_setpathinfo);
7151 case TRANSACT2_FINDNOTIFYFIRST:
7153 START_PROFILE(Trans2_findnotifyfirst);
7154 call_trans2findnotifyfirst(conn, req,
7155 &state->param, state->total_param,
7156 &state->data, state->total_data,
7157 state->max_data_return);
7158 END_PROFILE(Trans2_findnotifyfirst);
7162 case TRANSACT2_FINDNOTIFYNEXT:
7164 START_PROFILE(Trans2_findnotifynext);
7165 call_trans2findnotifynext(conn, req,
7166 &state->param, state->total_param,
7167 &state->data, state->total_data,
7168 state->max_data_return);
7169 END_PROFILE(Trans2_findnotifynext);
7173 case TRANSACT2_MKDIR:
7175 START_PROFILE(Trans2_mkdir);
7176 call_trans2mkdir(conn, req,
7177 &state->param, state->total_param,
7178 &state->data, state->total_data,
7179 state->max_data_return);
7180 END_PROFILE(Trans2_mkdir);
7184 case TRANSACT2_GET_DFS_REFERRAL:
7186 START_PROFILE(Trans2_get_dfs_referral);
7187 call_trans2getdfsreferral(conn, req,
7188 &state->param, state->total_param,
7189 &state->data, state->total_data,
7190 state->max_data_return);
7191 END_PROFILE(Trans2_get_dfs_referral);
7195 case TRANSACT2_IOCTL:
7197 START_PROFILE(Trans2_ioctl);
7198 call_trans2ioctl(conn, req,
7199 &state->param, state->total_param,
7200 &state->data, state->total_data,
7201 state->max_data_return);
7202 END_PROFILE(Trans2_ioctl);
7207 /* Error in request */
7208 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7209 reply_doserror(req, ERRSRV,ERRerror);
7213 /****************************************************************************
7214 Reply to a SMBtrans2.
7215 ****************************************************************************/
7217 void reply_trans2(struct smb_request *req)
7219 connection_struct *conn = req->conn;
7224 unsigned int tran_call;
7226 struct trans_state *state;
7229 START_PROFILE(SMBtrans2);
7231 if (req->wct < 14) {
7232 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7233 END_PROFILE(SMBtrans2);
7237 dsoff = SVAL(req->inbuf, smb_dsoff);
7238 dscnt = SVAL(req->inbuf, smb_dscnt);
7239 psoff = SVAL(req->inbuf, smb_psoff);
7240 pscnt = SVAL(req->inbuf, smb_pscnt);
7241 tran_call = SVAL(req->inbuf, smb_setup0);
7242 size = smb_len(req->inbuf) + 4;
7244 result = allow_new_trans(conn->pending_trans, req->mid);
7245 if (!NT_STATUS_IS_OK(result)) {
7246 DEBUG(2, ("Got invalid trans2 request: %s\n",
7247 nt_errstr(result)));
7248 reply_nterror(req, result);
7249 END_PROFILE(SMBtrans2);
7254 switch (tran_call) {
7255 /* List the allowed trans2 calls on IPC$ */
7256 case TRANSACT2_OPEN:
7257 case TRANSACT2_GET_DFS_REFERRAL:
7258 case TRANSACT2_QFILEINFO:
7259 case TRANSACT2_QFSINFO:
7260 case TRANSACT2_SETFSINFO:
7263 reply_doserror(req, ERRSRV, ERRaccess);
7264 END_PROFILE(SMBtrans2);
7269 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7270 DEBUG(0, ("talloc failed\n"));
7271 reply_nterror(req, NT_STATUS_NO_MEMORY);
7272 END_PROFILE(SMBtrans2);
7276 state->cmd = SMBtrans2;
7278 state->mid = req->mid;
7279 state->vuid = req->vuid;
7280 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7281 state->setup = NULL;
7282 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7283 state->param = NULL;
7284 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7286 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7287 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7288 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7289 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7290 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7292 state->call = tran_call;
7294 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7295 is so as a sanity check */
7296 if (state->setup_count != 1) {
7298 * Need to have rc=0 for ioctl to get job id for OS/2.
7299 * Network printing will fail if function is not successful.
7300 * Similar function in reply.c will be used if protocol
7301 * is LANMAN1.0 instead of LM1.2X002.
7302 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7303 * outbuf doesn't have to be set(only job id is used).
7305 if ( (state->setup_count == 4)
7306 && (tran_call == TRANSACT2_IOCTL)
7307 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7308 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7309 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7311 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7312 DEBUG(2,("Transaction is %d\n",tran_call));
7314 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7315 END_PROFILE(SMBtrans2);
7320 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7323 if (state->total_data) {
7324 /* Can't use talloc here, the core routines do realloc on the
7325 * params and data. */
7326 state->data = (char *)SMB_MALLOC(state->total_data);
7327 if (state->data == NULL) {
7328 DEBUG(0,("reply_trans2: data malloc fail for %u "
7329 "bytes !\n", (unsigned int)state->total_data));
7331 reply_nterror(req, NT_STATUS_NO_MEMORY);
7332 END_PROFILE(SMBtrans2);
7335 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7337 if ((smb_base(req->inbuf)+dsoff+dscnt
7338 > (char *)req->inbuf + size) ||
7339 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7342 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7345 if (state->total_param) {
7346 /* Can't use talloc here, the core routines do realloc on the
7347 * params and data. */
7348 state->param = (char *)SMB_MALLOC(state->total_param);
7349 if (state->param == NULL) {
7350 DEBUG(0,("reply_trans: param malloc fail for %u "
7351 "bytes !\n", (unsigned int)state->total_param));
7352 SAFE_FREE(state->data);
7354 reply_nterror(req, NT_STATUS_NO_MEMORY);
7355 END_PROFILE(SMBtrans2);
7358 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7360 if ((smb_base(req->inbuf)+psoff+pscnt
7361 > (char *)req->inbuf + size) ||
7362 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7365 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7368 state->received_data = dscnt;
7369 state->received_param = pscnt;
7371 if ((state->received_param == state->total_param) &&
7372 (state->received_data == state->total_data)) {
7374 handle_trans2(conn, req, state);
7376 SAFE_FREE(state->data);
7377 SAFE_FREE(state->param);
7379 END_PROFILE(SMBtrans2);
7383 DLIST_ADD(conn->pending_trans, state);
7385 /* We need to send an interim response then receive the rest
7386 of the parameter/data bytes */
7387 reply_outbuf(req, 0, 0);
7388 show_msg((char *)req->outbuf);
7389 END_PROFILE(SMBtrans2);
7394 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7395 SAFE_FREE(state->data);
7396 SAFE_FREE(state->param);
7398 END_PROFILE(SMBtrans2);
7399 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7403 /****************************************************************************
7404 Reply to a SMBtranss2
7405 ****************************************************************************/
7407 void reply_transs2(struct smb_request *req)
7409 connection_struct *conn = req->conn;
7410 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7411 struct trans_state *state;
7414 START_PROFILE(SMBtranss2);
7416 show_msg((char *)req->inbuf);
7419 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7420 END_PROFILE(SMBtranss2);
7424 size = smb_len(req->inbuf)+4;
7426 for (state = conn->pending_trans; state != NULL;
7427 state = state->next) {
7428 if (state->mid == req->mid) {
7433 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7434 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7435 END_PROFILE(SMBtranss2);
7439 /* Revise state->total_param and state->total_data in case they have
7440 changed downwards */
7442 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7443 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7444 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7445 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7447 pcnt = SVAL(req->inbuf, smb_spscnt);
7448 poff = SVAL(req->inbuf, smb_spsoff);
7449 pdisp = SVAL(req->inbuf, smb_spsdisp);
7451 dcnt = SVAL(req->inbuf, smb_sdscnt);
7452 doff = SVAL(req->inbuf, smb_sdsoff);
7453 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7455 state->received_param += pcnt;
7456 state->received_data += dcnt;
7458 if ((state->received_data > state->total_data) ||
7459 (state->received_param > state->total_param))
7463 if (pdisp+pcnt > state->total_param)
7465 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7467 if (pdisp > state->total_param)
7469 if ((smb_base(req->inbuf) + poff + pcnt
7470 > (char *)req->inbuf + size) ||
7471 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7473 if (state->param + pdisp < state->param)
7476 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7481 if (ddisp+dcnt > state->total_data)
7483 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7485 if (ddisp > state->total_data)
7487 if ((smb_base(req->inbuf) + doff + dcnt
7488 > (char *)req->inbuf + size) ||
7489 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7491 if (state->data + ddisp < state->data)
7494 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7498 if ((state->received_param < state->total_param) ||
7499 (state->received_data < state->total_data)) {
7500 END_PROFILE(SMBtranss2);
7505 * construct_reply_common will copy smb_com from inbuf to
7506 * outbuf. SMBtranss2 is wrong here.
7508 SCVAL(req->inbuf,smb_com,SMBtrans2);
7510 handle_trans2(conn, req, state);
7512 DLIST_REMOVE(conn->pending_trans, state);
7513 SAFE_FREE(state->data);
7514 SAFE_FREE(state->param);
7517 END_PROFILE(SMBtranss2);
7522 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7523 DLIST_REMOVE(conn->pending_trans, state);
7524 SAFE_FREE(state->data);
7525 SAFE_FREE(state->param);
7527 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7528 END_PROFILE(SMBtranss2);