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));
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:
2491 #if defined(HAVE_SYS_QUOTAS)
2492 quota_flag = FILE_VOLUME_QUOTAS;
2495 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2496 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2497 FILE_SUPPORTS_OBJECT_IDS|
2498 FILE_UNICODE_ON_DISK|
2499 quota_flag); /* FS ATTRIBUTES */
2501 SIVAL(pdata,4,255); /* Max filename component length */
2502 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2503 and will think we can't do long filenames */
2504 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2505 PTR_DIFF(end_data, pdata+12),
2508 data_len = 12 + len;
2511 case SMB_QUERY_FS_LABEL_INFO:
2512 case SMB_FS_LABEL_INFORMATION:
2513 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2514 PTR_DIFF(end_data, pdata+4), 0);
2519 case SMB_QUERY_FS_VOLUME_INFO:
2520 case SMB_FS_VOLUME_INFORMATION:
2523 * Add volume serial number - hash of a combination of
2524 * the called hostname and the service name.
2526 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2527 (str_checksum(get_local_machine_name())<<16));
2529 /* Max label len is 32 characters. */
2530 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2531 PTR_DIFF(end_data, pdata+18),
2533 SIVAL(pdata,12,len);
2536 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2537 (int)strlen(vname),vname, lp_servicename(snum)));
2540 case SMB_QUERY_FS_SIZE_INFO:
2541 case SMB_FS_SIZE_INFORMATION:
2543 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2545 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2546 reply_unixerror(req, ERRHRD, ERRgeneral);
2549 block_size = lp_block_size(snum);
2550 if (bsize < block_size) {
2551 SMB_BIG_UINT factor = block_size/bsize;
2556 if (bsize > block_size) {
2557 SMB_BIG_UINT factor = bsize/block_size;
2562 bytes_per_sector = 512;
2563 sectors_per_unit = bsize/bytes_per_sector;
2564 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2565 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2566 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2567 SBIG_UINT(pdata,0,dsize);
2568 SBIG_UINT(pdata,8,dfree);
2569 SIVAL(pdata,16,sectors_per_unit);
2570 SIVAL(pdata,20,bytes_per_sector);
2574 case SMB_FS_FULL_SIZE_INFORMATION:
2576 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2578 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2579 reply_unixerror(req, ERRHRD, ERRgeneral);
2582 block_size = lp_block_size(snum);
2583 if (bsize < block_size) {
2584 SMB_BIG_UINT factor = block_size/bsize;
2589 if (bsize > block_size) {
2590 SMB_BIG_UINT factor = bsize/block_size;
2595 bytes_per_sector = 512;
2596 sectors_per_unit = bsize/bytes_per_sector;
2597 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2598 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2599 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2600 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2601 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2602 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2603 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2604 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2608 case SMB_QUERY_FS_DEVICE_INFO:
2609 case SMB_FS_DEVICE_INFORMATION:
2611 SIVAL(pdata,0,0); /* dev type */
2612 SIVAL(pdata,4,0); /* characteristics */
2615 #ifdef HAVE_SYS_QUOTAS
2616 case SMB_FS_QUOTA_INFORMATION:
2618 * what we have to send --metze:
2620 * Unknown1: 24 NULL bytes
2621 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2622 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2623 * Quota Flags: 2 byte :
2624 * Unknown3: 6 NULL bytes
2628 * details for Quota Flags:
2630 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2631 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2632 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2633 * 0x0001 Enable Quotas: enable quota for this fs
2637 /* we need to fake up a fsp here,
2638 * because its not send in this call
2641 SMB_NTQUOTA_STRUCT quotas;
2644 ZERO_STRUCT(quotas);
2650 if (current_user.ut.uid != 0) {
2651 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2652 lp_servicename(SNUM(conn)),conn->user));
2653 reply_doserror(req, ERRDOS, ERRnoaccess);
2657 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2658 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2659 reply_doserror(req, ERRSRV, ERRerror);
2665 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2667 /* Unknown1 24 NULL bytes*/
2668 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2669 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2670 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2672 /* Default Soft Quota 8 bytes */
2673 SBIG_UINT(pdata,24,quotas.softlim);
2675 /* Default Hard Quota 8 bytes */
2676 SBIG_UINT(pdata,32,quotas.hardlim);
2678 /* Quota flag 2 bytes */
2679 SSVAL(pdata,40,quotas.qflags);
2681 /* Unknown3 6 NULL bytes */
2687 #endif /* HAVE_SYS_QUOTAS */
2688 case SMB_FS_OBJECTID_INFORMATION:
2690 unsigned char objid[16];
2691 memcpy(pdata,create_volume_objectid(conn, objid),16);
2697 * Query the version and capabilities of the CIFS UNIX extensions
2701 case SMB_QUERY_CIFS_UNIX_INFO:
2703 bool large_write = lp_min_receive_file_size() &&
2704 !srv_is_signing_active();
2705 bool large_read = !srv_is_signing_active();
2706 int encrypt_caps = 0;
2708 if (!lp_unix_extensions()) {
2709 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2713 switch (conn->encrypt_level) {
2719 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2722 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2723 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2724 large_write = false;
2730 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2731 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2733 /* We have POSIX ACLs, pathname, encryption,
2734 * large read/write, and locking capability. */
2736 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2737 CIFS_UNIX_POSIX_ACLS_CAP|
2738 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2739 CIFS_UNIX_FCNTL_LOCKS_CAP|
2740 CIFS_UNIX_EXTATTR_CAP|
2741 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2743 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2745 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2749 case SMB_QUERY_POSIX_FS_INFO:
2752 vfs_statvfs_struct svfs;
2754 if (!lp_unix_extensions()) {
2755 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2759 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2763 SIVAL(pdata,0,svfs.OptimalTransferSize);
2764 SIVAL(pdata,4,svfs.BlockSize);
2765 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2766 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2767 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2768 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2769 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2770 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2771 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2773 } else if (rc == EOPNOTSUPP) {
2774 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2776 #endif /* EOPNOTSUPP */
2778 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2779 reply_doserror(req, ERRSRV, ERRerror);
2785 case SMB_QUERY_POSIX_WHOAMI:
2791 if (!lp_unix_extensions()) {
2792 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2796 if (max_data_bytes < 40) {
2797 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2801 /* We ARE guest if global_sid_Builtin_Guests is
2802 * in our list of SIDs.
2804 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2805 current_user.nt_user_token)) {
2806 flags |= SMB_WHOAMI_GUEST;
2809 /* We are NOT guest if global_sid_Authenticated_Users
2810 * is in our list of SIDs.
2812 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2813 current_user.nt_user_token)) {
2814 flags &= ~SMB_WHOAMI_GUEST;
2817 /* NOTE: 8 bytes for UID/GID, irrespective of native
2818 * platform size. This matches
2819 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2821 data_len = 4 /* flags */
2828 + 4 /* pad/reserved */
2829 + (current_user.ut.ngroups * 8)
2831 + (current_user.nt_user_token->num_sids *
2835 SIVAL(pdata, 0, flags);
2836 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2837 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2838 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2841 if (data_len >= max_data_bytes) {
2842 /* Potential overflow, skip the GIDs and SIDs. */
2844 SIVAL(pdata, 24, 0); /* num_groups */
2845 SIVAL(pdata, 28, 0); /* num_sids */
2846 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2847 SIVAL(pdata, 36, 0); /* reserved */
2853 SIVAL(pdata, 24, current_user.ut.ngroups);
2855 current_user.nt_user_token->num_sids);
2857 /* We walk the SID list twice, but this call is fairly
2858 * infrequent, and I don't expect that it's performance
2859 * sensitive -- jpeach
2861 for (i = 0, sid_bytes = 0;
2862 i < current_user.nt_user_token->num_sids; ++i) {
2863 sid_bytes += ndr_size_dom_sid(
2864 ¤t_user.nt_user_token->user_sids[i], 0);
2867 /* SID list byte count */
2868 SIVAL(pdata, 32, sid_bytes);
2870 /* 4 bytes pad/reserved - must be zero */
2871 SIVAL(pdata, 36, 0);
2875 for (i = 0; i < current_user.ut.ngroups; ++i) {
2876 SBIG_UINT(pdata, data_len,
2877 (SMB_BIG_UINT)current_user.ut.groups[i]);
2883 i < current_user.nt_user_token->num_sids; ++i) {
2884 int sid_len = ndr_size_dom_sid(
2885 ¤t_user.nt_user_token->user_sids[i], 0);
2887 sid_linearize(pdata + data_len, sid_len,
2888 ¤t_user.nt_user_token->user_sids[i]);
2889 data_len += sid_len;
2895 case SMB_MAC_QUERY_FS_INFO:
2897 * Thursby MAC extension... ONLY on NTFS filesystems
2898 * once we do streams then we don't need this
2900 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2902 SIVAL(pdata,84,0x100); /* Don't support mac... */
2907 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2912 send_trans2_replies(conn, req, params, 0, pdata, data_len,
2915 DEBUG( 4, ( "%s info_level = %d\n",
2916 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2921 /****************************************************************************
2922 Reply to a TRANS2_SETFSINFO (set filesystem info).
2923 ****************************************************************************/
2925 static void call_trans2setfsinfo(connection_struct *conn,
2926 struct smb_request *req,
2927 char **pparams, int total_params,
2928 char **ppdata, int total_data,
2929 unsigned int max_data_bytes)
2931 char *pdata = *ppdata;
2932 char *params = *pparams;
2935 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2938 if (total_params < 4) {
2939 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2941 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2945 info_level = SVAL(params,2);
2948 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
2949 info_level != SMB_SET_CIFS_UNIX_INFO) {
2950 DEBUG(0,("call_trans2setfsinfo: not an allowed "
2951 "info level (0x%x) on IPC$.\n",
2952 (unsigned int)info_level));
2953 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2958 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2959 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
2960 DEBUG(0,("call_trans2setfsinfo: encryption required "
2961 "and info level 0x%x sent.\n",
2962 (unsigned int)info_level));
2963 exit_server_cleanly("encryption required "
2969 switch(info_level) {
2970 case SMB_SET_CIFS_UNIX_INFO:
2972 uint16 client_unix_major;
2973 uint16 client_unix_minor;
2974 uint32 client_unix_cap_low;
2975 uint32 client_unix_cap_high;
2977 if (!lp_unix_extensions()) {
2979 NT_STATUS_INVALID_LEVEL);
2983 /* There should be 12 bytes of capabilities set. */
2984 if (total_data < 8) {
2987 NT_STATUS_INVALID_PARAMETER);
2990 client_unix_major = SVAL(pdata,0);
2991 client_unix_minor = SVAL(pdata,2);
2992 client_unix_cap_low = IVAL(pdata,4);
2993 client_unix_cap_high = IVAL(pdata,8);
2994 /* Just print these values for now. */
2995 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2996 cap_low = 0x%x, cap_high = 0x%x\n",
2997 (unsigned int)client_unix_major,
2998 (unsigned int)client_unix_minor,
2999 (unsigned int)client_unix_cap_low,
3000 (unsigned int)client_unix_cap_high ));
3002 /* Here is where we must switch to posix pathname processing... */
3003 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3004 lp_set_posix_pathnames();
3005 mangle_change_to_posix();
3008 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3009 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3010 /* Client that knows how to do posix locks,
3011 * but not posix open/mkdir operations. Set a
3012 * default type for read/write checks. */
3014 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3020 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3023 size_t param_len = 0;
3024 size_t data_len = total_data;
3026 if (!lp_unix_extensions()) {
3029 NT_STATUS_INVALID_LEVEL);
3033 if (lp_smb_encrypt(SNUM(conn)) == false) {
3036 NT_STATUS_NOT_SUPPORTED);
3040 DEBUG( 4,("call_trans2setfsinfo: "
3041 "request transport encrption.\n"));
3043 status = srv_request_encryption_setup(conn,
3044 (unsigned char **)ppdata,
3046 (unsigned char **)pparams,
3049 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3050 !NT_STATUS_IS_OK(status)) {
3051 reply_nterror(req, status);
3055 send_trans2_replies(conn, req,
3062 if (NT_STATUS_IS_OK(status)) {
3063 /* Server-side transport
3064 * encryption is now *on*. */
3065 status = srv_encryption_start(conn);
3066 if (!NT_STATUS_IS_OK(status)) {
3067 exit_server_cleanly(
3068 "Failure in setting "
3069 "up encrypted transport");
3075 case SMB_FS_QUOTA_INFORMATION:
3077 files_struct *fsp = NULL;
3078 SMB_NTQUOTA_STRUCT quotas;
3080 ZERO_STRUCT(quotas);
3083 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3084 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3085 lp_servicename(SNUM(conn)),conn->user));
3086 reply_doserror(req, ERRSRV, ERRaccess);
3090 /* note: normaly there're 48 bytes,
3091 * but we didn't use the last 6 bytes for now
3094 fsp = file_fsp(SVAL(params,0));
3095 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3096 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3098 req, NT_STATUS_INVALID_HANDLE);
3102 if (total_data < 42) {
3103 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3107 NT_STATUS_INVALID_PARAMETER);
3111 /* unknown_1 24 NULL bytes in pdata*/
3113 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3114 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3115 #ifdef LARGE_SMB_OFF_T
3116 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3117 #else /* LARGE_SMB_OFF_T */
3118 if ((IVAL(pdata,28) != 0)&&
3119 ((quotas.softlim != 0xFFFFFFFF)||
3120 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3121 /* more than 32 bits? */
3124 NT_STATUS_INVALID_PARAMETER);
3127 #endif /* LARGE_SMB_OFF_T */
3129 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3130 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3131 #ifdef LARGE_SMB_OFF_T
3132 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3133 #else /* LARGE_SMB_OFF_T */
3134 if ((IVAL(pdata,36) != 0)&&
3135 ((quotas.hardlim != 0xFFFFFFFF)||
3136 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3137 /* more than 32 bits? */
3140 NT_STATUS_INVALID_PARAMETER);
3143 #endif /* LARGE_SMB_OFF_T */
3145 /* quota_flags 2 bytes **/
3146 quotas.qflags = SVAL(pdata,40);
3148 /* unknown_2 6 NULL bytes follow*/
3150 /* now set the quotas */
3151 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3152 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3153 reply_doserror(req, ERRSRV, ERRerror);
3160 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3162 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3168 * sending this reply works fine,
3169 * but I'm not sure it's the same
3170 * like windows do...
3173 reply_outbuf(req, 10, 0);
3176 #if defined(HAVE_POSIX_ACLS)
3177 /****************************************************************************
3178 Utility function to count the number of entries in a POSIX acl.
3179 ****************************************************************************/
3181 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3183 unsigned int ace_count = 0;
3184 int entry_id = SMB_ACL_FIRST_ENTRY;
3185 SMB_ACL_ENTRY_T entry;
3187 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3189 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3190 entry_id = SMB_ACL_NEXT_ENTRY;
3197 /****************************************************************************
3198 Utility function to marshall a POSIX acl into wire format.
3199 ****************************************************************************/
3201 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3203 int entry_id = SMB_ACL_FIRST_ENTRY;
3204 SMB_ACL_ENTRY_T entry;
3206 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3207 SMB_ACL_TAG_T tagtype;
3208 SMB_ACL_PERMSET_T permset;
3209 unsigned char perms = 0;
3210 unsigned int own_grp;
3213 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3214 entry_id = SMB_ACL_NEXT_ENTRY;
3217 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3218 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3222 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3223 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3227 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3228 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3229 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3231 SCVAL(pdata,1,perms);
3234 case SMB_ACL_USER_OBJ:
3235 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3236 own_grp = (unsigned int)pst->st_uid;
3237 SIVAL(pdata,2,own_grp);
3242 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3244 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3247 own_grp = (unsigned int)*puid;
3248 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3249 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3250 SIVAL(pdata,2,own_grp);
3254 case SMB_ACL_GROUP_OBJ:
3255 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3256 own_grp = (unsigned int)pst->st_gid;
3257 SIVAL(pdata,2,own_grp);
3262 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3264 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3267 own_grp = (unsigned int)*pgid;
3268 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3269 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3270 SIVAL(pdata,2,own_grp);
3275 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3276 SIVAL(pdata,2,0xFFFFFFFF);
3277 SIVAL(pdata,6,0xFFFFFFFF);
3280 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3281 SIVAL(pdata,2,0xFFFFFFFF);
3282 SIVAL(pdata,6,0xFFFFFFFF);
3285 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3288 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3295 /****************************************************************************
3296 Store the FILE_UNIX_BASIC info.
3297 ****************************************************************************/
3299 static char *store_file_unix_basic(connection_struct *conn,
3302 const SMB_STRUCT_STAT *psbuf)
3304 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3305 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3307 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3310 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3313 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3314 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3315 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3318 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3322 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3326 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3329 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3333 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3337 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3340 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3344 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3351 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3352 * the chflags(2) (or equivalent) flags.
3354 * XXX: this really should be behind the VFS interface. To do this, we would
3355 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3356 * Each VFS module could then implement its own mapping as appropriate for the
3357 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3359 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3363 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3367 { UF_IMMUTABLE, EXT_IMMUTABLE },
3371 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3375 { UF_HIDDEN, EXT_HIDDEN },
3378 /* Do not remove. We need to guarantee that this array has at least one
3379 * entry to build on HP-UX.
3385 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3386 uint32 *smb_fflags, uint32 *smb_fmask)
3388 #ifdef HAVE_STAT_ST_FLAGS
3391 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3392 *smb_fmask |= info2_flags_map[i].smb_fflag;
3393 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3394 *smb_fflags |= info2_flags_map[i].smb_fflag;
3397 #endif /* HAVE_STAT_ST_FLAGS */
3400 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3401 const uint32 smb_fflags,
3402 const uint32 smb_fmask,
3405 #ifdef HAVE_STAT_ST_FLAGS
3406 uint32 max_fmask = 0;
3409 *stat_fflags = psbuf->st_flags;
3411 /* For each flags requested in smb_fmask, check the state of the
3412 * corresponding flag in smb_fflags and set or clear the matching
3416 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3417 max_fmask |= info2_flags_map[i].smb_fflag;
3418 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3419 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3420 *stat_fflags |= info2_flags_map[i].stat_fflag;
3422 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3427 /* If smb_fmask is asking to set any bits that are not supported by
3428 * our flag mappings, we should fail.
3430 if ((smb_fmask & max_fmask) != smb_fmask) {
3437 #endif /* HAVE_STAT_ST_FLAGS */
3441 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3442 * of file flags and birth (create) time.
3444 static char *store_file_unix_basic_info2(connection_struct *conn,
3447 const SMB_STRUCT_STAT *psbuf)
3449 uint32 file_flags = 0;
3450 uint32 flags_mask = 0;
3452 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3454 /* Create (birth) time 64 bit */
3455 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3458 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3459 SIVAL(pdata, 0, file_flags); /* flags */
3460 SIVAL(pdata, 4, flags_mask); /* mask */
3466 /****************************************************************************
3467 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3468 ****************************************************************************/
3470 static void call_trans2qpipeinfo(connection_struct *conn,
3471 struct smb_request *req,
3472 unsigned int tran_call,
3473 char **pparams, int total_params,
3474 char **ppdata, int total_data,
3475 unsigned int max_data_bytes)
3477 char *params = *pparams;
3478 char *pdata = *ppdata;
3479 unsigned int data_size = 0;
3480 unsigned int param_size = 2;
3482 smb_np_struct *p_pipe = NULL;
3485 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3489 if (total_params < 4) {
3490 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3494 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3495 if (p_pipe == NULL) {
3496 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3500 info_level = SVAL(params,2);
3502 *pparams = (char *)SMB_REALLOC(*pparams,2);
3503 if (*pparams == NULL) {
3504 reply_nterror(req, NT_STATUS_NO_MEMORY);
3509 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3510 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3511 if (*ppdata == NULL ) {
3512 reply_nterror(req, NT_STATUS_NO_MEMORY);
3517 switch (info_level) {
3518 case SMB_FILE_STANDARD_INFORMATION:
3520 SOFF_T(pdata,0,4096LL);
3527 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3531 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3537 /****************************************************************************
3538 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3539 file name or file id).
3540 ****************************************************************************/
3542 static void call_trans2qfilepathinfo(connection_struct *conn,
3543 struct smb_request *req,
3544 unsigned int tran_call,
3545 char **pparams, int total_params,
3546 char **ppdata, int total_data,
3547 unsigned int max_data_bytes)
3549 char *params = *pparams;
3550 char *pdata = *ppdata;
3551 char *dstart, *dend;
3555 SMB_OFF_T file_size=0;
3556 SMB_BIG_UINT allocation_size=0;
3557 unsigned int data_size = 0;
3558 unsigned int param_size = 2;
3559 SMB_STRUCT_STAT sbuf;
3560 char *dos_fname = NULL;
3566 bool delete_pending = False;
3568 time_t create_time, mtime, atime;
3569 struct timespec create_time_ts, mtime_ts, atime_ts;
3570 files_struct *fsp = NULL;
3571 struct file_id fileid;
3572 struct ea_list *ea_list = NULL;
3573 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3574 char *lock_data = NULL;
3575 TALLOC_CTX *ctx = talloc_tos();
3578 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3584 if (tran_call == TRANSACT2_QFILEINFO) {
3585 if (total_params < 4) {
3586 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3591 call_trans2qpipeinfo(conn, req, tran_call,
3592 pparams, total_params,
3598 fsp = file_fsp(SVAL(params,0));
3599 info_level = SVAL(params,2);
3601 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3603 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3604 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3608 /* Initial check for valid fsp ptr. */
3609 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
3613 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3615 reply_nterror(req, NT_STATUS_NO_MEMORY);
3619 if(fsp->fake_file_handle) {
3621 * This is actually for the QUOTA_FAKE_FILE --metze
3624 /* We know this name is ok, it's already passed the checks. */
3626 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3628 * This is actually a QFILEINFO on a directory
3629 * handle (returned from an NT SMB). NT5.0 seems
3630 * to do this call. JRA.
3633 if (INFO_LEVEL_IS_UNIX(info_level)) {
3634 /* Always do lstat for UNIX calls. */
3635 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3636 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3637 reply_unixerror(req,ERRDOS,ERRbadpath);
3640 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3641 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3642 reply_unixerror(req, ERRDOS, ERRbadpath);
3646 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3647 delete_pending = get_delete_on_close_flag(fileid);
3650 * Original code - this is an open file.
3652 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3656 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3657 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3658 reply_unixerror(req, ERRDOS, ERRbadfid);
3661 pos = fsp->fh->position_information;
3662 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3663 delete_pending = get_delete_on_close_flag(fileid);
3664 access_mask = fsp->access_mask;
3668 NTSTATUS status = NT_STATUS_OK;
3671 if (total_params < 7) {
3672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3676 info_level = SVAL(params,0);
3678 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3680 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3681 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3685 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3687 STR_TERMINATE, &status);
3688 if (!NT_STATUS_IS_OK(status)) {
3689 reply_nterror(req, status);
3693 status = resolve_dfspath(ctx,
3695 req->flags2 & FLAGS2_DFS_PATHNAMES,
3698 if (!NT_STATUS_IS_OK(status)) {
3699 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3700 reply_botherror(req,
3701 NT_STATUS_PATH_NOT_COVERED,
3702 ERRSRV, ERRbadpath);
3704 reply_nterror(req, status);
3708 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3709 if (!NT_STATUS_IS_OK(status)) {
3710 reply_nterror(req, status);
3713 status = check_name(conn, fname);
3714 if (!NT_STATUS_IS_OK(status)) {
3715 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3716 reply_nterror(req, status);
3720 if (INFO_LEVEL_IS_UNIX(info_level)) {
3721 /* Always do lstat for UNIX calls. */
3722 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3723 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3724 reply_unixerror(req, ERRDOS, ERRbadpath);
3727 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3728 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3729 reply_unixerror(req, ERRDOS, ERRbadpath);
3733 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3734 delete_pending = get_delete_on_close_flag(fileid);
3735 if (delete_pending) {
3736 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3741 nlink = sbuf.st_nlink;
3743 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3744 /* NTFS does not seem to count ".." */
3748 if ((nlink > 0) && delete_pending) {
3752 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3753 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3757 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3758 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3760 p = strrchr_m(fname,'/');
3766 mode = dos_mode(conn,fname,&sbuf);
3768 mode = FILE_ATTRIBUTE_NORMAL;
3770 fullpathname = fname;
3772 file_size = get_file_size(sbuf);
3774 /* Pull out any data sent here before we realloc. */
3775 switch (info_level) {
3776 case SMB_INFO_QUERY_EAS_FROM_LIST:
3778 /* Pull any EA list from the data portion. */
3781 if (total_data < 4) {
3783 req, NT_STATUS_INVALID_PARAMETER);
3786 ea_size = IVAL(pdata,0);
3788 if (total_data > 0 && ea_size != total_data) {
3789 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3790 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3792 req, NT_STATUS_INVALID_PARAMETER);
3796 if (!lp_ea_support(SNUM(conn))) {
3797 reply_doserror(req, ERRDOS,
3798 ERReasnotsupported);
3802 /* Pull out the list of names. */
3803 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3806 req, NT_STATUS_INVALID_PARAMETER);
3812 case SMB_QUERY_POSIX_LOCK:
3814 if (fsp == NULL || fsp->fh->fd == -1) {
3815 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3819 if (total_data != POSIX_LOCK_DATA_SIZE) {
3821 req, NT_STATUS_INVALID_PARAMETER);
3825 /* Copy the lock range data. */
3826 lock_data = (char *)TALLOC_MEMDUP(
3827 ctx, pdata, total_data);
3829 reply_nterror(req, NT_STATUS_NO_MEMORY);
3837 *pparams = (char *)SMB_REALLOC(*pparams,2);
3838 if (*pparams == NULL) {
3839 reply_nterror(req, NT_STATUS_NO_MEMORY);
3844 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3845 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3846 if (*ppdata == NULL ) {
3847 reply_nterror(req, NT_STATUS_NO_MEMORY);
3852 dend = dstart + data_size - 1;
3854 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3855 mtime_ts = get_mtimespec(&sbuf);
3856 atime_ts = get_atimespec(&sbuf);
3858 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3861 if (!null_timespec(fsp->pending_modtime)) {
3862 /* the pending modtime overrides the current modtime */
3863 mtime_ts = fsp->pending_modtime;
3867 /* Do we have this path open ? */
3868 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3869 fsp1 = file_find_di_first(fileid);
3870 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3871 /* the pending modtime overrides the current modtime */
3872 mtime_ts = fsp1->pending_modtime;
3874 if (fsp1 && fsp1->initial_allocation_size) {
3875 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3879 if (lp_dos_filetime_resolution(SNUM(conn))) {
3880 dos_filetime_timespec(&create_time_ts);
3881 dos_filetime_timespec(&mtime_ts);
3882 dos_filetime_timespec(&atime_ts);
3885 create_time = convert_timespec_to_time_t(create_time_ts);
3886 mtime = convert_timespec_to_time_t(mtime_ts);
3887 atime = convert_timespec_to_time_t(atime_ts);
3889 /* NT expects the name to be in an exact form of the *full*
3890 filename. See the trans2 torture test */
3891 if (ISDOT(base_name)) {
3892 dos_fname = talloc_strdup(ctx, "\\");
3894 reply_nterror(req, NT_STATUS_NO_MEMORY);
3898 dos_fname = talloc_asprintf(ctx,
3902 reply_nterror(req, NT_STATUS_NO_MEMORY);
3905 string_replace(dos_fname, '/', '\\');
3908 switch (info_level) {
3909 case SMB_INFO_STANDARD:
3910 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3912 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3913 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3914 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3915 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3916 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3917 SSVAL(pdata,l1_attrFile,mode);
3920 case SMB_INFO_QUERY_EA_SIZE:
3922 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3923 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3925 srv_put_dos_date2(pdata,0,create_time);
3926 srv_put_dos_date2(pdata,4,atime);
3927 srv_put_dos_date2(pdata,8,mtime); /* write time */
3928 SIVAL(pdata,12,(uint32)file_size);
3929 SIVAL(pdata,16,(uint32)allocation_size);
3930 SSVAL(pdata,20,mode);
3931 SIVAL(pdata,22,ea_size);
3935 case SMB_INFO_IS_NAME_VALID:
3936 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3937 if (tran_call == TRANSACT2_QFILEINFO) {
3938 /* os/2 needs this ? really ?*/
3939 reply_doserror(req, ERRDOS, ERRbadfunc);
3946 case SMB_INFO_QUERY_EAS_FROM_LIST:
3948 size_t total_ea_len = 0;
3949 struct ea_list *ea_file_list = NULL;
3951 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3953 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3954 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3956 if (!ea_list || (total_ea_len > data_size)) {
3958 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3962 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3966 case SMB_INFO_QUERY_ALL_EAS:
3968 /* We have data_size bytes to put EA's into. */
3969 size_t total_ea_len = 0;
3971 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3973 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3974 if (!ea_list || (total_ea_len > data_size)) {
3976 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3980 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3984 case SMB_FILE_BASIC_INFORMATION:
3985 case SMB_QUERY_FILE_BASIC_INFO:
3987 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3988 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3989 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3991 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3995 put_long_date_timespec(pdata,create_time_ts);
3996 put_long_date_timespec(pdata+8,atime_ts);
3997 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3998 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3999 SIVAL(pdata,32,mode);
4001 DEBUG(5,("SMB_QFBI - "));
4002 DEBUG(5,("create: %s ", ctime(&create_time)));
4003 DEBUG(5,("access: %s ", ctime(&atime)));
4004 DEBUG(5,("write: %s ", ctime(&mtime)));
4005 DEBUG(5,("change: %s ", ctime(&mtime)));
4006 DEBUG(5,("mode: %x\n", mode));
4009 case SMB_FILE_STANDARD_INFORMATION:
4010 case SMB_QUERY_FILE_STANDARD_INFO:
4012 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4014 SOFF_T(pdata,0,allocation_size);
4015 SOFF_T(pdata,8,file_size);
4016 SIVAL(pdata,16,nlink);
4017 SCVAL(pdata,20,delete_pending?1:0);
4018 SCVAL(pdata,21,(mode&aDIR)?1:0);
4019 SSVAL(pdata,22,0); /* Padding. */
4022 case SMB_FILE_EA_INFORMATION:
4023 case SMB_QUERY_FILE_EA_INFO:
4025 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4026 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4028 SIVAL(pdata,0,ea_size);
4032 /* Get the 8.3 name - used if NT SMB was negotiated. */
4033 case SMB_QUERY_FILE_ALT_NAME_INFO:
4034 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4036 char mangled_name[13];
4037 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4038 if (!name_to_8_3(base_name,mangled_name,
4039 True,conn->params)) {
4042 NT_STATUS_NO_MEMORY);
4044 len = srvstr_push(dstart, req->flags2,
4045 pdata+4, mangled_name,
4046 PTR_DIFF(dend, pdata+4),
4048 data_size = 4 + len;
4053 case SMB_QUERY_FILE_NAME_INFO:
4055 this must be *exactly* right for ACLs on mapped drives to work
4057 len = srvstr_push(dstart, req->flags2,
4059 PTR_DIFF(dend, pdata+4),
4061 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4062 data_size = 4 + len;
4066 case SMB_FILE_ALLOCATION_INFORMATION:
4067 case SMB_QUERY_FILE_ALLOCATION_INFO:
4068 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4070 SOFF_T(pdata,0,allocation_size);
4073 case SMB_FILE_END_OF_FILE_INFORMATION:
4074 case SMB_QUERY_FILE_END_OF_FILEINFO:
4075 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4077 SOFF_T(pdata,0,file_size);
4080 case SMB_QUERY_FILE_ALL_INFO:
4081 case SMB_FILE_ALL_INFORMATION:
4083 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4084 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4085 put_long_date_timespec(pdata,create_time_ts);
4086 put_long_date_timespec(pdata+8,atime_ts);
4087 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4088 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4089 SIVAL(pdata,32,mode);
4090 SIVAL(pdata,36,0); /* padding. */
4092 SOFF_T(pdata,0,allocation_size);
4093 SOFF_T(pdata,8,file_size);
4094 SIVAL(pdata,16,nlink);
4095 SCVAL(pdata,20,delete_pending);
4096 SCVAL(pdata,21,(mode&aDIR)?1:0);
4099 SIVAL(pdata,0,ea_size);
4100 pdata += 4; /* EA info */
4101 len = srvstr_push(dstart, req->flags2,
4103 PTR_DIFF(dend, pdata+4),
4107 data_size = PTR_DIFF(pdata,(*ppdata));
4110 case SMB_FILE_INTERNAL_INFORMATION:
4111 /* This should be an index number - looks like
4114 I think this causes us to fail the IFSKIT
4115 BasicFileInformationTest. -tpot */
4117 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4118 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4119 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4123 case SMB_FILE_ACCESS_INFORMATION:
4124 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4125 SIVAL(pdata,0,access_mask);
4129 case SMB_FILE_NAME_INFORMATION:
4130 /* Pathname with leading '\'. */
4133 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4134 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4135 SIVAL(pdata,0,byte_len);
4136 data_size = 4 + byte_len;
4140 case SMB_FILE_DISPOSITION_INFORMATION:
4141 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4143 SCVAL(pdata,0,delete_pending);
4146 case SMB_FILE_POSITION_INFORMATION:
4147 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4149 SOFF_T(pdata,0,pos);
4152 case SMB_FILE_MODE_INFORMATION:
4153 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4154 SIVAL(pdata,0,mode);
4158 case SMB_FILE_ALIGNMENT_INFORMATION:
4159 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4160 SIVAL(pdata,0,0); /* No alignment needed. */
4166 * NT4 server just returns "invalid query" to this - if we try to answer
4167 * it then NTws gets a BSOD! (tridge).
4168 * W2K seems to want this. JRA.
4170 case SMB_QUERY_FILE_STREAM_INFO:
4172 case SMB_FILE_STREAM_INFORMATION:
4173 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4177 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4178 SIVAL(pdata,0,0); /* ??? */
4179 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4180 SOFF_T(pdata,8,file_size);
4181 SOFF_T(pdata,16,allocation_size);
4182 data_size = 24 + byte_len;
4186 case SMB_QUERY_COMPRESSION_INFO:
4187 case SMB_FILE_COMPRESSION_INFORMATION:
4188 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4189 SOFF_T(pdata,0,file_size);
4190 SIVAL(pdata,8,0); /* ??? */
4191 SIVAL(pdata,12,0); /* ??? */
4195 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4196 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4197 put_long_date_timespec(pdata,create_time_ts);
4198 put_long_date_timespec(pdata+8,atime_ts);
4199 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4200 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4201 SOFF_T(pdata,32,allocation_size);
4202 SOFF_T(pdata,40,file_size);
4203 SIVAL(pdata,48,mode);
4204 SIVAL(pdata,52,0); /* ??? */
4208 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4209 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4210 SIVAL(pdata,0,mode);
4216 * CIFS UNIX Extensions.
4219 case SMB_QUERY_FILE_UNIX_BASIC:
4221 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4222 data_size = PTR_DIFF(pdata,(*ppdata));
4226 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4228 for (i=0; i<100; i++)
4229 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4235 case SMB_QUERY_FILE_UNIX_INFO2:
4237 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4238 data_size = PTR_DIFF(pdata,(*ppdata));
4242 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4244 for (i=0; i<100; i++)
4245 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4251 case SMB_QUERY_FILE_UNIX_LINK:
4253 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4256 reply_nterror(req, NT_STATUS_NO_MEMORY);
4260 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4262 if(!S_ISLNK(sbuf.st_mode)) {
4263 reply_unixerror(req, ERRSRV,
4268 reply_unixerror(req, ERRDOS, ERRbadlink);
4271 len = SMB_VFS_READLINK(conn,fullpathname,
4274 reply_unixerror(req, ERRDOS,
4279 len = srvstr_push(dstart, req->flags2,
4281 PTR_DIFF(dend, pdata),
4284 data_size = PTR_DIFF(pdata,(*ppdata));
4289 #if defined(HAVE_POSIX_ACLS)
4290 case SMB_QUERY_POSIX_ACL:
4292 SMB_ACL_T file_acl = NULL;
4293 SMB_ACL_T def_acl = NULL;
4294 uint16 num_file_acls = 0;
4295 uint16 num_def_acls = 0;
4297 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4298 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4300 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4303 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4304 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4308 NT_STATUS_NOT_IMPLEMENTED);
4312 if (S_ISDIR(sbuf.st_mode)) {
4313 if (fsp && fsp->is_directory) {
4314 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4316 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4318 def_acl = free_empty_sys_acl(conn, def_acl);
4321 num_file_acls = count_acl_entries(conn, file_acl);
4322 num_def_acls = count_acl_entries(conn, def_acl);
4324 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4325 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4327 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4328 SMB_POSIX_ACL_HEADER_SIZE) ));
4330 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4333 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4337 NT_STATUS_BUFFER_TOO_SMALL);
4341 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4342 SSVAL(pdata,2,num_file_acls);
4343 SSVAL(pdata,4,num_def_acls);
4344 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4346 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4349 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4352 req, NT_STATUS_INTERNAL_ERROR);
4355 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4357 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4360 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4364 NT_STATUS_INTERNAL_ERROR);
4369 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4372 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4374 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4380 case SMB_QUERY_POSIX_LOCK:
4382 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4384 SMB_BIG_UINT offset;
4386 enum brl_type lock_type;
4388 if (total_data != POSIX_LOCK_DATA_SIZE) {
4390 req, NT_STATUS_INVALID_PARAMETER);
4394 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4395 case POSIX_LOCK_TYPE_READ:
4396 lock_type = READ_LOCK;
4398 case POSIX_LOCK_TYPE_WRITE:
4399 lock_type = WRITE_LOCK;
4401 case POSIX_LOCK_TYPE_UNLOCK:
4403 /* There's no point in asking for an unlock... */
4406 NT_STATUS_INVALID_PARAMETER);
4410 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4411 #if defined(HAVE_LONGLONG)
4412 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4413 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4414 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4415 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4416 #else /* HAVE_LONGLONG */
4417 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4418 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4419 #endif /* HAVE_LONGLONG */
4421 status = query_lock(fsp,
4428 if (ERROR_WAS_LOCK_DENIED(status)) {
4429 /* Here we need to report who has it locked... */
4430 data_size = POSIX_LOCK_DATA_SIZE;
4432 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4433 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4434 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4435 #if defined(HAVE_LONGLONG)
4436 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4437 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4438 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4439 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4440 #else /* HAVE_LONGLONG */
4441 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4442 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4443 #endif /* HAVE_LONGLONG */
4445 } else if (NT_STATUS_IS_OK(status)) {
4446 /* For success we just return a copy of what we sent
4447 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4448 data_size = POSIX_LOCK_DATA_SIZE;
4449 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4450 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4452 reply_nterror(req, status);
4459 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4463 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4469 /****************************************************************************
4470 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4472 ****************************************************************************/
4474 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4475 connection_struct *conn,
4476 const char *oldname_in,
4477 const char *newname_in)
4479 SMB_STRUCT_STAT sbuf1, sbuf2;
4480 char *last_component_oldname = NULL;
4481 char *last_component_newname = NULL;
4482 char *oldname = NULL;
4483 char *newname = NULL;
4484 NTSTATUS status = NT_STATUS_OK;
4489 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4490 &last_component_oldname, &sbuf1);
4491 if (!NT_STATUS_IS_OK(status)) {
4495 status = check_name(conn, oldname);
4496 if (!NT_STATUS_IS_OK(status)) {
4500 /* source must already exist. */
4501 if (!VALID_STAT(sbuf1)) {
4502 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4505 status = unix_convert(ctx, conn, newname_in, False, &newname,
4506 &last_component_newname, &sbuf2);
4507 if (!NT_STATUS_IS_OK(status)) {
4511 status = check_name(conn, newname);
4512 if (!NT_STATUS_IS_OK(status)) {
4516 /* Disallow if newname already exists. */
4517 if (VALID_STAT(sbuf2)) {
4518 return NT_STATUS_OBJECT_NAME_COLLISION;
4521 /* No links from a directory. */
4522 if (S_ISDIR(sbuf1.st_mode)) {
4523 return NT_STATUS_FILE_IS_A_DIRECTORY;
4526 /* Ensure this is within the share. */
4527 status = check_reduced_name(conn, oldname);
4528 if (!NT_STATUS_IS_OK(status)) {
4532 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4534 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4535 status = map_nt_error_from_unix(errno);
4536 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4537 nt_errstr(status), newname, oldname));
4543 /****************************************************************************
4544 Deal with setting the time from any of the setfilepathinfo functions.
4545 ****************************************************************************/
4547 static NTSTATUS smb_set_file_time(connection_struct *conn,
4550 const SMB_STRUCT_STAT *psbuf,
4551 struct timespec ts[2],
4552 bool setting_write_time)
4555 FILE_NOTIFY_CHANGE_LAST_ACCESS
4556 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4558 if (!VALID_STAT(*psbuf)) {
4559 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4562 /* get some defaults (no modifications) if any info is zero or -1. */
4563 if (null_timespec(ts[0])) {
4564 ts[0] = get_atimespec(psbuf);
4565 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4568 if (null_timespec(ts[1])) {
4569 ts[1] = get_mtimespec(psbuf);
4570 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4573 if (!setting_write_time) {
4574 /* ts[1] comes from change time, not write time. */
4575 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4578 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4579 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4582 * Try and set the times of this file if
4583 * they are different from the current values.
4587 struct timespec mts = get_mtimespec(psbuf);
4588 struct timespec ats = get_atimespec(psbuf);
4589 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4590 return NT_STATUS_OK;
4596 * This was a setfileinfo on an open file.
4597 * NT does this a lot. We also need to
4598 * set the time here, as it can be read by
4599 * FindFirst/FindNext and with the patch for bug #2045
4600 * in smbd/fileio.c it ensures that this timestamp is
4601 * kept sticky even after a write. We save the request
4602 * away and will set it on file close and after a write. JRA.
4605 if (!null_timespec(ts[1])) {
4606 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4607 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4608 fsp_set_pending_modtime(fsp, ts[1]);
4612 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4614 if(file_ntimes(conn, fname, ts)!=0) {
4615 return map_nt_error_from_unix(errno);
4617 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4619 return NT_STATUS_OK;
4622 /****************************************************************************
4623 Deal with setting the dosmode from any of the setfilepathinfo functions.
4624 ****************************************************************************/
4626 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4628 SMB_STRUCT_STAT *psbuf,
4631 if (!VALID_STAT(*psbuf)) {
4632 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4636 if (S_ISDIR(psbuf->st_mode)) {
4643 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4645 /* check the mode isn't different, before changing it */
4646 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4648 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4649 fname, (unsigned int)dosmode ));
4651 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4652 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4653 fname, strerror(errno)));
4654 return map_nt_error_from_unix(errno);
4657 return NT_STATUS_OK;
4660 /****************************************************************************
4661 Deal with setting the size from any of the setfilepathinfo functions.
4662 ****************************************************************************/
4664 static NTSTATUS smb_set_file_size(connection_struct *conn,
4665 struct smb_request *req,
4668 SMB_STRUCT_STAT *psbuf,
4671 NTSTATUS status = NT_STATUS_OK;
4672 files_struct *new_fsp = NULL;
4674 if (!VALID_STAT(*psbuf)) {
4675 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4678 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4680 if (size == get_file_size(*psbuf)) {
4681 return NT_STATUS_OK;
4684 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4685 fname, (double)size ));
4687 if (fsp && fsp->fh->fd != -1) {
4688 /* Handle based call. */
4689 if (vfs_set_filelen(fsp, size) == -1) {
4690 return map_nt_error_from_unix(errno);
4692 return NT_STATUS_OK;
4695 status = open_file_ntcreate(conn, req, fname, psbuf,
4697 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4700 FILE_ATTRIBUTE_NORMAL,
4701 FORCE_OPLOCK_BREAK_TO_NONE,
4704 if (!NT_STATUS_IS_OK(status)) {
4705 /* NB. We check for open_was_deferred in the caller. */
4709 if (vfs_set_filelen(new_fsp, size) == -1) {
4710 status = map_nt_error_from_unix(errno);
4711 close_file(new_fsp,NORMAL_CLOSE);
4715 close_file(new_fsp,NORMAL_CLOSE);
4716 return NT_STATUS_OK;
4719 /****************************************************************************
4720 Deal with SMB_INFO_SET_EA.
4721 ****************************************************************************/
4723 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4729 struct ea_list *ea_list = NULL;
4730 TALLOC_CTX *ctx = NULL;
4731 NTSTATUS status = NT_STATUS_OK;
4733 if (total_data < 10) {
4735 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4736 length. They seem to have no effect. Bug #3212. JRA */
4738 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4739 /* We're done. We only get EA info in this call. */
4740 return NT_STATUS_OK;
4743 return NT_STATUS_INVALID_PARAMETER;
4746 if (IVAL(pdata,0) > total_data) {
4747 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4748 IVAL(pdata,0), (unsigned int)total_data));
4749 return NT_STATUS_INVALID_PARAMETER;
4753 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4755 return NT_STATUS_INVALID_PARAMETER;
4757 status = set_ea(conn, fsp, fname, ea_list);
4762 /****************************************************************************
4763 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4764 ****************************************************************************/
4766 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4771 SMB_STRUCT_STAT *psbuf)
4773 NTSTATUS status = NT_STATUS_OK;
4774 bool delete_on_close;
4777 if (total_data < 1) {
4778 return NT_STATUS_INVALID_PARAMETER;
4782 return NT_STATUS_INVALID_HANDLE;
4785 delete_on_close = (CVAL(pdata,0) ? True : False);
4786 dosmode = dos_mode(conn, fname, psbuf);
4788 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4789 "delete_on_close = %u\n",
4791 (unsigned int)dosmode,
4792 (unsigned int)delete_on_close ));
4794 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4796 if (!NT_STATUS_IS_OK(status)) {
4800 /* The set is across all open files on this dev/inode pair. */
4801 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4802 return NT_STATUS_ACCESS_DENIED;
4804 return NT_STATUS_OK;
4807 /****************************************************************************
4808 Deal with SMB_FILE_POSITION_INFORMATION.
4809 ****************************************************************************/
4811 static NTSTATUS smb_file_position_information(connection_struct *conn,
4816 SMB_BIG_UINT position_information;
4818 if (total_data < 8) {
4819 return NT_STATUS_INVALID_PARAMETER;
4823 /* Ignore on pathname based set. */
4824 return NT_STATUS_OK;
4827 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4828 #ifdef LARGE_SMB_OFF_T
4829 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4830 #else /* LARGE_SMB_OFF_T */
4831 if (IVAL(pdata,4) != 0) {
4832 /* more than 32 bits? */
4833 return NT_STATUS_INVALID_PARAMETER;
4835 #endif /* LARGE_SMB_OFF_T */
4837 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4838 fsp->fsp_name, (double)position_information ));
4839 fsp->fh->position_information = position_information;
4840 return NT_STATUS_OK;
4843 /****************************************************************************
4844 Deal with SMB_FILE_MODE_INFORMATION.
4845 ****************************************************************************/
4847 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4853 if (total_data < 4) {
4854 return NT_STATUS_INVALID_PARAMETER;
4856 mode = IVAL(pdata,0);
4857 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4858 return NT_STATUS_INVALID_PARAMETER;
4860 return NT_STATUS_OK;
4863 /****************************************************************************
4864 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4865 ****************************************************************************/
4867 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4868 struct smb_request *req,
4873 char *link_target = NULL;
4874 const char *newname = fname;
4875 NTSTATUS status = NT_STATUS_OK;
4876 TALLOC_CTX *ctx = talloc_tos();
4878 /* Set a symbolic link. */
4879 /* Don't allow this if follow links is false. */
4881 if (total_data == 0) {
4882 return NT_STATUS_INVALID_PARAMETER;
4885 if (!lp_symlinks(SNUM(conn))) {
4886 return NT_STATUS_ACCESS_DENIED;
4889 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
4890 total_data, STR_TERMINATE);
4893 return NT_STATUS_INVALID_PARAMETER;
4896 /* !widelinks forces the target path to be within the share. */
4897 /* This means we can interpret the target as a pathname. */
4898 if (!lp_widelinks(SNUM(conn))) {
4899 char *rel_name = NULL;
4900 char *last_dirp = NULL;
4902 if (*link_target == '/') {
4903 /* No absolute paths allowed. */
4904 return NT_STATUS_ACCESS_DENIED;
4906 rel_name = talloc_strdup(ctx,newname);
4908 return NT_STATUS_NO_MEMORY;
4910 last_dirp = strrchr_m(rel_name, '/');
4912 last_dirp[1] = '\0';
4914 rel_name = talloc_strdup(ctx,"./");
4916 return NT_STATUS_NO_MEMORY;
4919 rel_name = talloc_asprintf_append(rel_name,
4923 return NT_STATUS_NO_MEMORY;
4926 status = check_name(conn, rel_name);
4927 if (!NT_STATUS_IS_OK(status)) {
4932 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4933 newname, link_target ));
4935 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4936 return map_nt_error_from_unix(errno);
4939 return NT_STATUS_OK;
4942 /****************************************************************************
4943 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4944 ****************************************************************************/
4946 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4947 struct smb_request *req,
4948 const char *pdata, int total_data,
4951 char *oldname = NULL;
4952 TALLOC_CTX *ctx = talloc_tos();
4953 NTSTATUS status = NT_STATUS_OK;
4955 /* Set a hard link. */
4956 if (total_data == 0) {
4957 return NT_STATUS_INVALID_PARAMETER;
4960 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
4961 total_data, STR_TERMINATE, &status);
4962 if (!NT_STATUS_IS_OK(status)) {
4966 status = resolve_dfspath(ctx, conn,
4967 req->flags2 & FLAGS2_DFS_PATHNAMES,
4970 if (!NT_STATUS_IS_OK(status)) {
4974 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4977 return hardlink_internals(ctx, conn, oldname, fname);
4980 /****************************************************************************
4981 Deal with SMB_FILE_RENAME_INFORMATION.
4982 ****************************************************************************/
4984 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4985 struct smb_request *req,
4994 char *newname = NULL;
4995 char *base_name = NULL;
4996 bool dest_has_wcard = False;
4997 NTSTATUS status = NT_STATUS_OK;
4999 TALLOC_CTX *ctx = talloc_tos();
5001 if (total_data < 13) {
5002 return NT_STATUS_INVALID_PARAMETER;
5005 overwrite = (CVAL(pdata,0) ? True : False);
5006 root_fid = IVAL(pdata,4);
5007 len = IVAL(pdata,8);
5009 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5010 return NT_STATUS_INVALID_PARAMETER;
5013 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5016 if (!NT_STATUS_IS_OK(status)) {
5020 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5023 status = resolve_dfspath_wcard(ctx, conn,
5024 req->flags2 & FLAGS2_DFS_PATHNAMES,
5028 if (!NT_STATUS_IS_OK(status)) {
5032 /* Check the new name has no '/' characters. */
5033 if (strchr_m(newname, '/')) {
5034 return NT_STATUS_NOT_SUPPORTED;
5037 /* Create the base directory. */
5038 base_name = talloc_strdup(ctx, fname);
5040 return NT_STATUS_NO_MEMORY;
5042 p = strrchr_m(base_name, '/');
5046 base_name = talloc_strdup(ctx, "./");
5048 return NT_STATUS_NO_MEMORY;
5051 /* Append the new name. */
5052 base_name = talloc_asprintf_append(base_name,
5056 return NT_STATUS_NO_MEMORY;
5060 SMB_STRUCT_STAT sbuf;
5061 char *newname_last_component = NULL;
5065 status = unix_convert(ctx, conn, newname, False,
5067 &newname_last_component,
5070 /* If an error we expect this to be
5071 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5073 if (!NT_STATUS_IS_OK(status)
5074 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5079 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5080 fsp->fnum, fsp->fsp_name, base_name ));
5081 status = rename_internals_fsp(conn, fsp, base_name,
5082 newname_last_component, 0,
5085 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5086 fname, base_name ));
5087 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5088 overwrite, False, dest_has_wcard);
5094 /****************************************************************************
5095 Deal with SMB_SET_POSIX_ACL.
5096 ****************************************************************************/
5098 #if defined(HAVE_POSIX_ACLS)
5099 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5104 SMB_STRUCT_STAT *psbuf)
5106 uint16 posix_acl_version;
5107 uint16 num_file_acls;
5108 uint16 num_def_acls;
5109 bool valid_file_acls = True;
5110 bool valid_def_acls = True;
5112 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5113 return NT_STATUS_INVALID_PARAMETER;
5115 posix_acl_version = SVAL(pdata,0);
5116 num_file_acls = SVAL(pdata,2);
5117 num_def_acls = SVAL(pdata,4);
5119 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5120 valid_file_acls = False;
5124 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5125 valid_def_acls = False;
5129 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5130 return NT_STATUS_INVALID_PARAMETER;
5133 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5134 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5135 return NT_STATUS_INVALID_PARAMETER;
5138 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5139 fname ? fname : fsp->fsp_name,
5140 (unsigned int)num_file_acls,
5141 (unsigned int)num_def_acls));
5143 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5144 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5145 return map_nt_error_from_unix(errno);
5148 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5149 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5150 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5151 return map_nt_error_from_unix(errno);
5153 return NT_STATUS_OK;
5157 /****************************************************************************
5158 Deal with SMB_SET_POSIX_LOCK.
5159 ****************************************************************************/
5161 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5162 const struct smb_request *req,
5168 SMB_BIG_UINT offset;
5170 bool blocking_lock = False;
5171 enum brl_type lock_type;
5173 NTSTATUS status = NT_STATUS_OK;
5175 if (fsp == NULL || fsp->fh->fd == -1) {
5176 return NT_STATUS_INVALID_HANDLE;
5179 if (total_data != POSIX_LOCK_DATA_SIZE) {
5180 return NT_STATUS_INVALID_PARAMETER;
5183 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5184 case POSIX_LOCK_TYPE_READ:
5185 lock_type = READ_LOCK;
5187 case POSIX_LOCK_TYPE_WRITE:
5188 /* Return the right POSIX-mappable error code for files opened read-only. */
5189 if (!fsp->can_write) {
5190 return NT_STATUS_INVALID_HANDLE;
5192 lock_type = WRITE_LOCK;
5194 case POSIX_LOCK_TYPE_UNLOCK:
5195 lock_type = UNLOCK_LOCK;
5198 return NT_STATUS_INVALID_PARAMETER;
5201 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5202 blocking_lock = False;
5203 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5204 blocking_lock = True;
5206 return NT_STATUS_INVALID_PARAMETER;
5209 if (!lp_blocking_locks(SNUM(conn))) {
5210 blocking_lock = False;
5213 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5214 #if defined(HAVE_LONGLONG)
5215 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5216 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5217 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5218 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5219 #else /* HAVE_LONGLONG */
5220 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5221 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5222 #endif /* HAVE_LONGLONG */
5224 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5225 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5227 (unsigned int)lock_type,
5228 (unsigned int)lock_pid,
5232 if (lock_type == UNLOCK_LOCK) {
5233 status = do_unlock(smbd_messaging_context(),
5240 uint32 block_smbpid;
5242 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5253 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5255 * A blocking lock was requested. Package up
5256 * this smb into a queued request and push it
5257 * onto the blocking lock queue.
5259 if(push_blocking_lock_request(br_lck,
5262 -1, /* infinite timeout. */
5270 TALLOC_FREE(br_lck);
5274 TALLOC_FREE(br_lck);
5280 /****************************************************************************
5281 Deal with SMB_INFO_STANDARD.
5282 ****************************************************************************/
5284 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5289 const SMB_STRUCT_STAT *psbuf)
5291 struct timespec ts[2];
5293 if (total_data < 12) {
5294 return NT_STATUS_INVALID_PARAMETER;
5298 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5300 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5302 DEBUG(10,("smb_set_info_standard: file %s\n",
5303 fname ? fname : fsp->fsp_name ));
5305 return smb_set_file_time(conn,
5313 /****************************************************************************
5314 Deal with SMB_SET_FILE_BASIC_INFO.
5315 ****************************************************************************/
5317 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5322 SMB_STRUCT_STAT *psbuf)
5324 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5325 struct timespec write_time;
5326 struct timespec changed_time;
5328 struct timespec ts[2];
5329 NTSTATUS status = NT_STATUS_OK;
5330 bool setting_write_time = true;
5332 if (total_data < 36) {
5333 return NT_STATUS_INVALID_PARAMETER;
5336 /* Set the attributes */
5337 dosmode = IVAL(pdata,32);
5338 status = smb_set_file_dosmode(conn,
5342 if (!NT_STATUS_IS_OK(status)) {
5346 /* Ignore create time at offset pdata. */
5349 ts[0] = interpret_long_date(pdata+8);
5351 write_time = interpret_long_date(pdata+16);
5352 changed_time = interpret_long_date(pdata+24);
5355 ts[1] = timespec_min(&write_time, &changed_time);
5357 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5361 /* Prefer a defined time to an undefined one. */
5362 if (null_timespec(ts[1])) {
5363 if (null_timespec(write_time)) {
5364 ts[1] = changed_time;
5365 setting_write_time = false;
5371 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5372 fname ? fname : fsp->fsp_name ));
5374 return smb_set_file_time(conn,
5379 setting_write_time);
5382 /****************************************************************************
5383 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5384 ****************************************************************************/
5386 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5387 struct smb_request *req,
5392 SMB_STRUCT_STAT *psbuf)
5394 SMB_BIG_UINT allocation_size = 0;
5395 NTSTATUS status = NT_STATUS_OK;
5396 files_struct *new_fsp = NULL;
5398 if (!VALID_STAT(*psbuf)) {
5399 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5402 if (total_data < 8) {
5403 return NT_STATUS_INVALID_PARAMETER;
5406 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5407 #ifdef LARGE_SMB_OFF_T
5408 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5409 #else /* LARGE_SMB_OFF_T */
5410 if (IVAL(pdata,4) != 0) {
5411 /* more than 32 bits? */
5412 return NT_STATUS_INVALID_PARAMETER;
5414 #endif /* LARGE_SMB_OFF_T */
5416 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5417 fname, (double)allocation_size ));
5419 if (allocation_size) {
5420 allocation_size = smb_roundup(conn, allocation_size);
5423 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5424 fname, (double)allocation_size ));
5426 if (fsp && fsp->fh->fd != -1) {
5427 /* Open file handle. */
5428 /* Only change if needed. */
5429 if (allocation_size != get_file_size(*psbuf)) {
5430 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5431 return map_nt_error_from_unix(errno);
5434 /* But always update the time. */
5435 if (null_timespec(fsp->pending_modtime)) {
5437 * This is equivalent to a write. Ensure it's seen immediately
5438 * if there are no pending writes.
5440 set_filetime(fsp->conn, fsp->fsp_name,
5441 timespec_current());
5443 return NT_STATUS_OK;
5446 /* Pathname or stat or directory file. */
5448 status = open_file_ntcreate(conn, req, fname, psbuf,
5450 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5453 FILE_ATTRIBUTE_NORMAL,
5454 FORCE_OPLOCK_BREAK_TO_NONE,
5457 if (!NT_STATUS_IS_OK(status)) {
5458 /* NB. We check for open_was_deferred in the caller. */
5462 /* Only change if needed. */
5463 if (allocation_size != get_file_size(*psbuf)) {
5464 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5465 status = map_nt_error_from_unix(errno);
5466 close_file(new_fsp,NORMAL_CLOSE);
5471 /* Changing the allocation size should set the last mod time. */
5472 /* Don't need to call set_filetime as this will be flushed on
5475 fsp_set_pending_modtime(new_fsp, timespec_current());
5477 close_file(new_fsp,NORMAL_CLOSE);
5478 return NT_STATUS_OK;
5481 /****************************************************************************
5482 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5483 ****************************************************************************/
5485 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5486 struct smb_request *req,
5491 SMB_STRUCT_STAT *psbuf)
5495 if (total_data < 8) {
5496 return NT_STATUS_INVALID_PARAMETER;
5499 size = IVAL(pdata,0);
5500 #ifdef LARGE_SMB_OFF_T
5501 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5502 #else /* LARGE_SMB_OFF_T */
5503 if (IVAL(pdata,4) != 0) {
5504 /* more than 32 bits? */
5505 return NT_STATUS_INVALID_PARAMETER;
5507 #endif /* LARGE_SMB_OFF_T */
5508 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5509 "file %s to %.0f\n", fname, (double)size ));
5511 return smb_set_file_size(conn, req,
5518 /****************************************************************************
5519 Allow a UNIX info mknod.
5520 ****************************************************************************/
5522 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5526 SMB_STRUCT_STAT *psbuf)
5528 uint32 file_type = IVAL(pdata,56);
5529 #if defined(HAVE_MAKEDEV)
5530 uint32 dev_major = IVAL(pdata,60);
5531 uint32 dev_minor = IVAL(pdata,68);
5533 SMB_DEV_T dev = (SMB_DEV_T)0;
5534 uint32 raw_unixmode = IVAL(pdata,84);
5538 if (total_data < 100) {
5539 return NT_STATUS_INVALID_PARAMETER;
5542 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5543 if (!NT_STATUS_IS_OK(status)) {
5547 #if defined(HAVE_MAKEDEV)
5548 dev = makedev(dev_major, dev_minor);
5551 switch (file_type) {
5552 #if defined(S_IFIFO)
5553 case UNIX_TYPE_FIFO:
5554 unixmode |= S_IFIFO;
5557 #if defined(S_IFSOCK)
5558 case UNIX_TYPE_SOCKET:
5559 unixmode |= S_IFSOCK;
5562 #if defined(S_IFCHR)
5563 case UNIX_TYPE_CHARDEV:
5564 unixmode |= S_IFCHR;
5567 #if defined(S_IFBLK)
5568 case UNIX_TYPE_BLKDEV:
5569 unixmode |= S_IFBLK;
5573 return NT_STATUS_INVALID_PARAMETER;
5576 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5577 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5579 /* Ok - do the mknod. */
5580 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5581 return map_nt_error_from_unix(errno);
5584 /* If any of the other "set" calls fail we
5585 * don't want to end up with a half-constructed mknod.
5588 if (lp_inherit_perms(SNUM(conn))) {
5590 conn, parent_dirname(fname),
5594 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5595 status = map_nt_error_from_unix(errno);
5596 SMB_VFS_UNLINK(conn,fname);
5599 return NT_STATUS_OK;
5602 /****************************************************************************
5603 Deal with SMB_SET_FILE_UNIX_BASIC.
5604 ****************************************************************************/
5606 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5607 struct smb_request *req,
5612 SMB_STRUCT_STAT *psbuf)
5614 struct timespec ts[2];
5615 uint32 raw_unixmode;
5618 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5619 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5620 NTSTATUS status = NT_STATUS_OK;
5621 bool delete_on_fail = False;
5622 enum perm_type ptype;
5624 if (total_data < 100) {
5625 return NT_STATUS_INVALID_PARAMETER;
5628 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5629 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5630 size=IVAL(pdata,0); /* first 8 Bytes are size */
5631 #ifdef LARGE_SMB_OFF_T
5632 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5633 #else /* LARGE_SMB_OFF_T */
5634 if (IVAL(pdata,4) != 0) {
5635 /* more than 32 bits? */
5636 return NT_STATUS_INVALID_PARAMETER;
5638 #endif /* LARGE_SMB_OFF_T */
5641 ts[0] = interpret_long_date(pdata+24); /* access_time */
5642 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5643 set_owner = (uid_t)IVAL(pdata,40);
5644 set_grp = (gid_t)IVAL(pdata,48);
5645 raw_unixmode = IVAL(pdata,84);
5647 if (VALID_STAT(*psbuf)) {
5648 if (S_ISDIR(psbuf->st_mode)) {
5649 ptype = PERM_EXISTING_DIR;
5651 ptype = PERM_EXISTING_FILE;
5654 ptype = PERM_NEW_FILE;
5657 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5658 if (!NT_STATUS_IS_OK(status)) {
5662 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5663 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5664 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5666 if (!VALID_STAT(*psbuf)) {
5668 * The only valid use of this is to create character and block
5669 * devices, and named pipes. This is deprecated (IMHO) and
5670 * a new info level should be used for mknod. JRA.
5673 status = smb_unix_mknod(conn,
5678 if (!NT_STATUS_IS_OK(status)) {
5682 /* Ensure we don't try and change anything else. */
5683 raw_unixmode = SMB_MODE_NO_CHANGE;
5684 size = get_file_size(*psbuf);
5685 ts[0] = get_atimespec(psbuf);
5686 ts[1] = get_mtimespec(psbuf);
5688 * We continue here as we might want to change the
5691 delete_on_fail = True;
5695 /* Horrible backwards compatibility hack as an old server bug
5696 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5700 size = get_file_size(*psbuf);
5705 * Deal with the UNIX specific mode set.
5708 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5709 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5710 (unsigned int)unixmode, fname ));
5711 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5712 return map_nt_error_from_unix(errno);
5717 * Deal with the UNIX specific uid set.
5720 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5723 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5724 (unsigned int)set_owner, fname ));
5726 if (S_ISLNK(psbuf->st_mode)) {
5727 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5729 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5733 status = map_nt_error_from_unix(errno);
5734 if (delete_on_fail) {
5735 SMB_VFS_UNLINK(conn,fname);
5742 * Deal with the UNIX specific gid set.
5745 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5746 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5747 (unsigned int)set_owner, fname ));
5748 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5749 status = map_nt_error_from_unix(errno);
5750 if (delete_on_fail) {
5751 SMB_VFS_UNLINK(conn,fname);
5757 /* Deal with any size changes. */
5759 status = smb_set_file_size(conn, req,
5764 if (!NT_STATUS_IS_OK(status)) {
5768 /* Deal with any time changes. */
5770 return smb_set_file_time(conn,
5778 /****************************************************************************
5779 Deal with SMB_SET_FILE_UNIX_INFO2.
5780 ****************************************************************************/
5782 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5783 struct smb_request *req,
5788 SMB_STRUCT_STAT *psbuf)
5794 if (total_data < 116) {
5795 return NT_STATUS_INVALID_PARAMETER;
5798 /* Start by setting all the fields that are common between UNIX_BASIC
5801 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5803 if (!NT_STATUS_IS_OK(status)) {
5807 smb_fflags = IVAL(pdata, 108);
5808 smb_fmask = IVAL(pdata, 112);
5810 /* NB: We should only attempt to alter the file flags if the client
5811 * sends a non-zero mask.
5813 if (smb_fmask != 0) {
5814 int stat_fflags = 0;
5816 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5818 /* Client asked to alter a flag we don't understand. */
5819 return NT_STATUS_INVALID_PARAMETER;
5822 if (fsp && fsp->fh->fd != -1) {
5823 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5824 return NT_STATUS_NOT_SUPPORTED;
5826 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5827 return map_nt_error_from_unix(errno);
5832 /* XXX: need to add support for changing the create_time here. You
5833 * can do this for paths on Darwin with setattrlist(2). The right way
5834 * to hook this up is probably by extending the VFS utimes interface.
5837 return NT_STATUS_OK;
5840 /****************************************************************************
5841 Create a directory with POSIX semantics.
5842 ****************************************************************************/
5844 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5845 struct smb_request *req,
5849 SMB_STRUCT_STAT *psbuf,
5850 int *pdata_return_size)
5852 NTSTATUS status = NT_STATUS_OK;
5853 uint32 raw_unixmode = 0;
5854 uint32 mod_unixmode = 0;
5855 mode_t unixmode = (mode_t)0;
5856 files_struct *fsp = NULL;
5857 uint16 info_level_return = 0;
5859 char *pdata = *ppdata;
5861 if (total_data < 18) {
5862 return NT_STATUS_INVALID_PARAMETER;
5865 raw_unixmode = IVAL(pdata,8);
5866 /* Next 4 bytes are not yet defined. */
5868 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5869 if (!NT_STATUS_IS_OK(status)) {
5873 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5875 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5876 fname, (unsigned int)unixmode ));
5878 status = open_directory(conn, req,
5881 FILE_READ_ATTRIBUTES, /* Just a stat open */
5882 FILE_SHARE_NONE, /* Ignored for stat opens */
5889 if (NT_STATUS_IS_OK(status)) {
5890 close_file(fsp, NORMAL_CLOSE);
5893 info_level_return = SVAL(pdata,16);
5895 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5896 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5897 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5898 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5900 *pdata_return_size = 12;
5903 /* Realloc the data size */
5904 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5905 if (*ppdata == NULL) {
5906 *pdata_return_size = 0;
5907 return NT_STATUS_NO_MEMORY;
5911 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5912 SSVAL(pdata,2,0); /* No fnum. */
5913 SIVAL(pdata,4,info); /* Was directory created. */
5915 switch (info_level_return) {
5916 case SMB_QUERY_FILE_UNIX_BASIC:
5917 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5918 SSVAL(pdata,10,0); /* Padding. */
5919 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5921 case SMB_QUERY_FILE_UNIX_INFO2:
5922 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5923 SSVAL(pdata,10,0); /* Padding. */
5924 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5927 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5928 SSVAL(pdata,10,0); /* Padding. */
5935 /****************************************************************************
5936 Open/Create a file with POSIX semantics.
5937 ****************************************************************************/
5939 static NTSTATUS smb_posix_open(connection_struct *conn,
5940 struct smb_request *req,
5944 SMB_STRUCT_STAT *psbuf,
5945 int *pdata_return_size)
5947 bool extended_oplock_granted = False;
5948 char *pdata = *ppdata;
5950 uint32 wire_open_mode = 0;
5951 uint32 raw_unixmode = 0;
5952 uint32 mod_unixmode = 0;
5953 uint32 create_disp = 0;
5954 uint32 access_mask = 0;
5955 uint32 create_options = 0;
5956 NTSTATUS status = NT_STATUS_OK;
5957 mode_t unixmode = (mode_t)0;
5958 files_struct *fsp = NULL;
5959 int oplock_request = 0;
5961 uint16 info_level_return = 0;
5963 if (total_data < 18) {
5964 return NT_STATUS_INVALID_PARAMETER;
5967 flags = IVAL(pdata,0);
5968 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5969 if (oplock_request) {
5970 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5973 wire_open_mode = IVAL(pdata,4);
5975 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5976 return smb_posix_mkdir(conn, req,
5984 switch (wire_open_mode & SMB_ACCMODE) {
5986 access_mask = FILE_READ_DATA;
5989 access_mask = FILE_WRITE_DATA;
5992 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5995 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5996 (unsigned int)wire_open_mode ));
5997 return NT_STATUS_INVALID_PARAMETER;
6000 wire_open_mode &= ~SMB_ACCMODE;
6002 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6003 create_disp = FILE_CREATE;
6004 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6005 create_disp = FILE_OVERWRITE_IF;
6006 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6007 create_disp = FILE_OPEN_IF;
6009 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6010 (unsigned int)wire_open_mode ));
6011 return NT_STATUS_INVALID_PARAMETER;
6014 raw_unixmode = IVAL(pdata,8);
6015 /* Next 4 bytes are not yet defined. */
6017 status = unix_perms_from_wire(conn,
6020 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6023 if (!NT_STATUS_IS_OK(status)) {
6027 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6029 if (wire_open_mode & SMB_O_SYNC) {
6030 create_options |= FILE_WRITE_THROUGH;
6032 if (wire_open_mode & SMB_O_APPEND) {
6033 access_mask |= FILE_APPEND_DATA;
6035 if (wire_open_mode & SMB_O_DIRECT) {
6036 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6039 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6041 (unsigned int)wire_open_mode,
6042 (unsigned int)unixmode ));
6044 status = open_file_ntcreate(conn, req,
6048 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6050 0, /* no create options yet. */
6056 if (!NT_STATUS_IS_OK(status)) {
6060 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6061 extended_oplock_granted = True;
6064 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6065 extended_oplock_granted = True;
6068 info_level_return = SVAL(pdata,16);
6070 /* Allocate the correct return size. */
6072 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6073 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6074 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6075 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6077 *pdata_return_size = 12;
6080 /* Realloc the data size */
6081 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6082 if (*ppdata == NULL) {
6083 close_file(fsp,ERROR_CLOSE);
6084 *pdata_return_size = 0;
6085 return NT_STATUS_NO_MEMORY;
6089 if (extended_oplock_granted) {
6090 if (flags & REQUEST_BATCH_OPLOCK) {
6091 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6093 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6095 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6096 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6098 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6101 SSVAL(pdata,2,fsp->fnum);
6102 SIVAL(pdata,4,info); /* Was file created etc. */
6104 switch (info_level_return) {
6105 case SMB_QUERY_FILE_UNIX_BASIC:
6106 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6107 SSVAL(pdata,10,0); /* padding. */
6108 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6110 case SMB_QUERY_FILE_UNIX_INFO2:
6111 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6112 SSVAL(pdata,10,0); /* padding. */
6113 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6116 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6117 SSVAL(pdata,10,0); /* padding. */
6120 return NT_STATUS_OK;
6123 /****************************************************************************
6124 Delete a file with POSIX semantics.
6125 ****************************************************************************/
6127 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6128 struct smb_request *req,
6132 SMB_STRUCT_STAT *psbuf)
6134 NTSTATUS status = NT_STATUS_OK;
6135 files_struct *fsp = NULL;
6140 struct share_mode_lock *lck = NULL;
6142 if (total_data < 2) {
6143 return NT_STATUS_INVALID_PARAMETER;
6146 flags = SVAL(pdata,0);
6148 if (!VALID_STAT(*psbuf)) {
6149 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6152 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6153 !VALID_STAT_OF_DIR(*psbuf)) {
6154 return NT_STATUS_NOT_A_DIRECTORY;
6157 DEBUG(10,("smb_posix_unlink: %s %s\n",
6158 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6161 if (VALID_STAT_OF_DIR(*psbuf)) {
6162 status = open_directory(conn, req,
6166 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6169 FILE_FLAG_POSIX_SEMANTICS|0777,
6174 status = open_file_ntcreate(conn, req,
6178 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6181 FILE_FLAG_POSIX_SEMANTICS|0777,
6182 0, /* No oplock, but break existing ones. */
6187 if (!NT_STATUS_IS_OK(status)) {
6192 * Don't lie to client. If we can't really delete due to
6193 * non-POSIX opens return SHARING_VIOLATION.
6196 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
6198 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6199 "lock for file %s\n", fsp->fsp_name));
6200 close_file(fsp, NORMAL_CLOSE);
6201 return NT_STATUS_INVALID_PARAMETER;
6205 * See if others still have the file open. If this is the case, then
6206 * don't delete. If all opens are POSIX delete we can set the delete
6207 * on close disposition.
6209 for (i=0; i<lck->num_share_modes; i++) {
6210 struct share_mode_entry *e = &lck->share_modes[i];
6211 if (is_valid_share_mode_entry(e)) {
6212 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6215 /* Fail with sharing violation. */
6216 close_file(fsp, NORMAL_CLOSE);
6218 return NT_STATUS_SHARING_VIOLATION;
6223 * Set the delete on close.
6225 status = smb_set_file_disposition_info(conn,
6232 if (!NT_STATUS_IS_OK(status)) {
6233 close_file(fsp, NORMAL_CLOSE);
6238 return close_file(fsp, NORMAL_CLOSE);
6241 /****************************************************************************
6242 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6243 ****************************************************************************/
6245 static void call_trans2setfilepathinfo(connection_struct *conn,
6246 struct smb_request *req,
6247 unsigned int tran_call,
6248 char **pparams, int total_params,
6249 char **ppdata, int total_data,
6250 unsigned int max_data_bytes)
6252 char *params = *pparams;
6253 char *pdata = *ppdata;
6255 SMB_STRUCT_STAT sbuf;
6257 files_struct *fsp = NULL;
6258 NTSTATUS status = NT_STATUS_OK;
6259 int data_return_size = 0;
6260 TALLOC_CTX *ctx = talloc_tos();
6263 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6269 if (tran_call == TRANSACT2_SETFILEINFO) {
6270 if (total_params < 4) {
6271 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6275 fsp = file_fsp(SVAL(params,0));
6276 /* Basic check for non-null fsp. */
6277 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
6280 info_level = SVAL(params,2);
6282 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6284 reply_nterror(req, NT_STATUS_NO_MEMORY);
6288 if(fsp->is_directory || fsp->fh->fd == -1) {
6290 * This is actually a SETFILEINFO on a directory
6291 * handle (returned from an NT SMB). NT5.0 seems
6292 * to do this call. JRA.
6294 if (INFO_LEVEL_IS_UNIX(info_level)) {
6295 /* Always do lstat for UNIX calls. */
6296 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6297 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6298 reply_unixerror(req,ERRDOS,ERRbadpath);
6302 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6303 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6304 reply_unixerror(req,ERRDOS,ERRbadpath);
6308 } else if (fsp->print_file) {
6310 * Doing a DELETE_ON_CLOSE should cancel a print job.
6312 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6313 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6315 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6318 send_trans2_replies(conn, req, params, 2,
6323 reply_unixerror(req, ERRDOS, ERRbadpath);
6328 * Original code - this is an open file.
6330 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6334 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6335 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6336 reply_unixerror(req, ERRDOS, ERRbadfid);
6342 if (total_params < 7) {
6343 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6347 info_level = SVAL(params,0);
6348 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6349 total_params - 6, STR_TERMINATE,
6351 if (!NT_STATUS_IS_OK(status)) {
6352 reply_nterror(req, status);
6356 status = resolve_dfspath(ctx, conn,
6357 req->flags2 & FLAGS2_DFS_PATHNAMES,
6360 if (!NT_STATUS_IS_OK(status)) {
6361 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6362 reply_botherror(req,
6363 NT_STATUS_PATH_NOT_COVERED,
6364 ERRSRV, ERRbadpath);
6367 reply_nterror(req, status);
6371 status = unix_convert(ctx, conn, fname, False,
6372 &fname, NULL, &sbuf);
6373 if (!NT_STATUS_IS_OK(status)) {
6374 reply_nterror(req, status);
6378 status = check_name(conn, fname);
6379 if (!NT_STATUS_IS_OK(status)) {
6380 reply_nterror(req, status);
6384 if (INFO_LEVEL_IS_UNIX(info_level)) {
6386 * For CIFS UNIX extensions the target name may not exist.
6389 /* Always do lstat for UNIX calls. */
6390 SMB_VFS_LSTAT(conn,fname,&sbuf);
6392 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6393 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6394 reply_unixerror(req, ERRDOS, ERRbadpath);
6399 if (!CAN_WRITE(conn)) {
6400 reply_doserror(req, ERRSRV, ERRaccess);
6404 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6405 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6409 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6410 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6412 /* Realloc the parameter size */
6413 *pparams = (char *)SMB_REALLOC(*pparams,2);
6414 if (*pparams == NULL) {
6415 reply_nterror(req, NT_STATUS_NO_MEMORY);
6422 if (fsp && !null_timespec(fsp->pending_modtime)) {
6423 /* the pending modtime overrides the current modtime */
6424 set_mtimespec(&sbuf, fsp->pending_modtime);
6427 switch (info_level) {
6429 case SMB_INFO_STANDARD:
6431 status = smb_set_info_standard(conn,
6440 case SMB_INFO_SET_EA:
6442 status = smb_info_set_ea(conn,
6450 case SMB_SET_FILE_BASIC_INFO:
6451 case SMB_FILE_BASIC_INFORMATION:
6453 status = smb_set_file_basic_info(conn,
6462 case SMB_FILE_ALLOCATION_INFORMATION:
6463 case SMB_SET_FILE_ALLOCATION_INFO:
6465 status = smb_set_file_allocation_info(conn, req,
6474 case SMB_FILE_END_OF_FILE_INFORMATION:
6475 case SMB_SET_FILE_END_OF_FILE_INFO:
6477 status = smb_set_file_end_of_file_info(conn, req,
6486 case SMB_FILE_DISPOSITION_INFORMATION:
6487 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6490 /* JRA - We used to just ignore this on a path ?
6491 * Shouldn't this be invalid level on a pathname
6494 if (tran_call != TRANSACT2_SETFILEINFO) {
6495 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6498 status = smb_set_file_disposition_info(conn,
6507 case SMB_FILE_POSITION_INFORMATION:
6509 status = smb_file_position_information(conn,
6516 /* From tridge Samba4 :
6517 * MODE_INFORMATION in setfileinfo (I have no
6518 * idea what "mode information" on a file is - it takes a value of 0,
6519 * 2, 4 or 6. What could it be?).
6522 case SMB_FILE_MODE_INFORMATION:
6524 status = smb_file_mode_information(conn,
6531 * CIFS UNIX extensions.
6534 case SMB_SET_FILE_UNIX_BASIC:
6536 status = smb_set_file_unix_basic(conn, req,
6545 case SMB_SET_FILE_UNIX_INFO2:
6547 status = smb_set_file_unix_info2(conn, req,
6556 case SMB_SET_FILE_UNIX_LINK:
6558 if (tran_call != TRANSACT2_SETPATHINFO) {
6559 /* We must have a pathname for this. */
6560 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6563 status = smb_set_file_unix_link(conn, req, pdata,
6568 case SMB_SET_FILE_UNIX_HLINK:
6570 if (tran_call != TRANSACT2_SETPATHINFO) {
6571 /* We must have a pathname for this. */
6572 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6575 status = smb_set_file_unix_hlink(conn, req,
6581 case SMB_FILE_RENAME_INFORMATION:
6583 status = smb_file_rename_information(conn, req,
6589 #if defined(HAVE_POSIX_ACLS)
6590 case SMB_SET_POSIX_ACL:
6592 status = smb_set_posix_acl(conn,
6602 case SMB_SET_POSIX_LOCK:
6604 if (tran_call != TRANSACT2_SETFILEINFO) {
6605 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6608 status = smb_set_posix_lock(conn, req,
6609 pdata, total_data, fsp);
6613 case SMB_POSIX_PATH_OPEN:
6615 if (tran_call != TRANSACT2_SETPATHINFO) {
6616 /* We must have a pathname for this. */
6617 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6621 status = smb_posix_open(conn, req,
6630 case SMB_POSIX_PATH_UNLINK:
6632 if (tran_call != TRANSACT2_SETPATHINFO) {
6633 /* We must have a pathname for this. */
6634 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6638 status = smb_posix_unlink(conn, req,
6647 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6652 if (!NT_STATUS_IS_OK(status)) {
6653 if (open_was_deferred(req->mid)) {
6654 /* We have re-scheduled this call. */
6657 if (blocking_lock_was_deferred(req->mid)) {
6658 /* We have re-scheduled this call. */
6661 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6662 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6663 ERRSRV, ERRbadpath);
6666 if (info_level == SMB_POSIX_PATH_OPEN) {
6667 reply_openerror(req, status);
6671 reply_nterror(req, status);
6676 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
6682 /****************************************************************************
6683 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6684 ****************************************************************************/
6686 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6687 char **pparams, int total_params,
6688 char **ppdata, int total_data,
6689 unsigned int max_data_bytes)
6691 char *params = *pparams;
6692 char *pdata = *ppdata;
6693 char *directory = NULL;
6694 SMB_STRUCT_STAT sbuf;
6695 NTSTATUS status = NT_STATUS_OK;
6696 struct ea_list *ea_list = NULL;
6697 TALLOC_CTX *ctx = talloc_tos();
6699 if (!CAN_WRITE(conn)) {
6700 reply_doserror(req, ERRSRV, ERRaccess);
6704 if (total_params < 5) {
6705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6709 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
6710 total_params - 4, STR_TERMINATE,
6712 if (!NT_STATUS_IS_OK(status)) {
6713 reply_nterror(req, status);
6717 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6719 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6720 if (!NT_STATUS_IS_OK(status)) {
6721 reply_nterror(req, status);
6725 status = check_name(conn, directory);
6726 if (!NT_STATUS_IS_OK(status)) {
6727 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6728 reply_nterror(req, status);
6732 /* Any data in this call is an EA list. */
6733 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6734 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6739 * OS/2 workplace shell seems to send SET_EA requests of "null"
6740 * length (4 bytes containing IVAL 4).
6741 * They seem to have no effect. Bug #3212. JRA.
6744 if (total_data != 4) {
6745 if (total_data < 10) {
6746 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6750 if (IVAL(pdata,0) > total_data) {
6751 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6752 IVAL(pdata,0), (unsigned int)total_data));
6753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6757 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6760 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6763 } else if (IVAL(pdata,0) != 4) {
6764 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6768 status = create_directory(conn, req, directory);
6770 if (!NT_STATUS_IS_OK(status)) {
6771 reply_nterror(req, status);
6775 /* Try and set any given EA. */
6777 status = set_ea(conn, NULL, directory, ea_list);
6778 if (!NT_STATUS_IS_OK(status)) {
6779 reply_nterror(req, status);
6784 /* Realloc the parameter and data sizes */
6785 *pparams = (char *)SMB_REALLOC(*pparams,2);
6786 if(*pparams == NULL) {
6787 reply_nterror(req, NT_STATUS_NO_MEMORY);
6794 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
6799 /****************************************************************************
6800 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6801 We don't actually do this - we just send a null response.
6802 ****************************************************************************/
6804 static void call_trans2findnotifyfirst(connection_struct *conn,
6805 struct smb_request *req,
6806 char **pparams, int total_params,
6807 char **ppdata, int total_data,
6808 unsigned int max_data_bytes)
6810 static uint16 fnf_handle = 257;
6811 char *params = *pparams;
6814 if (total_params < 6) {
6815 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6819 info_level = SVAL(params,4);
6820 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6822 switch (info_level) {
6827 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6831 /* Realloc the parameter and data sizes */
6832 *pparams = (char *)SMB_REALLOC(*pparams,6);
6833 if (*pparams == NULL) {
6834 reply_nterror(req, NT_STATUS_NO_MEMORY);
6839 SSVAL(params,0,fnf_handle);
6840 SSVAL(params,2,0); /* No changes */
6841 SSVAL(params,4,0); /* No EA errors */
6848 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
6853 /****************************************************************************
6854 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6855 changes). Currently this does nothing.
6856 ****************************************************************************/
6858 static void call_trans2findnotifynext(connection_struct *conn,
6859 struct smb_request *req,
6860 char **pparams, int total_params,
6861 char **ppdata, int total_data,
6862 unsigned int max_data_bytes)
6864 char *params = *pparams;
6866 DEBUG(3,("call_trans2findnotifynext\n"));
6868 /* Realloc the parameter and data sizes */
6869 *pparams = (char *)SMB_REALLOC(*pparams,4);
6870 if (*pparams == NULL) {
6871 reply_nterror(req, NT_STATUS_NO_MEMORY);
6876 SSVAL(params,0,0); /* No changes */
6877 SSVAL(params,2,0); /* No EA errors */
6879 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
6884 /****************************************************************************
6885 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6886 ****************************************************************************/
6888 static void call_trans2getdfsreferral(connection_struct *conn,
6889 struct smb_request *req,
6890 char **pparams, int total_params,
6891 char **ppdata, int total_data,
6892 unsigned int max_data_bytes)
6894 char *params = *pparams;
6895 char *pathname = NULL;
6897 int max_referral_level;
6898 NTSTATUS status = NT_STATUS_OK;
6899 TALLOC_CTX *ctx = talloc_tos();
6901 DEBUG(10,("call_trans2getdfsreferral\n"));
6903 if (total_params < 3) {
6904 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6908 max_referral_level = SVAL(params,0);
6910 if(!lp_host_msdfs()) {
6911 reply_doserror(req, ERRDOS, ERRbadfunc);
6915 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
6916 total_params - 2, STR_TERMINATE);
6918 reply_nterror(req, NT_STATUS_NOT_FOUND);
6921 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6922 ppdata,&status)) < 0) {
6923 reply_nterror(req, status);
6927 SSVAL(req->inbuf, smb_flg2,
6928 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6929 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
6934 #define LMCAT_SPL 0x53
6935 #define LMFUNC_GETJOBID 0x60
6937 /****************************************************************************
6938 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6939 ****************************************************************************/
6941 static void call_trans2ioctl(connection_struct *conn,
6942 struct smb_request *req,
6943 char **pparams, int total_params,
6944 char **ppdata, int total_data,
6945 unsigned int max_data_bytes)
6947 char *pdata = *ppdata;
6948 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6950 /* check for an invalid fid before proceeding */
6953 reply_doserror(req, ERRDOS, ERRbadfid);
6957 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6958 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6959 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6960 if (*ppdata == NULL) {
6961 reply_nterror(req, NT_STATUS_NO_MEMORY);
6966 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6967 CAN ACCEPT THIS IN UNICODE. JRA. */
6969 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6970 srvstr_push(pdata, req->flags2, pdata + 2,
6971 global_myname(), 15,
6972 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6973 srvstr_push(pdata, req->flags2, pdata+18,
6974 lp_servicename(SNUM(conn)), 13,
6975 STR_ASCII|STR_TERMINATE); /* Service name */
6976 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
6981 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6982 reply_doserror(req, ERRSRV, ERRerror);
6985 /****************************************************************************
6986 Reply to a SMBfindclose (stop trans2 directory search).
6987 ****************************************************************************/
6989 void reply_findclose(struct smb_request *req)
6993 START_PROFILE(SMBfindclose);
6996 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6997 END_PROFILE(SMBfindclose);
7001 dptr_num = SVALS(req->inbuf,smb_vwv0);
7003 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7005 dptr_close(&dptr_num);
7007 reply_outbuf(req, 0, 0);
7009 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7011 END_PROFILE(SMBfindclose);
7015 /****************************************************************************
7016 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7017 ****************************************************************************/
7019 void reply_findnclose(struct smb_request *req)
7023 START_PROFILE(SMBfindnclose);
7026 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7027 END_PROFILE(SMBfindnclose);
7031 dptr_num = SVAL(req->inbuf,smb_vwv0);
7033 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7035 /* We never give out valid handles for a
7036 findnotifyfirst - so any dptr_num is ok here.
7039 reply_outbuf(req, 0, 0);
7041 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7043 END_PROFILE(SMBfindnclose);
7047 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7048 struct trans_state *state)
7050 if (Protocol >= PROTOCOL_NT1) {
7051 req->flags2 |= 0x40; /* IS_LONG_NAME */
7052 SSVAL(req->inbuf,smb_flg2,req->flags2);
7055 if (conn->encrypt_level == Required && !req->encrypted) {
7056 if (state->call != TRANSACT2_QFSINFO &&
7057 state->call != TRANSACT2_SETFSINFO) {
7058 DEBUG(0,("handle_trans2: encryption required "
7060 (unsigned int)state->call));
7061 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7066 /* Now we must call the relevant TRANS2 function */
7067 switch(state->call) {
7068 case TRANSACT2_OPEN:
7070 START_PROFILE(Trans2_open);
7071 call_trans2open(conn, req,
7072 &state->param, state->total_param,
7073 &state->data, state->total_data,
7074 state->max_data_return);
7075 END_PROFILE(Trans2_open);
7079 case TRANSACT2_FINDFIRST:
7081 START_PROFILE(Trans2_findfirst);
7082 call_trans2findfirst(conn, req,
7083 &state->param, state->total_param,
7084 &state->data, state->total_data,
7085 state->max_data_return);
7086 END_PROFILE(Trans2_findfirst);
7090 case TRANSACT2_FINDNEXT:
7092 START_PROFILE(Trans2_findnext);
7093 call_trans2findnext(conn, req,
7094 &state->param, state->total_param,
7095 &state->data, state->total_data,
7096 state->max_data_return);
7097 END_PROFILE(Trans2_findnext);
7101 case TRANSACT2_QFSINFO:
7103 START_PROFILE(Trans2_qfsinfo);
7104 call_trans2qfsinfo(conn, req,
7105 &state->param, state->total_param,
7106 &state->data, state->total_data,
7107 state->max_data_return);
7108 END_PROFILE(Trans2_qfsinfo);
7112 case TRANSACT2_SETFSINFO:
7114 START_PROFILE(Trans2_setfsinfo);
7115 call_trans2setfsinfo(conn, req,
7116 &state->param, state->total_param,
7117 &state->data, state->total_data,
7118 state->max_data_return);
7119 END_PROFILE(Trans2_setfsinfo);
7123 case TRANSACT2_QPATHINFO:
7124 case TRANSACT2_QFILEINFO:
7126 START_PROFILE(Trans2_qpathinfo);
7127 call_trans2qfilepathinfo(conn, req, state->call,
7128 &state->param, state->total_param,
7129 &state->data, state->total_data,
7130 state->max_data_return);
7131 END_PROFILE(Trans2_qpathinfo);
7135 case TRANSACT2_SETPATHINFO:
7136 case TRANSACT2_SETFILEINFO:
7138 START_PROFILE(Trans2_setpathinfo);
7139 call_trans2setfilepathinfo(conn, req, state->call,
7140 &state->param, state->total_param,
7141 &state->data, state->total_data,
7142 state->max_data_return);
7143 END_PROFILE(Trans2_setpathinfo);
7147 case TRANSACT2_FINDNOTIFYFIRST:
7149 START_PROFILE(Trans2_findnotifyfirst);
7150 call_trans2findnotifyfirst(conn, req,
7151 &state->param, state->total_param,
7152 &state->data, state->total_data,
7153 state->max_data_return);
7154 END_PROFILE(Trans2_findnotifyfirst);
7158 case TRANSACT2_FINDNOTIFYNEXT:
7160 START_PROFILE(Trans2_findnotifynext);
7161 call_trans2findnotifynext(conn, req,
7162 &state->param, state->total_param,
7163 &state->data, state->total_data,
7164 state->max_data_return);
7165 END_PROFILE(Trans2_findnotifynext);
7169 case TRANSACT2_MKDIR:
7171 START_PROFILE(Trans2_mkdir);
7172 call_trans2mkdir(conn, req,
7173 &state->param, state->total_param,
7174 &state->data, state->total_data,
7175 state->max_data_return);
7176 END_PROFILE(Trans2_mkdir);
7180 case TRANSACT2_GET_DFS_REFERRAL:
7182 START_PROFILE(Trans2_get_dfs_referral);
7183 call_trans2getdfsreferral(conn, req,
7184 &state->param, state->total_param,
7185 &state->data, state->total_data,
7186 state->max_data_return);
7187 END_PROFILE(Trans2_get_dfs_referral);
7191 case TRANSACT2_IOCTL:
7193 START_PROFILE(Trans2_ioctl);
7194 call_trans2ioctl(conn, req,
7195 &state->param, state->total_param,
7196 &state->data, state->total_data,
7197 state->max_data_return);
7198 END_PROFILE(Trans2_ioctl);
7203 /* Error in request */
7204 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7205 reply_doserror(req, ERRSRV,ERRerror);
7209 /****************************************************************************
7210 Reply to a SMBtrans2.
7211 ****************************************************************************/
7213 void reply_trans2(struct smb_request *req)
7215 connection_struct *conn = req->conn;
7220 unsigned int tran_call;
7222 struct trans_state *state;
7225 START_PROFILE(SMBtrans2);
7227 if (req->wct < 14) {
7228 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7229 END_PROFILE(SMBtrans2);
7233 dsoff = SVAL(req->inbuf, smb_dsoff);
7234 dscnt = SVAL(req->inbuf, smb_dscnt);
7235 psoff = SVAL(req->inbuf, smb_psoff);
7236 pscnt = SVAL(req->inbuf, smb_pscnt);
7237 tran_call = SVAL(req->inbuf, smb_setup0);
7238 size = smb_len(req->inbuf) + 4;
7240 result = allow_new_trans(conn->pending_trans, req->mid);
7241 if (!NT_STATUS_IS_OK(result)) {
7242 DEBUG(2, ("Got invalid trans2 request: %s\n",
7243 nt_errstr(result)));
7244 reply_nterror(req, result);
7245 END_PROFILE(SMBtrans2);
7250 switch (tran_call) {
7251 /* List the allowed trans2 calls on IPC$ */
7252 case TRANSACT2_OPEN:
7253 case TRANSACT2_GET_DFS_REFERRAL:
7254 case TRANSACT2_QFILEINFO:
7255 case TRANSACT2_QFSINFO:
7256 case TRANSACT2_SETFSINFO:
7259 reply_doserror(req, ERRSRV, ERRaccess);
7260 END_PROFILE(SMBtrans2);
7265 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7266 DEBUG(0, ("talloc failed\n"));
7267 reply_nterror(req, NT_STATUS_NO_MEMORY);
7268 END_PROFILE(SMBtrans2);
7272 state->cmd = SMBtrans2;
7274 state->mid = req->mid;
7275 state->vuid = req->vuid;
7276 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7277 state->setup = NULL;
7278 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7279 state->param = NULL;
7280 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7282 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7283 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7284 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7285 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7286 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7288 state->call = tran_call;
7290 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7291 is so as a sanity check */
7292 if (state->setup_count != 1) {
7294 * Need to have rc=0 for ioctl to get job id for OS/2.
7295 * Network printing will fail if function is not successful.
7296 * Similar function in reply.c will be used if protocol
7297 * is LANMAN1.0 instead of LM1.2X002.
7298 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7299 * outbuf doesn't have to be set(only job id is used).
7301 if ( (state->setup_count == 4)
7302 && (tran_call == TRANSACT2_IOCTL)
7303 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7304 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7305 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7307 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7308 DEBUG(2,("Transaction is %d\n",tran_call));
7310 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7311 END_PROFILE(SMBtrans2);
7316 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7319 if (state->total_data) {
7320 /* Can't use talloc here, the core routines do realloc on the
7321 * params and data. */
7322 state->data = (char *)SMB_MALLOC(state->total_data);
7323 if (state->data == NULL) {
7324 DEBUG(0,("reply_trans2: data malloc fail for %u "
7325 "bytes !\n", (unsigned int)state->total_data));
7327 reply_nterror(req, NT_STATUS_NO_MEMORY);
7328 END_PROFILE(SMBtrans2);
7331 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7333 if ((smb_base(req->inbuf)+dsoff+dscnt
7334 > (char *)req->inbuf + size) ||
7335 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7338 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7341 if (state->total_param) {
7342 /* Can't use talloc here, the core routines do realloc on the
7343 * params and data. */
7344 state->param = (char *)SMB_MALLOC(state->total_param);
7345 if (state->param == NULL) {
7346 DEBUG(0,("reply_trans: param malloc fail for %u "
7347 "bytes !\n", (unsigned int)state->total_param));
7348 SAFE_FREE(state->data);
7350 reply_nterror(req, NT_STATUS_NO_MEMORY);
7351 END_PROFILE(SMBtrans2);
7354 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7356 if ((smb_base(req->inbuf)+psoff+pscnt
7357 > (char *)req->inbuf + size) ||
7358 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7361 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7364 state->received_data = dscnt;
7365 state->received_param = pscnt;
7367 if ((state->received_param == state->total_param) &&
7368 (state->received_data == state->total_data)) {
7370 handle_trans2(conn, req, state);
7372 SAFE_FREE(state->data);
7373 SAFE_FREE(state->param);
7375 END_PROFILE(SMBtrans2);
7379 DLIST_ADD(conn->pending_trans, state);
7381 /* We need to send an interim response then receive the rest
7382 of the parameter/data bytes */
7383 reply_outbuf(req, 0, 0);
7384 show_msg((char *)req->outbuf);
7385 END_PROFILE(SMBtrans2);
7390 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7391 SAFE_FREE(state->data);
7392 SAFE_FREE(state->param);
7394 END_PROFILE(SMBtrans2);
7395 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7399 /****************************************************************************
7400 Reply to a SMBtranss2
7401 ****************************************************************************/
7403 void reply_transs2(struct smb_request *req)
7405 connection_struct *conn = req->conn;
7406 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7407 struct trans_state *state;
7410 START_PROFILE(SMBtranss2);
7412 show_msg((char *)req->inbuf);
7415 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7416 END_PROFILE(SMBtranss2);
7420 size = smb_len(req->inbuf)+4;
7422 for (state = conn->pending_trans; state != NULL;
7423 state = state->next) {
7424 if (state->mid == req->mid) {
7429 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7430 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7431 END_PROFILE(SMBtranss2);
7435 /* Revise state->total_param and state->total_data in case they have
7436 changed downwards */
7438 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7439 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7440 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7441 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7443 pcnt = SVAL(req->inbuf, smb_spscnt);
7444 poff = SVAL(req->inbuf, smb_spsoff);
7445 pdisp = SVAL(req->inbuf, smb_spsdisp);
7447 dcnt = SVAL(req->inbuf, smb_sdscnt);
7448 doff = SVAL(req->inbuf, smb_sdsoff);
7449 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7451 state->received_param += pcnt;
7452 state->received_data += dcnt;
7454 if ((state->received_data > state->total_data) ||
7455 (state->received_param > state->total_param))
7459 if (pdisp+pcnt > state->total_param)
7461 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7463 if (pdisp > state->total_param)
7465 if ((smb_base(req->inbuf) + poff + pcnt
7466 > (char *)req->inbuf + size) ||
7467 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7469 if (state->param + pdisp < state->param)
7472 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7477 if (ddisp+dcnt > state->total_data)
7479 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7481 if (ddisp > state->total_data)
7483 if ((smb_base(req->inbuf) + doff + dcnt
7484 > (char *)req->inbuf + size) ||
7485 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7487 if (state->data + ddisp < state->data)
7490 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7494 if ((state->received_param < state->total_param) ||
7495 (state->received_data < state->total_data)) {
7496 END_PROFILE(SMBtranss2);
7501 * construct_reply_common will copy smb_com from inbuf to
7502 * outbuf. SMBtranss2 is wrong here.
7504 SCVAL(req->inbuf,smb_com,SMBtrans2);
7506 handle_trans2(conn, req, state);
7508 DLIST_REMOVE(conn->pending_trans, state);
7509 SAFE_FREE(state->data);
7510 SAFE_FREE(state->param);
7513 END_PROFILE(SMBtranss2);
7518 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7519 DLIST_REMOVE(conn->pending_trans, state);
7520 SAFE_FREE(state->data);
7521 SAFE_FREE(state->param);
7523 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7524 END_PROFILE(SMBtranss2);