2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 extern enum protocol_types Protocol;
30 extern uint32 global_client_caps;
31 extern struct current_user current_user;
33 #define get_file_size(sbuf) ((sbuf).st_size)
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
36 static char *store_file_unix_basic(connection_struct *conn,
39 const SMB_STRUCT_STAT *psbuf);
41 static char *store_file_unix_basic_info2(connection_struct *conn,
44 const SMB_STRUCT_STAT *psbuf);
46 /********************************************************************
47 Roundup a value to the nearest allocation roundup size boundary.
48 Only do this for Windows clients.
49 ********************************************************************/
51 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
53 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
55 /* Only roundup for Windows clients. */
56 enum remote_arch_types ra_type = get_remote_arch();
57 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
58 val = SMB_ROUNDUP(val,rval);
63 /********************************************************************
64 Given a stat buffer return the allocated size on disk, taking into
66 ********************************************************************/
68 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
72 if(S_ISDIR(sbuf->st_mode)) {
76 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
77 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
79 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
82 if (fsp && fsp->initial_allocation_size)
83 ret = MAX(ret,fsp->initial_allocation_size);
85 return smb_roundup(conn, ret);
88 /****************************************************************************
89 Utility functions for dealing with extended attributes.
90 ****************************************************************************/
92 /****************************************************************************
93 Refuse to allow clients to overwrite our private xattrs.
94 ****************************************************************************/
96 static bool samba_private_attr_name(const char *unix_ea_name)
98 static const char *prohibited_ea_names[] = {
99 SAMBA_POSIX_INHERITANCE_EA_NAME,
100 SAMBA_XATTR_DOS_ATTRIB,
106 for (i = 0; prohibited_ea_names[i]; i++) {
107 if (strequal( prohibited_ea_names[i], unix_ea_name))
113 /****************************************************************************
114 Get one EA value. Fill in a struct ea_struct.
115 ****************************************************************************/
117 static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
118 const char *fname, char *ea_name, struct ea_struct *pea)
120 /* Get the value of this xattr. Max size is 64k. */
121 size_t attr_size = 256;
127 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
132 if (fsp && fsp->fh->fd != -1) {
133 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
135 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
138 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
147 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
148 dump_data(10, (uint8 *)val, sizeret);
151 if (strnequal(ea_name, "user.", 5)) {
152 pea->name = &ea_name[5];
156 pea->value.data = (unsigned char *)val;
157 pea->value.length = (size_t)sizeret;
161 /****************************************************************************
162 Return a linked list of the total EA's. Plus the total size
163 ****************************************************************************/
165 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
166 const char *fname, size_t *pea_total_len)
168 /* Get a list of all xattrs. Max namesize is 64k. */
169 size_t ea_namelist_size = 1024;
174 struct ea_list *ea_list_head = NULL;
178 if (!lp_ea_support(SNUM(conn))) {
182 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
183 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
189 if (fsp && fsp->fh->fd != -1) {
190 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
192 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
195 if (sizeret == -1 && errno == ERANGE) {
196 ea_namelist_size *= 2;
205 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
208 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
209 struct ea_list *listp;
211 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
214 listp = TALLOC_P(mem_ctx, struct ea_list);
218 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
224 push_ascii_fstring(dos_ea_name, listp->ea.name);
225 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
226 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
227 (unsigned int)*pea_total_len, dos_ea_name,
228 (unsigned int)listp->ea.value.length ));
230 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
232 /* Add on 4 for total length. */
233 if (*pea_total_len) {
238 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
242 /****************************************************************************
243 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
245 ****************************************************************************/
247 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
248 connection_struct *conn, struct ea_list *ea_list)
250 unsigned int ret_data_size = 4;
253 SMB_ASSERT(total_data_size >= 4);
255 if (!lp_ea_support(SNUM(conn))) {
260 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
263 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
264 dos_namelen = strlen(dos_ea_name);
265 if (dos_namelen > 255 || dos_namelen == 0) {
268 if (ea_list->ea.value.length > 65535) {
271 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
275 /* We know we have room. */
276 SCVAL(p,0,ea_list->ea.flags);
277 SCVAL(p,1,dos_namelen);
278 SSVAL(p,2,ea_list->ea.value.length);
279 fstrcpy(p+4, dos_ea_name);
280 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
282 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
283 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
286 ret_data_size = PTR_DIFF(p, pdata);
287 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
288 SIVAL(pdata,0,ret_data_size);
289 return ret_data_size;
292 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
294 size_t total_ea_len = 0;
295 TALLOC_CTX *mem_ctx = NULL;
297 if (!lp_ea_support(SNUM(conn))) {
300 mem_ctx = talloc_init("estimate_ea_size");
301 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
302 talloc_destroy(mem_ctx);
306 /****************************************************************************
307 Ensure the EA name is case insensitive by matching any existing EA name.
308 ****************************************************************************/
310 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
313 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
314 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
316 for (; ea_list; ea_list = ea_list->next) {
317 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
318 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
319 &unix_ea_name[5], ea_list->ea.name));
320 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
324 talloc_destroy(mem_ctx);
327 /****************************************************************************
328 Set or delete an extended attribute.
329 ****************************************************************************/
331 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
333 if (!lp_ea_support(SNUM(conn))) {
334 return NT_STATUS_EAS_NOT_SUPPORTED;
337 for (;ea_list; ea_list = ea_list->next) {
339 fstring unix_ea_name;
341 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
342 fstrcat(unix_ea_name, ea_list->ea.name);
344 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
346 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
348 if (samba_private_attr_name(unix_ea_name)) {
349 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
350 return NT_STATUS_ACCESS_DENIED;
353 if (ea_list->ea.value.length == 0) {
354 /* Remove the attribute. */
355 if (fsp && (fsp->fh->fd != -1)) {
356 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
357 unix_ea_name, fsp->fsp_name));
358 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
360 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
361 unix_ea_name, fname));
362 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
365 /* Removing a non existent attribute always succeeds. */
366 if (ret == -1 && errno == ENOATTR) {
367 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
373 if (fsp && (fsp->fh->fd != -1)) {
374 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
375 unix_ea_name, fsp->fsp_name));
376 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
377 ea_list->ea.value.data, ea_list->ea.value.length, 0);
379 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
380 unix_ea_name, fname));
381 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
382 ea_list->ea.value.data, ea_list->ea.value.length, 0);
388 if (errno == ENOTSUP) {
389 return NT_STATUS_EAS_NOT_SUPPORTED;
392 return map_nt_error_from_unix(errno);
398 /****************************************************************************
399 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
400 ****************************************************************************/
402 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
404 struct ea_list *ea_list_head = NULL;
407 while (offset + 2 < data_size) {
408 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
409 unsigned int namelen = CVAL(pdata,offset);
411 offset++; /* Go past the namelen byte. */
413 /* integer wrap paranioa. */
414 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
415 (offset > data_size) || (namelen > data_size) ||
416 (offset + namelen >= data_size)) {
419 /* Ensure the name is null terminated. */
420 if (pdata[offset + namelen] != '\0') {
423 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
428 offset += (namelen + 1); /* Go past the name + terminating zero. */
429 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
430 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
436 /****************************************************************************
437 Read one EA list entry from the buffer.
438 ****************************************************************************/
440 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
442 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
444 unsigned int namelen;
454 eal->ea.flags = CVAL(pdata,0);
455 namelen = CVAL(pdata,1);
456 val_len = SVAL(pdata,2);
458 if (4 + namelen + 1 + val_len > data_size) {
462 /* Ensure the name is null terminated. */
463 if (pdata[namelen + 4] != '\0') {
466 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
471 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
472 if (!eal->ea.value.data) {
476 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
478 /* Ensure we're null terminated just in case we print the value. */
479 eal->ea.value.data[val_len] = '\0';
480 /* But don't count the null. */
481 eal->ea.value.length--;
484 *pbytes_used = 4 + namelen + 1 + val_len;
487 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
488 dump_data(10, eal->ea.value.data, eal->ea.value.length);
493 /****************************************************************************
494 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
495 ****************************************************************************/
497 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
499 struct ea_list *ea_list_head = NULL;
501 size_t bytes_used = 0;
503 while (offset < data_size) {
504 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
510 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
511 offset += bytes_used;
517 /****************************************************************************
518 Count the total EA size needed.
519 ****************************************************************************/
521 static size_t ea_list_size(struct ea_list *ealist)
524 struct ea_list *listp;
527 for (listp = ealist; listp; listp = listp->next) {
528 push_ascii_fstring(dos_ea_name, listp->ea.name);
529 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
531 /* Add on 4 for total length. */
539 /****************************************************************************
540 Return a union of EA's from a file list and a list of names.
541 The TALLOC context for the two lists *MUST* be identical as we steal
542 memory from one list to add to another. JRA.
543 ****************************************************************************/
545 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
547 struct ea_list *nlistp, *flistp;
549 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
550 for (flistp = file_list; flistp; flistp = flistp->next) {
551 if (strequal(nlistp->ea.name, flistp->ea.name)) {
557 /* Copy the data from this entry. */
558 nlistp->ea.flags = flistp->ea.flags;
559 nlistp->ea.value = flistp->ea.value;
562 nlistp->ea.flags = 0;
563 ZERO_STRUCT(nlistp->ea.value);
567 *total_ea_len = ea_list_size(name_list);
571 /****************************************************************************
572 Send the required number of replies back.
573 We assume all fields other than the data fields are
574 set correctly for the type of call.
575 HACK ! Always assumes smb_setup field is zero.
576 ****************************************************************************/
578 void send_trans2_replies(connection_struct *conn,
579 struct smb_request *req,
586 /* As we are using a protocol > LANMAN1 then the max_send
587 variable must have been set in the sessetupX call.
588 This takes precedence over the max_xmit field in the
589 global struct. These different max_xmit variables should
590 be merged as this is now too confusing */
592 int data_to_send = datasize;
593 int params_to_send = paramsize;
595 const char *pp = params;
596 const char *pd = pdata;
597 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
598 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
599 int data_alignment_offset = 0;
600 bool overflow = False;
602 /* Modify the data_to_send and datasize and set the error if
603 we're trying to send more than max_data_bytes. We still send
604 the part of the packet(s) that fit. Strange, but needed
607 if (max_data_bytes > 0 && datasize > max_data_bytes) {
608 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
609 max_data_bytes, datasize ));
610 datasize = data_to_send = max_data_bytes;
614 /* If there genuinely are no parameters or data to send just send the empty packet */
616 if(params_to_send == 0 && data_to_send == 0) {
617 reply_outbuf(req, 10, 0);
618 show_msg((char *)req->outbuf);
622 /* When sending params and data ensure that both are nicely aligned */
623 /* Only do this alignment when there is also data to send - else
624 can cause NT redirector problems. */
626 if (((params_to_send % 4) != 0) && (data_to_send != 0))
627 data_alignment_offset = 4 - (params_to_send % 4);
629 /* Space is bufsize minus Netbios over TCP header minus SMB header */
630 /* The alignment_offset is to align the param bytes on an even byte
631 boundary. NT 4.0 Beta needs this to work correctly. */
633 useable_space = max_send - (smb_size
636 + data_alignment_offset);
638 /* useable_space can never be more than max_send minus the alignment offset. */
640 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
642 while (params_to_send || data_to_send) {
643 /* Calculate whether we will totally or partially fill this packet */
645 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
647 /* We can never send more than useable_space */
649 * Note that 'useable_space' does not include the alignment offsets,
650 * but we must include the alignment offsets in the calculation of
651 * the length of the data we send over the wire, as the alignment offsets
652 * are sent here. Fix from Marc_Jacobsen@hp.com.
655 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
657 reply_outbuf(req, 10, total_sent_thistime);
659 /* Set total params and data to be sent */
660 SSVAL(req->outbuf,smb_tprcnt,paramsize);
661 SSVAL(req->outbuf,smb_tdrcnt,datasize);
663 /* Calculate how many parameters and data we can fit into
664 * this packet. Parameters get precedence
667 params_sent_thistime = MIN(params_to_send,useable_space);
668 data_sent_thistime = useable_space - params_sent_thistime;
669 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
671 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
673 /* smb_proff is the offset from the start of the SMB header to the
674 parameter bytes, however the first 4 bytes of outbuf are
675 the Netbios over TCP header. Thus use smb_base() to subtract
676 them from the calculation */
678 SSVAL(req->outbuf,smb_proff,
679 ((smb_buf(req->outbuf)+alignment_offset)
680 - smb_base(req->outbuf)));
682 if(params_sent_thistime == 0)
683 SSVAL(req->outbuf,smb_prdisp,0);
685 /* Absolute displacement of param bytes sent in this packet */
686 SSVAL(req->outbuf,smb_prdisp,pp - params);
688 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
689 if(data_sent_thistime == 0) {
690 SSVAL(req->outbuf,smb_droff,0);
691 SSVAL(req->outbuf,smb_drdisp, 0);
693 /* The offset of the data bytes is the offset of the
694 parameter bytes plus the number of parameters being sent this time */
695 SSVAL(req->outbuf, smb_droff,
696 ((smb_buf(req->outbuf)+alignment_offset)
697 - smb_base(req->outbuf))
698 + params_sent_thistime + data_alignment_offset);
699 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
702 /* Initialize the padding for alignment */
704 if (alignment_offset != 0) {
705 memset(smb_buf(req->outbuf), 0, alignment_offset);
708 /* Copy the param bytes into the packet */
710 if(params_sent_thistime) {
711 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
712 params_sent_thistime);
715 /* Copy in the data bytes */
716 if(data_sent_thistime) {
717 if (data_alignment_offset != 0) {
718 memset((smb_buf(req->outbuf)+alignment_offset+
719 params_sent_thistime), 0,
720 data_alignment_offset);
722 memcpy(smb_buf(req->outbuf)+alignment_offset
723 +params_sent_thistime+data_alignment_offset,
724 pd,data_sent_thistime);
727 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
728 params_sent_thistime, data_sent_thistime, useable_space));
729 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
730 params_to_send, data_to_send, paramsize, datasize));
733 error_packet_set((char *)req->outbuf,
734 ERRDOS,ERRbufferoverflow,
735 STATUS_BUFFER_OVERFLOW,
739 /* Send the packet */
740 show_msg((char *)req->outbuf);
741 if (!srv_send_smb(smbd_server_fd(),
743 IS_CONN_ENCRYPTED(conn)))
744 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
746 TALLOC_FREE(req->outbuf);
748 pp += params_sent_thistime;
749 pd += data_sent_thistime;
751 params_to_send -= params_sent_thistime;
752 data_to_send -= data_sent_thistime;
755 if(params_to_send < 0 || data_to_send < 0) {
756 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
757 params_to_send, data_to_send));
765 /****************************************************************************
766 Reply to a TRANSACT2_OPEN.
767 ****************************************************************************/
769 static void call_trans2open(connection_struct *conn,
770 struct smb_request *req,
771 char **pparams, int total_params,
772 char **ppdata, int total_data,
773 unsigned int max_data_bytes)
775 char *params = *pparams;
776 char *pdata = *ppdata;
781 bool return_additional_info;
792 SMB_STRUCT_STAT sbuf;
795 struct ea_list *ea_list = NULL;
800 uint32 create_disposition;
801 uint32 create_options = 0;
802 TALLOC_CTX *ctx = talloc_tos();
805 * Ensure we have enough parameters to perform the operation.
808 if (total_params < 29) {
809 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
813 flags = SVAL(params, 0);
814 deny_mode = SVAL(params, 2);
815 open_attr = SVAL(params,6);
816 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
817 if (oplock_request) {
818 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
822 return_additional_info = BITSETW(params,0);
823 open_sattr = SVAL(params, 4);
824 open_time = make_unix_date3(params+8);
826 open_ofun = SVAL(params,12);
827 open_size = IVAL(params,14);
831 reply_doserror(req, ERRSRV, ERRaccess);
835 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
836 total_params - 28, STR_TERMINATE,
838 if (!NT_STATUS_IS_OK(status)) {
839 reply_nterror(req, status);
843 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
844 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
845 (unsigned int)open_ofun, open_size));
847 if (open_ofun == 0) {
848 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
852 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
857 reply_doserror(req, ERRDOS, ERRbadaccess);
861 /* Any data in this call is an EA list. */
862 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
863 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
867 if (total_data != 4) {
868 if (total_data < 10) {
869 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
873 if (IVAL(pdata,0) > total_data) {
874 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
875 IVAL(pdata,0), (unsigned int)total_data));
876 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
880 ea_list = read_ea_list(talloc_tos(), pdata + 4,
883 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
886 } else if (IVAL(pdata,0) != 4) {
887 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
891 status = create_file(conn, /* conn */
893 0, /* root_dir_fid */
895 access_mask, /* access_mask */
896 share_mode, /* share_access */
897 create_disposition, /* create_disposition*/
898 create_options, /* create_options */
899 open_attr, /* file_attributes */
900 oplock_request, /* oplock_request */
901 open_size, /* allocation_size */
903 ea_list, /* ea_list */
905 &smb_action, /* pinfo */
908 if (!NT_STATUS_IS_OK(status)) {
909 if (open_was_deferred(req->mid)) {
910 /* We have re-scheduled this call. */
913 reply_openerror(req, status);
917 size = get_file_size(sbuf);
918 fattr = dos_mode(conn,fname,&sbuf);
919 mtime = sbuf.st_mtime;
922 close_file(fsp,ERROR_CLOSE);
923 reply_doserror(req, ERRDOS,ERRnoaccess);
927 /* Realloc the size of parameters and data we will return */
928 *pparams = (char *)SMB_REALLOC(*pparams, 30);
929 if(*pparams == NULL ) {
930 reply_nterror(req, NT_STATUS_NO_MEMORY);
935 SSVAL(params,0,fsp->fnum);
936 SSVAL(params,2,fattr);
937 srv_put_dos_date2(params,4, mtime);
938 SIVAL(params,8, (uint32)size);
939 SSVAL(params,12,deny_mode);
940 SSVAL(params,14,0); /* open_type - file or directory. */
941 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
943 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
944 smb_action |= EXTENDED_OPLOCK_GRANTED;
947 SSVAL(params,18,smb_action);
950 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
952 SIVAL(params,20,inode);
953 SSVAL(params,24,0); /* Padding. */
955 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
956 SIVAL(params, 26, ea_size);
958 SIVAL(params, 26, 0);
961 /* Send the required number of replies */
962 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
965 /*********************************************************
966 Routine to check if a given string matches exactly.
967 as a special case a mask of "." does NOT match. That
968 is required for correct wildcard semantics
969 Case can be significant or not.
970 **********************************************************/
972 static bool exact_match(connection_struct *conn,
976 if (mask[0] == '.' && mask[1] == 0)
978 if (conn->case_sensitive)
979 return strcmp(str,mask)==0;
980 if (StrCaseCmp(str,mask) != 0) {
983 if (dptr_has_wild(conn->dirptr)) {
989 /****************************************************************************
990 Return the filetype for UNIX extensions.
991 ****************************************************************************/
993 static uint32 unix_filetype(mode_t mode)
996 return UNIX_TYPE_FILE;
997 else if(S_ISDIR(mode))
998 return UNIX_TYPE_DIR;
1000 else if(S_ISLNK(mode))
1001 return UNIX_TYPE_SYMLINK;
1004 else if(S_ISCHR(mode))
1005 return UNIX_TYPE_CHARDEV;
1008 else if(S_ISBLK(mode))
1009 return UNIX_TYPE_BLKDEV;
1012 else if(S_ISFIFO(mode))
1013 return UNIX_TYPE_FIFO;
1016 else if(S_ISSOCK(mode))
1017 return UNIX_TYPE_SOCKET;
1020 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1021 return UNIX_TYPE_UNKNOWN;
1024 /****************************************************************************
1025 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1026 ****************************************************************************/
1028 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1030 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1031 SMB_STRUCT_STAT *psbuf,
1033 enum perm_type ptype,
1038 if (perms == SMB_MODE_NO_CHANGE) {
1039 if (!VALID_STAT(*psbuf)) {
1040 return NT_STATUS_INVALID_PARAMETER;
1042 *ret_perms = psbuf->st_mode;
1043 return NT_STATUS_OK;
1047 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1048 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1049 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1050 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1051 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1052 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1053 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1054 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1055 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1057 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1060 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1063 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1068 /* Apply mode mask */
1069 ret &= lp_create_mask(SNUM(conn));
1070 /* Add in force bits */
1071 ret |= lp_force_create_mode(SNUM(conn));
1074 ret &= lp_dir_mask(SNUM(conn));
1075 /* Add in force bits */
1076 ret |= lp_force_dir_mode(SNUM(conn));
1078 case PERM_EXISTING_FILE:
1079 /* Apply mode mask */
1080 ret &= lp_security_mask(SNUM(conn));
1081 /* Add in force bits */
1082 ret |= lp_force_security_mode(SNUM(conn));
1084 case PERM_EXISTING_DIR:
1085 /* Apply mode mask */
1086 ret &= lp_dir_security_mask(SNUM(conn));
1087 /* Add in force bits */
1088 ret |= lp_force_dir_security_mode(SNUM(conn));
1093 return NT_STATUS_OK;
1096 /****************************************************************************
1097 Get a level dependent lanman2 dir entry.
1098 ****************************************************************************/
1100 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1101 connection_struct *conn,
1103 const char *path_mask,
1106 int requires_resume_key,
1111 int space_remaining,
1113 bool *got_exact_match,
1114 int *last_entry_off,
1115 struct ea_list *name_list)
1119 SMB_STRUCT_STAT sbuf;
1120 const char *mask = NULL;
1121 char *pathreal = NULL;
1122 const char *fname = NULL;
1123 char *p, *q, *pdata = *ppdata;
1127 SMB_OFF_T file_size = 0;
1128 SMB_BIG_UINT allocation_size = 0;
1130 struct timespec mdate_ts, adate_ts, create_date_ts;
1131 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1133 char *last_entry_ptr;
1135 uint32 nt_extmode; /* Used for NT connections instead of mode */
1136 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1137 bool check_mangled_names = lp_manglednames(conn->params);
1138 char mangled_name[13]; /* mangled 8.3 name. */
1140 *out_of_space = False;
1141 *got_exact_match = False;
1143 ZERO_STRUCT(mdate_ts);
1144 ZERO_STRUCT(adate_ts);
1145 ZERO_STRUCT(create_date_ts);
1147 if (!conn->dirptr) {
1151 p = strrchr_m(path_mask,'/');
1154 mask = talloc_strdup(ctx,"*.*");
1164 bool ms_dfs_link = False;
1166 /* Needed if we run out of space */
1167 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1168 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1171 * Due to bugs in NT client redirectors we are not using
1172 * resume keys any more - set them to zero.
1173 * Check out the related comments in findfirst/findnext.
1179 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1180 (long)conn->dirptr,curr_dirpos));
1187 * fname may get mangled, dname is never mangled.
1188 * Whenever we're accessing the filesystem we use
1189 * pathreal which is composed from dname.
1195 /* Mangle fname if it's an illegal name. */
1196 if (mangle_must_mangle(dname,conn->params)) {
1197 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1198 continue; /* Error - couldn't mangle. */
1200 fname = mangled_name;
1203 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1204 got_match = mask_match(fname, mask, conn->case_sensitive);
1207 if(!got_match && check_mangled_names &&
1208 !mangle_is_8_3(fname, False, conn->params)) {
1210 * It turns out that NT matches wildcards against
1211 * both long *and* short names. This may explain some
1212 * of the wildcard wierdness from old DOS clients
1213 * that some people have been seeing.... JRA.
1215 /* Force the mangling into 8.3. */
1216 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1217 continue; /* Error - couldn't mangle. */
1220 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1221 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1226 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1228 if (dont_descend && !isdots) {
1234 pathreal = talloc_asprintf(ctx,
1239 pathreal = talloc_asprintf(ctx,
1249 if (INFO_LEVEL_IS_UNIX(info_level)) {
1250 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1251 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1252 pathreal,strerror(errno)));
1253 TALLOC_FREE(pathreal);
1256 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1257 /* Needed to show the msdfs symlinks as
1260 if(lp_host_msdfs() &&
1261 lp_msdfs_root(SNUM(conn)) &&
1262 ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) {
1263 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1266 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1270 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1271 pathreal,strerror(errno)));
1272 TALLOC_FREE(pathreal);
1278 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1280 mode = dos_mode(conn,pathreal,&sbuf);
1283 if (!dir_check_ftype(conn,mode,dirtype)) {
1284 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1285 TALLOC_FREE(pathreal);
1289 if (!(mode & aDIR)) {
1290 file_size = get_file_size(sbuf);
1292 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1294 mdate_ts = get_mtimespec(&sbuf);
1295 adate_ts = get_atimespec(&sbuf);
1296 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1298 if (lp_dos_filetime_resolution(SNUM(conn))) {
1299 dos_filetime_timespec(&create_date_ts);
1300 dos_filetime_timespec(&mdate_ts);
1301 dos_filetime_timespec(&adate_ts);
1304 create_date = convert_timespec_to_time_t(create_date_ts);
1305 mdate = convert_timespec_to_time_t(mdate_ts);
1306 adate = convert_timespec_to_time_t(adate_ts);
1308 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1312 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1319 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1321 switch (info_level) {
1322 case SMB_FIND_INFO_STANDARD:
1323 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1324 if(requires_resume_key) {
1328 srv_put_dos_date2(p,0,create_date);
1329 srv_put_dos_date2(p,4,adate);
1330 srv_put_dos_date2(p,8,mdate);
1331 SIVAL(p,12,(uint32)file_size);
1332 SIVAL(p,16,(uint32)allocation_size);
1336 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1337 p += ucs2_align(base_data, p, 0);
1339 len = srvstr_push(base_data, flags2, p,
1340 fname, PTR_DIFF(end_data, p),
1342 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1344 SCVAL(nameptr, -1, len - 2);
1346 SCVAL(nameptr, -1, 0);
1350 SCVAL(nameptr, -1, len - 1);
1352 SCVAL(nameptr, -1, 0);
1358 case SMB_FIND_EA_SIZE:
1359 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1360 if(requires_resume_key) {
1364 srv_put_dos_date2(p,0,create_date);
1365 srv_put_dos_date2(p,4,adate);
1366 srv_put_dos_date2(p,8,mdate);
1367 SIVAL(p,12,(uint32)file_size);
1368 SIVAL(p,16,(uint32)allocation_size);
1371 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1372 SIVAL(p,22,ea_size); /* Extended attributes */
1376 len = srvstr_push(base_data, flags2,
1377 p, fname, PTR_DIFF(end_data, p),
1378 STR_TERMINATE | STR_NOALIGN);
1379 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1392 SCVAL(nameptr,0,len);
1394 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1397 case SMB_FIND_EA_LIST:
1399 struct ea_list *file_list = NULL;
1402 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1406 if(requires_resume_key) {
1410 srv_put_dos_date2(p,0,create_date);
1411 srv_put_dos_date2(p,4,adate);
1412 srv_put_dos_date2(p,8,mdate);
1413 SIVAL(p,12,(uint32)file_size);
1414 SIVAL(p,16,(uint32)allocation_size);
1416 p += 22; /* p now points to the EA area. */
1418 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1419 name_list = ea_list_union(name_list, file_list, &ea_len);
1421 /* We need to determine if this entry will fit in the space available. */
1422 /* Max string size is 255 bytes. */
1423 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1424 /* Move the dirptr back to prev_dirpos */
1425 dptr_SeekDir(conn->dirptr, prev_dirpos);
1426 *out_of_space = True;
1427 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1428 return False; /* Not finished - just out of space */
1431 /* Push the ea_data followed by the name. */
1432 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1434 len = srvstr_push(base_data, flags2,
1435 p + 1, fname, PTR_DIFF(end_data, p+1),
1436 STR_TERMINATE | STR_NOALIGN);
1437 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1450 SCVAL(nameptr,0,len);
1452 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1456 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1457 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1458 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1460 SIVAL(p,0,reskey); p += 4;
1461 put_long_date_timespec(p,create_date_ts); p += 8;
1462 put_long_date_timespec(p,adate_ts); p += 8;
1463 put_long_date_timespec(p,mdate_ts); p += 8;
1464 put_long_date_timespec(p,mdate_ts); p += 8;
1465 SOFF_T(p,0,file_size); p += 8;
1466 SOFF_T(p,0,allocation_size); p += 8;
1467 SIVAL(p,0,nt_extmode); p += 4;
1468 q = p; p += 4; /* q is placeholder for name length. */
1470 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1471 SIVAL(p,0,ea_size); /* Extended attributes */
1474 /* Clear the short name buffer. This is
1475 * IMPORTANT as not doing so will trigger
1476 * a Win2k client bug. JRA.
1478 if (!was_8_3 && check_mangled_names) {
1479 if (!name_to_8_3(fname,mangled_name,True,
1481 /* Error - mangle failed ! */
1482 memset(mangled_name,'\0',12);
1484 mangled_name[12] = 0;
1485 len = srvstr_push(base_data, flags2,
1486 p+2, mangled_name, 24,
1487 STR_UPPER|STR_UNICODE);
1489 memset(p + 2 + len,'\0',24 - len);
1496 len = srvstr_push(base_data, flags2, p,
1497 fname, PTR_DIFF(end_data, p),
1498 STR_TERMINATE_ASCII);
1501 SIVAL(p,0,0); /* Ensure any padding is null. */
1502 len = PTR_DIFF(p, pdata);
1503 len = (len + 3) & ~3;
1508 case SMB_FIND_FILE_DIRECTORY_INFO:
1509 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1511 SIVAL(p,0,reskey); p += 4;
1512 put_long_date_timespec(p,create_date_ts); p += 8;
1513 put_long_date_timespec(p,adate_ts); p += 8;
1514 put_long_date_timespec(p,mdate_ts); p += 8;
1515 put_long_date_timespec(p,mdate_ts); p += 8;
1516 SOFF_T(p,0,file_size); p += 8;
1517 SOFF_T(p,0,allocation_size); p += 8;
1518 SIVAL(p,0,nt_extmode); p += 4;
1519 len = srvstr_push(base_data, flags2,
1520 p + 4, fname, PTR_DIFF(end_data, p+4),
1521 STR_TERMINATE_ASCII);
1524 SIVAL(p,0,0); /* Ensure any padding is null. */
1525 len = PTR_DIFF(p, pdata);
1526 len = (len + 3) & ~3;
1531 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1532 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1534 SIVAL(p,0,reskey); p += 4;
1535 put_long_date_timespec(p,create_date_ts); p += 8;
1536 put_long_date_timespec(p,adate_ts); p += 8;
1537 put_long_date_timespec(p,mdate_ts); p += 8;
1538 put_long_date_timespec(p,mdate_ts); p += 8;
1539 SOFF_T(p,0,file_size); p += 8;
1540 SOFF_T(p,0,allocation_size); p += 8;
1541 SIVAL(p,0,nt_extmode); p += 4;
1542 q = p; p += 4; /* q is placeholder for name length. */
1544 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1545 SIVAL(p,0,ea_size); /* Extended attributes */
1548 len = srvstr_push(base_data, flags2, p,
1549 fname, PTR_DIFF(end_data, p),
1550 STR_TERMINATE_ASCII);
1554 SIVAL(p,0,0); /* Ensure any padding is null. */
1555 len = PTR_DIFF(p, pdata);
1556 len = (len + 3) & ~3;
1561 case SMB_FIND_FILE_NAMES_INFO:
1562 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1564 SIVAL(p,0,reskey); p += 4;
1566 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1567 acl on a dir (tridge) */
1568 len = srvstr_push(base_data, flags2, p,
1569 fname, PTR_DIFF(end_data, p),
1570 STR_TERMINATE_ASCII);
1573 SIVAL(p,0,0); /* Ensure any padding is null. */
1574 len = PTR_DIFF(p, pdata);
1575 len = (len + 3) & ~3;
1580 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1581 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1583 SIVAL(p,0,reskey); p += 4;
1584 put_long_date_timespec(p,create_date_ts); p += 8;
1585 put_long_date_timespec(p,adate_ts); p += 8;
1586 put_long_date_timespec(p,mdate_ts); p += 8;
1587 put_long_date_timespec(p,mdate_ts); p += 8;
1588 SOFF_T(p,0,file_size); p += 8;
1589 SOFF_T(p,0,allocation_size); p += 8;
1590 SIVAL(p,0,nt_extmode); p += 4;
1591 q = p; p += 4; /* q is placeholder for name length. */
1593 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1594 SIVAL(p,0,ea_size); /* Extended attributes */
1597 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1598 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1599 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1600 len = srvstr_push(base_data, flags2, p,
1601 fname, PTR_DIFF(end_data, p),
1602 STR_TERMINATE_ASCII);
1605 SIVAL(p,0,0); /* Ensure any padding is null. */
1606 len = PTR_DIFF(p, pdata);
1607 len = (len + 3) & ~3;
1612 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1613 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1614 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1616 SIVAL(p,0,reskey); p += 4;
1617 put_long_date_timespec(p,create_date_ts); p += 8;
1618 put_long_date_timespec(p,adate_ts); p += 8;
1619 put_long_date_timespec(p,mdate_ts); p += 8;
1620 put_long_date_timespec(p,mdate_ts); p += 8;
1621 SOFF_T(p,0,file_size); p += 8;
1622 SOFF_T(p,0,allocation_size); p += 8;
1623 SIVAL(p,0,nt_extmode); p += 4;
1624 q = p; p += 4; /* q is placeholder for name length */
1626 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1627 SIVAL(p,0,ea_size); /* Extended attributes */
1630 /* Clear the short name buffer. This is
1631 * IMPORTANT as not doing so will trigger
1632 * a Win2k client bug. JRA.
1634 if (!was_8_3 && check_mangled_names) {
1635 if (!name_to_8_3(fname,mangled_name,True,
1637 /* Error - mangle failed ! */
1638 memset(mangled_name,'\0',12);
1640 mangled_name[12] = 0;
1641 len = srvstr_push(base_data, flags2,
1642 p+2, mangled_name, 24,
1643 STR_UPPER|STR_UNICODE);
1646 memset(p + 2 + len,'\0',24 - len);
1653 SSVAL(p,0,0); p += 2; /* Reserved ? */
1654 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1655 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1656 len = srvstr_push(base_data, flags2, p,
1657 fname, PTR_DIFF(end_data, p),
1658 STR_TERMINATE_ASCII);
1661 SIVAL(p,0,0); /* Ensure any padding is null. */
1662 len = PTR_DIFF(p, pdata);
1663 len = (len + 3) & ~3;
1668 /* CIFS UNIX Extension. */
1670 case SMB_FIND_FILE_UNIX:
1671 case SMB_FIND_FILE_UNIX_INFO2:
1673 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1675 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1677 if (info_level == SMB_FIND_FILE_UNIX) {
1678 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1679 p = store_file_unix_basic(conn, p,
1681 len = srvstr_push(base_data, flags2, p,
1682 fname, PTR_DIFF(end_data, p),
1685 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1686 p = store_file_unix_basic_info2(conn, p,
1690 len = srvstr_push(base_data, flags2, p, fname,
1691 PTR_DIFF(end_data, p), 0);
1692 SIVAL(nameptr, 0, len);
1696 SIVAL(p,0,0); /* Ensure any padding is null. */
1698 len = PTR_DIFF(p, pdata);
1699 len = (len + 3) & ~3;
1700 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1702 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1711 if (PTR_DIFF(p,pdata) > space_remaining) {
1712 /* Move the dirptr back to prev_dirpos */
1713 dptr_SeekDir(conn->dirptr, prev_dirpos);
1714 *out_of_space = True;
1715 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1716 return False; /* Not finished - just out of space */
1719 /* Setup the last entry pointer, as an offset from base_data */
1720 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1721 /* Advance the data pointer to the next slot */
1727 /****************************************************************************
1728 Reply to a TRANS2_FINDFIRST.
1729 ****************************************************************************/
1731 static void call_trans2findfirst(connection_struct *conn,
1732 struct smb_request *req,
1733 char **pparams, int total_params,
1734 char **ppdata, int total_data,
1735 unsigned int max_data_bytes)
1737 /* We must be careful here that we don't return more than the
1738 allowed number of data bytes. If this means returning fewer than
1739 maxentries then so be it. We assume that the redirector has
1740 enough room for the fixed number of parameter bytes it has
1742 char *params = *pparams;
1743 char *pdata = *ppdata;
1747 uint16 findfirst_flags;
1748 bool close_after_first;
1750 bool requires_resume_key;
1752 char *directory = NULL;
1753 const char *mask = NULL;
1755 int last_entry_off=0;
1759 bool finished = False;
1760 bool dont_descend = False;
1761 bool out_of_space = False;
1762 int space_remaining;
1763 bool mask_contains_wcard = False;
1764 SMB_STRUCT_STAT sbuf;
1765 struct ea_list *ea_list = NULL;
1766 NTSTATUS ntstatus = NT_STATUS_OK;
1767 TALLOC_CTX *ctx = talloc_tos();
1769 if (total_params < 13) {
1770 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1774 dirtype = SVAL(params,0);
1775 maxentries = SVAL(params,2);
1776 findfirst_flags = SVAL(params,4);
1777 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1778 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1779 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1780 info_level = SVAL(params,6);
1782 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1783 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1784 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1785 info_level, max_data_bytes));
1788 /* W2K3 seems to treat zero as 1. */
1792 switch (info_level) {
1793 case SMB_FIND_INFO_STANDARD:
1794 case SMB_FIND_EA_SIZE:
1795 case SMB_FIND_EA_LIST:
1796 case SMB_FIND_FILE_DIRECTORY_INFO:
1797 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1798 case SMB_FIND_FILE_NAMES_INFO:
1799 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1800 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1801 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1803 case SMB_FIND_FILE_UNIX:
1804 case SMB_FIND_FILE_UNIX_INFO2:
1805 if (!lp_unix_extensions()) {
1806 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1811 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1815 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1816 params+12, total_params - 12,
1817 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1818 if (!NT_STATUS_IS_OK(ntstatus)) {
1819 reply_nterror(req, ntstatus);
1823 ntstatus = resolve_dfspath_wcard(ctx, conn,
1824 req->flags2 & FLAGS2_DFS_PATHNAMES,
1827 &mask_contains_wcard);
1828 if (!NT_STATUS_IS_OK(ntstatus)) {
1829 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1830 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1831 ERRSRV, ERRbadpath);
1834 reply_nterror(req, ntstatus);
1838 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1839 if (!NT_STATUS_IS_OK(ntstatus)) {
1840 reply_nterror(req, ntstatus);
1844 ntstatus = check_name(conn, directory);
1845 if (!NT_STATUS_IS_OK(ntstatus)) {
1846 reply_nterror(req, ntstatus);
1850 p = strrchr_m(directory,'/');
1852 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1853 if((directory[0] == '.') && (directory[1] == '\0')) {
1855 mask_contains_wcard = True;
1859 directory = talloc_strdup(talloc_tos(), "./");
1861 reply_nterror(req, NT_STATUS_NO_MEMORY);
1869 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1871 if (info_level == SMB_FIND_EA_LIST) {
1874 if (total_data < 4) {
1875 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1879 ea_size = IVAL(pdata,0);
1880 if (ea_size != total_data) {
1881 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1882 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1883 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1887 if (!lp_ea_support(SNUM(conn))) {
1888 reply_doserror(req, ERRDOS, ERReasnotsupported);
1892 /* Pull out the list of names. */
1893 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1900 *ppdata = (char *)SMB_REALLOC(
1901 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1902 if(*ppdata == NULL ) {
1903 reply_nterror(req, NT_STATUS_NO_MEMORY);
1907 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1909 /* Realloc the params space */
1910 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1911 if (*pparams == NULL) {
1912 reply_nterror(req, NT_STATUS_NO_MEMORY);
1917 /* Save the wildcard match and attribs we are using on this directory -
1918 needed as lanman2 assumes these are being saved between calls */
1920 ntstatus = dptr_create(conn,
1926 mask_contains_wcard,
1930 if (!NT_STATUS_IS_OK(ntstatus)) {
1931 reply_nterror(req, ntstatus);
1935 dptr_num = dptr_dnum(conn->dirptr);
1936 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1938 /* We don't need to check for VOL here as this is returned by
1939 a different TRANS2 call. */
1941 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1942 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1943 dont_descend = True;
1946 space_remaining = max_data_bytes;
1947 out_of_space = False;
1949 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1950 bool got_exact_match = False;
1952 /* this is a heuristic to avoid seeking the dirptr except when
1953 absolutely necessary. It allows for a filename of about 40 chars */
1954 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1955 out_of_space = True;
1958 TALLOC_CTX *sub_ctx = talloc_stackframe();
1960 finished = !get_lanman2_dir_entry(sub_ctx,
1963 mask,dirtype,info_level,
1964 requires_resume_key,dont_descend,
1966 space_remaining, &out_of_space,
1968 &last_entry_off, ea_list);
1970 TALLOC_FREE(sub_ctx);
1973 if (finished && out_of_space)
1976 if (!finished && !out_of_space)
1980 * As an optimisation if we know we aren't looking
1981 * for a wildcard name (ie. the name matches the wildcard exactly)
1982 * then we can finish on any (first) match.
1983 * This speeds up large directory searches. JRA.
1989 /* Ensure space_remaining never goes -ve. */
1990 if (PTR_DIFF(p,pdata) > max_data_bytes) {
1991 space_remaining = 0;
1992 out_of_space = true;
1994 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1998 /* Check if we can close the dirptr */
1999 if(close_after_first || (finished && close_if_end)) {
2000 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2001 dptr_close(&dptr_num);
2005 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2006 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2007 * the protocol level is less than NT1. Tested with smbclient. JRA.
2008 * This should fix the OS/2 client bug #2335.
2011 if(numentries == 0) {
2012 dptr_close(&dptr_num);
2013 if (Protocol < PROTOCOL_NT1) {
2014 reply_doserror(req, ERRDOS, ERRnofiles);
2017 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2018 ERRDOS, ERRbadfile);
2023 /* At this point pdata points to numentries directory entries. */
2025 /* Set up the return parameter block */
2026 SSVAL(params,0,dptr_num);
2027 SSVAL(params,2,numentries);
2028 SSVAL(params,4,finished);
2029 SSVAL(params,6,0); /* Never an EA error */
2030 SSVAL(params,8,last_entry_off);
2032 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2035 if ((! *directory) && dptr_path(dptr_num)) {
2036 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2038 reply_nterror(req, NT_STATUS_NO_MEMORY);
2042 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2043 smb_fn_name(CVAL(req->inbuf,smb_com)),
2044 mask, directory, dirtype, numentries ) );
2047 * Force a name mangle here to ensure that the
2048 * mask as an 8.3 name is top of the mangled cache.
2049 * The reasons for this are subtle. Don't remove
2050 * this code unless you know what you are doing
2051 * (see PR#13758). JRA.
2054 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2055 char mangled_name[13];
2056 name_to_8_3(mask, mangled_name, True, conn->params);
2062 /****************************************************************************
2063 Reply to a TRANS2_FINDNEXT.
2064 ****************************************************************************/
2066 static void call_trans2findnext(connection_struct *conn,
2067 struct smb_request *req,
2068 char **pparams, int total_params,
2069 char **ppdata, int total_data,
2070 unsigned int max_data_bytes)
2072 /* We must be careful here that we don't return more than the
2073 allowed number of data bytes. If this means returning fewer than
2074 maxentries then so be it. We assume that the redirector has
2075 enough room for the fixed number of parameter bytes it has
2077 char *params = *pparams;
2078 char *pdata = *ppdata;
2084 uint16 findnext_flags;
2085 bool close_after_request;
2087 bool requires_resume_key;
2089 bool mask_contains_wcard = False;
2090 char *resume_name = NULL;
2091 const char *mask = NULL;
2092 const char *directory = NULL;
2096 int i, last_entry_off=0;
2097 bool finished = False;
2098 bool dont_descend = False;
2099 bool out_of_space = False;
2100 int space_remaining;
2101 struct ea_list *ea_list = NULL;
2102 NTSTATUS ntstatus = NT_STATUS_OK;
2103 TALLOC_CTX *ctx = talloc_tos();
2105 if (total_params < 13) {
2106 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2110 dptr_num = SVAL(params,0);
2111 maxentries = SVAL(params,2);
2112 info_level = SVAL(params,4);
2113 resume_key = IVAL(params,6);
2114 findnext_flags = SVAL(params,10);
2115 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2116 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2117 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2118 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2120 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2122 total_params - 12, STR_TERMINATE, &ntstatus,
2123 &mask_contains_wcard);
2124 if (!NT_STATUS_IS_OK(ntstatus)) {
2125 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2126 complain (it thinks we're asking for the directory above the shared
2127 path or an invalid name). Catch this as the resume name is only compared, never used in
2128 a file access. JRA. */
2129 srvstr_pull_talloc(ctx, params, req->flags2,
2130 &resume_name, params+12,
2134 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2135 reply_nterror(req, ntstatus);
2140 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2141 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2142 resume_key = %d resume name = %s continue=%d level = %d\n",
2143 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2144 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2147 /* W2K3 seems to treat zero as 1. */
2151 switch (info_level) {
2152 case SMB_FIND_INFO_STANDARD:
2153 case SMB_FIND_EA_SIZE:
2154 case SMB_FIND_EA_LIST:
2155 case SMB_FIND_FILE_DIRECTORY_INFO:
2156 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2157 case SMB_FIND_FILE_NAMES_INFO:
2158 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2159 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2160 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2162 case SMB_FIND_FILE_UNIX:
2163 case SMB_FIND_FILE_UNIX_INFO2:
2164 if (!lp_unix_extensions()) {
2165 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2170 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2174 if (info_level == SMB_FIND_EA_LIST) {
2177 if (total_data < 4) {
2178 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2182 ea_size = IVAL(pdata,0);
2183 if (ea_size != total_data) {
2184 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2185 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2186 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2190 if (!lp_ea_support(SNUM(conn))) {
2191 reply_doserror(req, ERRDOS, ERReasnotsupported);
2195 /* Pull out the list of names. */
2196 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2198 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2203 *ppdata = (char *)SMB_REALLOC(
2204 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2205 if(*ppdata == NULL) {
2206 reply_nterror(req, NT_STATUS_NO_MEMORY);
2211 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2213 /* Realloc the params space */
2214 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2215 if(*pparams == NULL ) {
2216 reply_nterror(req, NT_STATUS_NO_MEMORY);
2222 /* Check that the dptr is valid */
2223 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2224 reply_doserror(req, ERRDOS, ERRnofiles);
2228 string_set(&conn->dirpath,dptr_path(dptr_num));
2230 /* Get the wildcard mask from the dptr */
2231 if((p = dptr_wcard(dptr_num))== NULL) {
2232 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2233 reply_doserror(req, ERRDOS, ERRnofiles);
2238 directory = conn->dirpath;
2240 /* Get the attr mask from the dptr */
2241 dirtype = dptr_attr(dptr_num);
2243 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2244 dptr_num, mask, dirtype,
2246 dptr_TellDir(conn->dirptr)));
2248 /* We don't need to check for VOL here as this is returned by
2249 a different TRANS2 call. */
2251 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2252 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2253 dont_descend = True;
2256 space_remaining = max_data_bytes;
2257 out_of_space = False;
2260 * Seek to the correct position. We no longer use the resume key but
2261 * depend on the last file name instead.
2264 if(*resume_name && !continue_bit) {
2267 long current_pos = 0;
2269 * Remember, name_to_8_3 is called by
2270 * get_lanman2_dir_entry(), so the resume name
2271 * could be mangled. Ensure we check the unmangled name.
2274 if (mangle_is_mangled(resume_name, conn->params)) {
2275 char *new_resume_name = NULL;
2276 mangle_lookup_name_from_8_3(ctx,
2280 if (new_resume_name) {
2281 resume_name = new_resume_name;
2286 * Fix for NT redirector problem triggered by resume key indexes
2287 * changing between directory scans. We now return a resume key of 0
2288 * and instead look for the filename to continue from (also given
2289 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2290 * findfirst/findnext (as is usual) then the directory pointer
2291 * should already be at the correct place.
2294 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2295 } /* end if resume_name && !continue_bit */
2297 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2298 bool got_exact_match = False;
2300 /* this is a heuristic to avoid seeking the dirptr except when
2301 absolutely necessary. It allows for a filename of about 40 chars */
2302 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2303 out_of_space = True;
2306 TALLOC_CTX *sub_ctx = talloc_stackframe();
2308 finished = !get_lanman2_dir_entry(sub_ctx,
2311 mask,dirtype,info_level,
2312 requires_resume_key,dont_descend,
2314 space_remaining, &out_of_space,
2316 &last_entry_off, ea_list);
2318 TALLOC_FREE(sub_ctx);
2321 if (finished && out_of_space)
2324 if (!finished && !out_of_space)
2328 * As an optimisation if we know we aren't looking
2329 * for a wildcard name (ie. the name matches the wildcard exactly)
2330 * then we can finish on any (first) match.
2331 * This speeds up large directory searches. JRA.
2337 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2340 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2341 smb_fn_name(CVAL(req->inbuf,smb_com)),
2342 mask, directory, dirtype, numentries ) );
2344 /* Check if we can close the dirptr */
2345 if(close_after_request || (finished && close_if_end)) {
2346 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2347 dptr_close(&dptr_num); /* This frees up the saved mask */
2350 /* Set up the return parameter block */
2351 SSVAL(params,0,numentries);
2352 SSVAL(params,2,finished);
2353 SSVAL(params,4,0); /* Never an EA error */
2354 SSVAL(params,6,last_entry_off);
2356 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2362 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2364 E_md4hash(lp_servicename(SNUM(conn)),objid);
2368 /****************************************************************************
2369 Reply to a TRANS2_QFSINFO (query filesystem info).
2370 ****************************************************************************/
2372 static void call_trans2qfsinfo(connection_struct *conn,
2373 struct smb_request *req,
2374 char **pparams, int total_params,
2375 char **ppdata, int total_data,
2376 unsigned int max_data_bytes)
2378 char *pdata, *end_data;
2379 char *params = *pparams;
2383 const char *vname = volume_label(SNUM(conn));
2384 int snum = SNUM(conn);
2385 char *fstype = lp_fstype(SNUM(conn));
2388 if (total_params < 2) {
2389 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2393 info_level = SVAL(params,0);
2396 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2397 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2398 "info level (0x%x) on IPC$.\n",
2399 (unsigned int)info_level));
2400 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2405 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2406 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2407 DEBUG(0,("call_trans2qfsinfo: encryption required "
2408 "and info level 0x%x sent.\n",
2409 (unsigned int)info_level));
2410 exit_server_cleanly("encryption required "
2416 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2418 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2419 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2420 reply_doserror(req, ERRSRV, ERRinvdevice);
2424 *ppdata = (char *)SMB_REALLOC(
2425 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2426 if (*ppdata == NULL ) {
2427 reply_nterror(req, NT_STATUS_NO_MEMORY);
2432 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2433 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2435 switch (info_level) {
2436 case SMB_INFO_ALLOCATION:
2438 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2440 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2441 reply_unixerror(req, ERRHRD, ERRgeneral);
2445 block_size = lp_block_size(snum);
2446 if (bsize < block_size) {
2447 SMB_BIG_UINT factor = block_size/bsize;
2452 if (bsize > block_size) {
2453 SMB_BIG_UINT factor = bsize/block_size;
2458 bytes_per_sector = 512;
2459 sectors_per_unit = bsize/bytes_per_sector;
2461 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2462 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2463 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2465 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2466 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2467 SIVAL(pdata,l1_cUnit,dsize);
2468 SIVAL(pdata,l1_cUnitAvail,dfree);
2469 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2473 case SMB_INFO_VOLUME:
2474 /* Return volume name */
2476 * Add volume serial number - hash of a combination of
2477 * the called hostname and the service name.
2479 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2481 * Win2k3 and previous mess this up by sending a name length
2482 * one byte short. I believe only older clients (OS/2 Win9x) use
2483 * this call so try fixing this by adding a terminating null to
2484 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2488 pdata+l2_vol_szVolLabel, vname,
2489 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2490 STR_NOALIGN|STR_TERMINATE);
2491 SCVAL(pdata,l2_vol_cch,len);
2492 data_len = l2_vol_szVolLabel + len;
2493 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2494 (unsigned)st.st_ctime, len, vname));
2497 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2498 case SMB_FS_ATTRIBUTE_INFORMATION:
2501 #if defined(HAVE_SYS_QUOTAS)
2502 quota_flag = FILE_VOLUME_QUOTAS;
2505 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2506 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2507 FILE_SUPPORTS_OBJECT_IDS|
2508 FILE_UNICODE_ON_DISK|
2509 quota_flag); /* FS ATTRIBUTES */
2511 SIVAL(pdata,4,255); /* Max filename component length */
2512 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2513 and will think we can't do long filenames */
2514 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2515 PTR_DIFF(end_data, pdata+12),
2518 data_len = 12 + len;
2521 case SMB_QUERY_FS_LABEL_INFO:
2522 case SMB_FS_LABEL_INFORMATION:
2523 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2524 PTR_DIFF(end_data, pdata+4), 0);
2529 case SMB_QUERY_FS_VOLUME_INFO:
2530 case SMB_FS_VOLUME_INFORMATION:
2533 * Add volume serial number - hash of a combination of
2534 * the called hostname and the service name.
2536 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2537 (str_checksum(get_local_machine_name())<<16));
2539 /* Max label len is 32 characters. */
2540 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2541 PTR_DIFF(end_data, pdata+18),
2543 SIVAL(pdata,12,len);
2546 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2547 (int)strlen(vname),vname, lp_servicename(snum)));
2550 case SMB_QUERY_FS_SIZE_INFO:
2551 case SMB_FS_SIZE_INFORMATION:
2553 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2555 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2556 reply_unixerror(req, ERRHRD, ERRgeneral);
2559 block_size = lp_block_size(snum);
2560 if (bsize < block_size) {
2561 SMB_BIG_UINT factor = block_size/bsize;
2566 if (bsize > block_size) {
2567 SMB_BIG_UINT factor = bsize/block_size;
2572 bytes_per_sector = 512;
2573 sectors_per_unit = bsize/bytes_per_sector;
2574 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2575 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2576 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2577 SBIG_UINT(pdata,0,dsize);
2578 SBIG_UINT(pdata,8,dfree);
2579 SIVAL(pdata,16,sectors_per_unit);
2580 SIVAL(pdata,20,bytes_per_sector);
2584 case SMB_FS_FULL_SIZE_INFORMATION:
2586 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2588 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2589 reply_unixerror(req, ERRHRD, ERRgeneral);
2592 block_size = lp_block_size(snum);
2593 if (bsize < block_size) {
2594 SMB_BIG_UINT factor = block_size/bsize;
2599 if (bsize > block_size) {
2600 SMB_BIG_UINT factor = bsize/block_size;
2605 bytes_per_sector = 512;
2606 sectors_per_unit = bsize/bytes_per_sector;
2607 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2608 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2609 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2610 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2611 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2612 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2613 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2614 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2618 case SMB_QUERY_FS_DEVICE_INFO:
2619 case SMB_FS_DEVICE_INFORMATION:
2621 SIVAL(pdata,0,0); /* dev type */
2622 SIVAL(pdata,4,0); /* characteristics */
2625 #ifdef HAVE_SYS_QUOTAS
2626 case SMB_FS_QUOTA_INFORMATION:
2628 * what we have to send --metze:
2630 * Unknown1: 24 NULL bytes
2631 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2632 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2633 * Quota Flags: 2 byte :
2634 * Unknown3: 6 NULL bytes
2638 * details for Quota Flags:
2640 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2641 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2642 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2643 * 0x0001 Enable Quotas: enable quota for this fs
2647 /* we need to fake up a fsp here,
2648 * because its not send in this call
2651 SMB_NTQUOTA_STRUCT quotas;
2654 ZERO_STRUCT(quotas);
2660 if (current_user.ut.uid != 0) {
2661 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2662 lp_servicename(SNUM(conn)),conn->user));
2663 reply_doserror(req, ERRDOS, ERRnoaccess);
2667 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2668 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2669 reply_doserror(req, ERRSRV, ERRerror);
2675 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2677 /* Unknown1 24 NULL bytes*/
2678 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2679 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2680 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2682 /* Default Soft Quota 8 bytes */
2683 SBIG_UINT(pdata,24,quotas.softlim);
2685 /* Default Hard Quota 8 bytes */
2686 SBIG_UINT(pdata,32,quotas.hardlim);
2688 /* Quota flag 2 bytes */
2689 SSVAL(pdata,40,quotas.qflags);
2691 /* Unknown3 6 NULL bytes */
2697 #endif /* HAVE_SYS_QUOTAS */
2698 case SMB_FS_OBJECTID_INFORMATION:
2700 unsigned char objid[16];
2701 memcpy(pdata,create_volume_objectid(conn, objid),16);
2707 * Query the version and capabilities of the CIFS UNIX extensions
2711 case SMB_QUERY_CIFS_UNIX_INFO:
2713 bool large_write = lp_min_receive_file_size() &&
2714 !srv_is_signing_active();
2715 bool large_read = !srv_is_signing_active();
2716 int encrypt_caps = 0;
2718 if (!lp_unix_extensions()) {
2719 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2723 switch (conn->encrypt_level) {
2729 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2732 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2733 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2734 large_write = false;
2740 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2741 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2743 /* We have POSIX ACLs, pathname, encryption,
2744 * large read/write, and locking capability. */
2746 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2747 CIFS_UNIX_POSIX_ACLS_CAP|
2748 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2749 CIFS_UNIX_FCNTL_LOCKS_CAP|
2750 CIFS_UNIX_EXTATTR_CAP|
2751 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2753 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2755 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2759 case SMB_QUERY_POSIX_FS_INFO:
2762 vfs_statvfs_struct svfs;
2764 if (!lp_unix_extensions()) {
2765 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2769 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2773 SIVAL(pdata,0,svfs.OptimalTransferSize);
2774 SIVAL(pdata,4,svfs.BlockSize);
2775 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2776 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2777 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2778 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2779 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2780 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2781 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2783 } else if (rc == EOPNOTSUPP) {
2784 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2786 #endif /* EOPNOTSUPP */
2788 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2789 reply_doserror(req, ERRSRV, ERRerror);
2795 case SMB_QUERY_POSIX_WHOAMI:
2801 if (!lp_unix_extensions()) {
2802 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2806 if (max_data_bytes < 40) {
2807 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2811 /* We ARE guest if global_sid_Builtin_Guests is
2812 * in our list of SIDs.
2814 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2815 current_user.nt_user_token)) {
2816 flags |= SMB_WHOAMI_GUEST;
2819 /* We are NOT guest if global_sid_Authenticated_Users
2820 * is in our list of SIDs.
2822 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2823 current_user.nt_user_token)) {
2824 flags &= ~SMB_WHOAMI_GUEST;
2827 /* NOTE: 8 bytes for UID/GID, irrespective of native
2828 * platform size. This matches
2829 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2831 data_len = 4 /* flags */
2838 + 4 /* pad/reserved */
2839 + (current_user.ut.ngroups * 8)
2841 + (current_user.nt_user_token->num_sids *
2845 SIVAL(pdata, 0, flags);
2846 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2847 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2848 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2851 if (data_len >= max_data_bytes) {
2852 /* Potential overflow, skip the GIDs and SIDs. */
2854 SIVAL(pdata, 24, 0); /* num_groups */
2855 SIVAL(pdata, 28, 0); /* num_sids */
2856 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2857 SIVAL(pdata, 36, 0); /* reserved */
2863 SIVAL(pdata, 24, current_user.ut.ngroups);
2865 current_user.nt_user_token->num_sids);
2867 /* We walk the SID list twice, but this call is fairly
2868 * infrequent, and I don't expect that it's performance
2869 * sensitive -- jpeach
2871 for (i = 0, sid_bytes = 0;
2872 i < current_user.nt_user_token->num_sids; ++i) {
2873 sid_bytes += ndr_size_dom_sid(
2874 ¤t_user.nt_user_token->user_sids[i], 0);
2877 /* SID list byte count */
2878 SIVAL(pdata, 32, sid_bytes);
2880 /* 4 bytes pad/reserved - must be zero */
2881 SIVAL(pdata, 36, 0);
2885 for (i = 0; i < current_user.ut.ngroups; ++i) {
2886 SBIG_UINT(pdata, data_len,
2887 (SMB_BIG_UINT)current_user.ut.groups[i]);
2893 i < current_user.nt_user_token->num_sids; ++i) {
2894 int sid_len = ndr_size_dom_sid(
2895 ¤t_user.nt_user_token->user_sids[i], 0);
2897 sid_linearize(pdata + data_len, sid_len,
2898 ¤t_user.nt_user_token->user_sids[i]);
2899 data_len += sid_len;
2905 case SMB_MAC_QUERY_FS_INFO:
2907 * Thursby MAC extension... ONLY on NTFS filesystems
2908 * once we do streams then we don't need this
2910 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2912 SIVAL(pdata,84,0x100); /* Don't support mac... */
2917 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2922 send_trans2_replies(conn, req, params, 0, pdata, data_len,
2925 DEBUG( 4, ( "%s info_level = %d\n",
2926 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2931 /****************************************************************************
2932 Reply to a TRANS2_SETFSINFO (set filesystem info).
2933 ****************************************************************************/
2935 static void call_trans2setfsinfo(connection_struct *conn,
2936 struct smb_request *req,
2937 char **pparams, int total_params,
2938 char **ppdata, int total_data,
2939 unsigned int max_data_bytes)
2941 char *pdata = *ppdata;
2942 char *params = *pparams;
2945 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2948 if (total_params < 4) {
2949 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2951 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2955 info_level = SVAL(params,2);
2958 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
2959 info_level != SMB_SET_CIFS_UNIX_INFO) {
2960 DEBUG(0,("call_trans2setfsinfo: not an allowed "
2961 "info level (0x%x) on IPC$.\n",
2962 (unsigned int)info_level));
2963 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2968 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2969 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
2970 DEBUG(0,("call_trans2setfsinfo: encryption required "
2971 "and info level 0x%x sent.\n",
2972 (unsigned int)info_level));
2973 exit_server_cleanly("encryption required "
2979 switch(info_level) {
2980 case SMB_SET_CIFS_UNIX_INFO:
2982 uint16 client_unix_major;
2983 uint16 client_unix_minor;
2984 uint32 client_unix_cap_low;
2985 uint32 client_unix_cap_high;
2987 if (!lp_unix_extensions()) {
2989 NT_STATUS_INVALID_LEVEL);
2993 /* There should be 12 bytes of capabilities set. */
2994 if (total_data < 8) {
2997 NT_STATUS_INVALID_PARAMETER);
3000 client_unix_major = SVAL(pdata,0);
3001 client_unix_minor = SVAL(pdata,2);
3002 client_unix_cap_low = IVAL(pdata,4);
3003 client_unix_cap_high = IVAL(pdata,8);
3004 /* Just print these values for now. */
3005 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3006 cap_low = 0x%x, cap_high = 0x%x\n",
3007 (unsigned int)client_unix_major,
3008 (unsigned int)client_unix_minor,
3009 (unsigned int)client_unix_cap_low,
3010 (unsigned int)client_unix_cap_high ));
3012 /* Here is where we must switch to posix pathname processing... */
3013 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3014 lp_set_posix_pathnames();
3015 mangle_change_to_posix();
3018 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3019 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3020 /* Client that knows how to do posix locks,
3021 * but not posix open/mkdir operations. Set a
3022 * default type for read/write checks. */
3024 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3030 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3033 size_t param_len = 0;
3034 size_t data_len = total_data;
3036 if (!lp_unix_extensions()) {
3039 NT_STATUS_INVALID_LEVEL);
3043 if (lp_smb_encrypt(SNUM(conn)) == false) {
3046 NT_STATUS_NOT_SUPPORTED);
3050 DEBUG( 4,("call_trans2setfsinfo: "
3051 "request transport encrption.\n"));
3053 status = srv_request_encryption_setup(conn,
3054 (unsigned char **)ppdata,
3056 (unsigned char **)pparams,
3059 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3060 !NT_STATUS_IS_OK(status)) {
3061 reply_nterror(req, status);
3065 send_trans2_replies(conn, req,
3072 if (NT_STATUS_IS_OK(status)) {
3073 /* Server-side transport
3074 * encryption is now *on*. */
3075 status = srv_encryption_start(conn);
3076 if (!NT_STATUS_IS_OK(status)) {
3077 exit_server_cleanly(
3078 "Failure in setting "
3079 "up encrypted transport");
3085 case SMB_FS_QUOTA_INFORMATION:
3087 files_struct *fsp = NULL;
3088 SMB_NTQUOTA_STRUCT quotas;
3090 ZERO_STRUCT(quotas);
3093 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3094 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3095 lp_servicename(SNUM(conn)),conn->user));
3096 reply_doserror(req, ERRSRV, ERRaccess);
3100 /* note: normaly there're 48 bytes,
3101 * but we didn't use the last 6 bytes for now
3104 fsp = file_fsp(SVAL(params,0));
3105 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3106 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3108 req, NT_STATUS_INVALID_HANDLE);
3112 if (total_data < 42) {
3113 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3117 NT_STATUS_INVALID_PARAMETER);
3121 /* unknown_1 24 NULL bytes in pdata*/
3123 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3124 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3125 #ifdef LARGE_SMB_OFF_T
3126 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3127 #else /* LARGE_SMB_OFF_T */
3128 if ((IVAL(pdata,28) != 0)&&
3129 ((quotas.softlim != 0xFFFFFFFF)||
3130 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3131 /* more than 32 bits? */
3134 NT_STATUS_INVALID_PARAMETER);
3137 #endif /* LARGE_SMB_OFF_T */
3139 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3140 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3141 #ifdef LARGE_SMB_OFF_T
3142 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3143 #else /* LARGE_SMB_OFF_T */
3144 if ((IVAL(pdata,36) != 0)&&
3145 ((quotas.hardlim != 0xFFFFFFFF)||
3146 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3147 /* more than 32 bits? */
3150 NT_STATUS_INVALID_PARAMETER);
3153 #endif /* LARGE_SMB_OFF_T */
3155 /* quota_flags 2 bytes **/
3156 quotas.qflags = SVAL(pdata,40);
3158 /* unknown_2 6 NULL bytes follow*/
3160 /* now set the quotas */
3161 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3162 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3163 reply_doserror(req, ERRSRV, ERRerror);
3170 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3172 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3178 * sending this reply works fine,
3179 * but I'm not sure it's the same
3180 * like windows do...
3183 reply_outbuf(req, 10, 0);
3186 #if defined(HAVE_POSIX_ACLS)
3187 /****************************************************************************
3188 Utility function to count the number of entries in a POSIX acl.
3189 ****************************************************************************/
3191 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3193 unsigned int ace_count = 0;
3194 int entry_id = SMB_ACL_FIRST_ENTRY;
3195 SMB_ACL_ENTRY_T entry;
3197 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3199 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3200 entry_id = SMB_ACL_NEXT_ENTRY;
3207 /****************************************************************************
3208 Utility function to marshall a POSIX acl into wire format.
3209 ****************************************************************************/
3211 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3213 int entry_id = SMB_ACL_FIRST_ENTRY;
3214 SMB_ACL_ENTRY_T entry;
3216 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3217 SMB_ACL_TAG_T tagtype;
3218 SMB_ACL_PERMSET_T permset;
3219 unsigned char perms = 0;
3220 unsigned int own_grp;
3223 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3224 entry_id = SMB_ACL_NEXT_ENTRY;
3227 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3228 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3232 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3233 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3237 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3238 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3239 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3241 SCVAL(pdata,1,perms);
3244 case SMB_ACL_USER_OBJ:
3245 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3246 own_grp = (unsigned int)pst->st_uid;
3247 SIVAL(pdata,2,own_grp);
3252 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3254 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3257 own_grp = (unsigned int)*puid;
3258 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3259 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3260 SIVAL(pdata,2,own_grp);
3264 case SMB_ACL_GROUP_OBJ:
3265 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3266 own_grp = (unsigned int)pst->st_gid;
3267 SIVAL(pdata,2,own_grp);
3272 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3274 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3277 own_grp = (unsigned int)*pgid;
3278 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3279 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3280 SIVAL(pdata,2,own_grp);
3285 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3286 SIVAL(pdata,2,0xFFFFFFFF);
3287 SIVAL(pdata,6,0xFFFFFFFF);
3290 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3291 SIVAL(pdata,2,0xFFFFFFFF);
3292 SIVAL(pdata,6,0xFFFFFFFF);
3295 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3298 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3305 /****************************************************************************
3306 Store the FILE_UNIX_BASIC info.
3307 ****************************************************************************/
3309 static char *store_file_unix_basic(connection_struct *conn,
3312 const SMB_STRUCT_STAT *psbuf)
3314 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3315 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3317 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3320 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3323 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3324 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3325 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3328 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3332 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3336 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3339 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3343 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3347 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3350 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3354 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3361 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3362 * the chflags(2) (or equivalent) flags.
3364 * XXX: this really should be behind the VFS interface. To do this, we would
3365 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3366 * Each VFS module could then implement its own mapping as appropriate for the
3367 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3369 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3373 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3377 { UF_IMMUTABLE, EXT_IMMUTABLE },
3381 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3385 { UF_HIDDEN, EXT_HIDDEN },
3388 /* Do not remove. We need to guarantee that this array has at least one
3389 * entry to build on HP-UX.
3395 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3396 uint32 *smb_fflags, uint32 *smb_fmask)
3398 #ifdef HAVE_STAT_ST_FLAGS
3401 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3402 *smb_fmask |= info2_flags_map[i].smb_fflag;
3403 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3404 *smb_fflags |= info2_flags_map[i].smb_fflag;
3407 #endif /* HAVE_STAT_ST_FLAGS */
3410 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3411 const uint32 smb_fflags,
3412 const uint32 smb_fmask,
3415 #ifdef HAVE_STAT_ST_FLAGS
3416 uint32 max_fmask = 0;
3419 *stat_fflags = psbuf->st_flags;
3421 /* For each flags requested in smb_fmask, check the state of the
3422 * corresponding flag in smb_fflags and set or clear the matching
3426 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3427 max_fmask |= info2_flags_map[i].smb_fflag;
3428 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3429 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3430 *stat_fflags |= info2_flags_map[i].stat_fflag;
3432 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3437 /* If smb_fmask is asking to set any bits that are not supported by
3438 * our flag mappings, we should fail.
3440 if ((smb_fmask & max_fmask) != smb_fmask) {
3447 #endif /* HAVE_STAT_ST_FLAGS */
3451 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3452 * of file flags and birth (create) time.
3454 static char *store_file_unix_basic_info2(connection_struct *conn,
3457 const SMB_STRUCT_STAT *psbuf)
3459 uint32 file_flags = 0;
3460 uint32 flags_mask = 0;
3462 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3464 /* Create (birth) time 64 bit */
3465 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3468 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3469 SIVAL(pdata, 0, file_flags); /* flags */
3470 SIVAL(pdata, 4, flags_mask); /* mask */
3476 /****************************************************************************
3477 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3478 ****************************************************************************/
3480 static void call_trans2qpipeinfo(connection_struct *conn,
3481 struct smb_request *req,
3482 unsigned int tran_call,
3483 char **pparams, int total_params,
3484 char **ppdata, int total_data,
3485 unsigned int max_data_bytes)
3487 char *params = *pparams;
3488 char *pdata = *ppdata;
3489 unsigned int data_size = 0;
3490 unsigned int param_size = 2;
3492 smb_np_struct *p_pipe = NULL;
3495 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3499 if (total_params < 4) {
3500 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3504 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3505 if (p_pipe == NULL) {
3506 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3510 info_level = SVAL(params,2);
3512 *pparams = (char *)SMB_REALLOC(*pparams,2);
3513 if (*pparams == NULL) {
3514 reply_nterror(req, NT_STATUS_NO_MEMORY);
3519 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3520 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3521 if (*ppdata == NULL ) {
3522 reply_nterror(req, NT_STATUS_NO_MEMORY);
3527 switch (info_level) {
3528 case SMB_FILE_STANDARD_INFORMATION:
3530 SOFF_T(pdata,0,4096LL);
3537 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3541 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3547 /****************************************************************************
3548 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3549 file name or file id).
3550 ****************************************************************************/
3552 static void call_trans2qfilepathinfo(connection_struct *conn,
3553 struct smb_request *req,
3554 unsigned int tran_call,
3555 char **pparams, int total_params,
3556 char **ppdata, int total_data,
3557 unsigned int max_data_bytes)
3559 char *params = *pparams;
3560 char *pdata = *ppdata;
3561 char *dstart, *dend;
3565 SMB_OFF_T file_size=0;
3566 SMB_BIG_UINT allocation_size=0;
3567 unsigned int data_size = 0;
3568 unsigned int param_size = 2;
3569 SMB_STRUCT_STAT sbuf;
3570 char *dos_fname = NULL;
3576 bool delete_pending = False;
3578 time_t create_time, mtime, atime;
3579 struct timespec create_time_ts, mtime_ts, atime_ts;
3580 files_struct *fsp = NULL;
3581 struct file_id fileid;
3582 struct ea_list *ea_list = NULL;
3583 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3584 char *lock_data = NULL;
3585 TALLOC_CTX *ctx = talloc_tos();
3588 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3594 if (tran_call == TRANSACT2_QFILEINFO) {
3595 if (total_params < 4) {
3596 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3601 call_trans2qpipeinfo(conn, req, tran_call,
3602 pparams, total_params,
3608 fsp = file_fsp(SVAL(params,0));
3609 info_level = SVAL(params,2);
3611 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3613 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3614 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3618 /* Initial check for valid fsp ptr. */
3619 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
3623 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3625 reply_nterror(req, NT_STATUS_NO_MEMORY);
3629 if(fsp->fake_file_handle) {
3631 * This is actually for the QUOTA_FAKE_FILE --metze
3634 /* We know this name is ok, it's already passed the checks. */
3636 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3638 * This is actually a QFILEINFO on a directory
3639 * handle (returned from an NT SMB). NT5.0 seems
3640 * to do this call. JRA.
3643 if (INFO_LEVEL_IS_UNIX(info_level)) {
3644 /* Always do lstat for UNIX calls. */
3645 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3646 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3647 reply_unixerror(req,ERRDOS,ERRbadpath);
3650 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3651 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3652 reply_unixerror(req, ERRDOS, ERRbadpath);
3656 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3657 delete_pending = get_delete_on_close_flag(fileid);
3660 * Original code - this is an open file.
3662 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3666 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3667 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3668 reply_unixerror(req, ERRDOS, ERRbadfid);
3671 pos = fsp->fh->position_information;
3672 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3673 delete_pending = get_delete_on_close_flag(fileid);
3674 access_mask = fsp->access_mask;
3678 NTSTATUS status = NT_STATUS_OK;
3681 if (total_params < 7) {
3682 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3686 info_level = SVAL(params,0);
3688 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3690 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3691 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3695 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3697 STR_TERMINATE, &status);
3698 if (!NT_STATUS_IS_OK(status)) {
3699 reply_nterror(req, status);
3703 status = resolve_dfspath(ctx,
3705 req->flags2 & FLAGS2_DFS_PATHNAMES,
3708 if (!NT_STATUS_IS_OK(status)) {
3709 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3710 reply_botherror(req,
3711 NT_STATUS_PATH_NOT_COVERED,
3712 ERRSRV, ERRbadpath);
3714 reply_nterror(req, status);
3718 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3719 if (!NT_STATUS_IS_OK(status)) {
3720 reply_nterror(req, status);
3723 status = check_name(conn, fname);
3724 if (!NT_STATUS_IS_OK(status)) {
3725 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3726 reply_nterror(req, status);
3730 if (INFO_LEVEL_IS_UNIX(info_level)) {
3731 /* Always do lstat for UNIX calls. */
3732 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3733 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3734 reply_unixerror(req, ERRDOS, ERRbadpath);
3737 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3738 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3739 reply_unixerror(req, ERRDOS, ERRbadpath);
3743 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3744 delete_pending = get_delete_on_close_flag(fileid);
3745 if (delete_pending) {
3746 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3751 nlink = sbuf.st_nlink;
3753 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3754 /* NTFS does not seem to count ".." */
3758 if ((nlink > 0) && delete_pending) {
3762 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3763 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3767 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3768 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3770 p = strrchr_m(fname,'/');
3776 mode = dos_mode(conn,fname,&sbuf);
3778 mode = FILE_ATTRIBUTE_NORMAL;
3780 fullpathname = fname;
3782 file_size = get_file_size(sbuf);
3784 /* Pull out any data sent here before we realloc. */
3785 switch (info_level) {
3786 case SMB_INFO_QUERY_EAS_FROM_LIST:
3788 /* Pull any EA list from the data portion. */
3791 if (total_data < 4) {
3793 req, NT_STATUS_INVALID_PARAMETER);
3796 ea_size = IVAL(pdata,0);
3798 if (total_data > 0 && ea_size != total_data) {
3799 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3800 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3802 req, NT_STATUS_INVALID_PARAMETER);
3806 if (!lp_ea_support(SNUM(conn))) {
3807 reply_doserror(req, ERRDOS,
3808 ERReasnotsupported);
3812 /* Pull out the list of names. */
3813 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3816 req, NT_STATUS_INVALID_PARAMETER);
3822 case SMB_QUERY_POSIX_LOCK:
3824 if (fsp == NULL || fsp->fh->fd == -1) {
3825 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3829 if (total_data != POSIX_LOCK_DATA_SIZE) {
3831 req, NT_STATUS_INVALID_PARAMETER);
3835 /* Copy the lock range data. */
3836 lock_data = (char *)TALLOC_MEMDUP(
3837 ctx, pdata, total_data);
3839 reply_nterror(req, NT_STATUS_NO_MEMORY);
3847 *pparams = (char *)SMB_REALLOC(*pparams,2);
3848 if (*pparams == NULL) {
3849 reply_nterror(req, NT_STATUS_NO_MEMORY);
3854 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3855 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3856 if (*ppdata == NULL ) {
3857 reply_nterror(req, NT_STATUS_NO_MEMORY);
3862 dend = dstart + data_size - 1;
3864 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3865 mtime_ts = get_mtimespec(&sbuf);
3866 atime_ts = get_atimespec(&sbuf);
3868 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3871 if (!null_timespec(fsp->pending_modtime)) {
3872 /* the pending modtime overrides the current modtime */
3873 mtime_ts = fsp->pending_modtime;
3877 /* Do we have this path open ? */
3878 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3879 fsp1 = file_find_di_first(fileid);
3880 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3881 /* the pending modtime overrides the current modtime */
3882 mtime_ts = fsp1->pending_modtime;
3884 if (fsp1 && fsp1->initial_allocation_size) {
3885 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3889 if (lp_dos_filetime_resolution(SNUM(conn))) {
3890 dos_filetime_timespec(&create_time_ts);
3891 dos_filetime_timespec(&mtime_ts);
3892 dos_filetime_timespec(&atime_ts);
3895 create_time = convert_timespec_to_time_t(create_time_ts);
3896 mtime = convert_timespec_to_time_t(mtime_ts);
3897 atime = convert_timespec_to_time_t(atime_ts);
3899 /* NT expects the name to be in an exact form of the *full*
3900 filename. See the trans2 torture test */
3901 if (ISDOT(base_name)) {
3902 dos_fname = talloc_strdup(ctx, "\\");
3904 reply_nterror(req, NT_STATUS_NO_MEMORY);
3908 dos_fname = talloc_asprintf(ctx,
3912 reply_nterror(req, NT_STATUS_NO_MEMORY);
3915 string_replace(dos_fname, '/', '\\');
3918 switch (info_level) {
3919 case SMB_INFO_STANDARD:
3920 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3922 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3923 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3924 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3925 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3926 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3927 SSVAL(pdata,l1_attrFile,mode);
3930 case SMB_INFO_QUERY_EA_SIZE:
3932 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3933 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3935 srv_put_dos_date2(pdata,0,create_time);
3936 srv_put_dos_date2(pdata,4,atime);
3937 srv_put_dos_date2(pdata,8,mtime); /* write time */
3938 SIVAL(pdata,12,(uint32)file_size);
3939 SIVAL(pdata,16,(uint32)allocation_size);
3940 SSVAL(pdata,20,mode);
3941 SIVAL(pdata,22,ea_size);
3945 case SMB_INFO_IS_NAME_VALID:
3946 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3947 if (tran_call == TRANSACT2_QFILEINFO) {
3948 /* os/2 needs this ? really ?*/
3949 reply_doserror(req, ERRDOS, ERRbadfunc);
3956 case SMB_INFO_QUERY_EAS_FROM_LIST:
3958 size_t total_ea_len = 0;
3959 struct ea_list *ea_file_list = NULL;
3961 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3963 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3964 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3966 if (!ea_list || (total_ea_len > data_size)) {
3968 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3972 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3976 case SMB_INFO_QUERY_ALL_EAS:
3978 /* We have data_size bytes to put EA's into. */
3979 size_t total_ea_len = 0;
3981 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3983 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3984 if (!ea_list || (total_ea_len > data_size)) {
3986 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3990 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3994 case SMB_FILE_BASIC_INFORMATION:
3995 case SMB_QUERY_FILE_BASIC_INFO:
3997 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3998 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3999 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4001 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4005 put_long_date_timespec(pdata,create_time_ts);
4006 put_long_date_timespec(pdata+8,atime_ts);
4007 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4008 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4009 SIVAL(pdata,32,mode);
4011 DEBUG(5,("SMB_QFBI - "));
4012 DEBUG(5,("create: %s ", ctime(&create_time)));
4013 DEBUG(5,("access: %s ", ctime(&atime)));
4014 DEBUG(5,("write: %s ", ctime(&mtime)));
4015 DEBUG(5,("change: %s ", ctime(&mtime)));
4016 DEBUG(5,("mode: %x\n", mode));
4019 case SMB_FILE_STANDARD_INFORMATION:
4020 case SMB_QUERY_FILE_STANDARD_INFO:
4022 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4024 SOFF_T(pdata,0,allocation_size);
4025 SOFF_T(pdata,8,file_size);
4026 SIVAL(pdata,16,nlink);
4027 SCVAL(pdata,20,delete_pending?1:0);
4028 SCVAL(pdata,21,(mode&aDIR)?1:0);
4029 SSVAL(pdata,22,0); /* Padding. */
4032 case SMB_FILE_EA_INFORMATION:
4033 case SMB_QUERY_FILE_EA_INFO:
4035 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4036 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4038 SIVAL(pdata,0,ea_size);
4042 /* Get the 8.3 name - used if NT SMB was negotiated. */
4043 case SMB_QUERY_FILE_ALT_NAME_INFO:
4044 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4046 char mangled_name[13];
4047 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4048 if (!name_to_8_3(base_name,mangled_name,
4049 True,conn->params)) {
4052 NT_STATUS_NO_MEMORY);
4054 len = srvstr_push(dstart, req->flags2,
4055 pdata+4, mangled_name,
4056 PTR_DIFF(dend, pdata+4),
4058 data_size = 4 + len;
4063 case SMB_QUERY_FILE_NAME_INFO:
4065 this must be *exactly* right for ACLs on mapped drives to work
4067 len = srvstr_push(dstart, req->flags2,
4069 PTR_DIFF(dend, pdata+4),
4071 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4072 data_size = 4 + len;
4076 case SMB_FILE_ALLOCATION_INFORMATION:
4077 case SMB_QUERY_FILE_ALLOCATION_INFO:
4078 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4080 SOFF_T(pdata,0,allocation_size);
4083 case SMB_FILE_END_OF_FILE_INFORMATION:
4084 case SMB_QUERY_FILE_END_OF_FILEINFO:
4085 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4087 SOFF_T(pdata,0,file_size);
4090 case SMB_QUERY_FILE_ALL_INFO:
4091 case SMB_FILE_ALL_INFORMATION:
4093 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4094 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4095 put_long_date_timespec(pdata,create_time_ts);
4096 put_long_date_timespec(pdata+8,atime_ts);
4097 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4098 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4099 SIVAL(pdata,32,mode);
4100 SIVAL(pdata,36,0); /* padding. */
4102 SOFF_T(pdata,0,allocation_size);
4103 SOFF_T(pdata,8,file_size);
4104 SIVAL(pdata,16,nlink);
4105 SCVAL(pdata,20,delete_pending);
4106 SCVAL(pdata,21,(mode&aDIR)?1:0);
4109 SIVAL(pdata,0,ea_size);
4110 pdata += 4; /* EA info */
4111 len = srvstr_push(dstart, req->flags2,
4113 PTR_DIFF(dend, pdata+4),
4117 data_size = PTR_DIFF(pdata,(*ppdata));
4120 case SMB_FILE_INTERNAL_INFORMATION:
4121 /* This should be an index number - looks like
4124 I think this causes us to fail the IFSKIT
4125 BasicFileInformationTest. -tpot */
4127 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4128 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4129 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4133 case SMB_FILE_ACCESS_INFORMATION:
4134 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4135 SIVAL(pdata,0,access_mask);
4139 case SMB_FILE_NAME_INFORMATION:
4140 /* Pathname with leading '\'. */
4143 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4144 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4145 SIVAL(pdata,0,byte_len);
4146 data_size = 4 + byte_len;
4150 case SMB_FILE_DISPOSITION_INFORMATION:
4151 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4153 SCVAL(pdata,0,delete_pending);
4156 case SMB_FILE_POSITION_INFORMATION:
4157 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4159 SOFF_T(pdata,0,pos);
4162 case SMB_FILE_MODE_INFORMATION:
4163 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4164 SIVAL(pdata,0,mode);
4168 case SMB_FILE_ALIGNMENT_INFORMATION:
4169 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4170 SIVAL(pdata,0,0); /* No alignment needed. */
4176 * NT4 server just returns "invalid query" to this - if we try to answer
4177 * it then NTws gets a BSOD! (tridge).
4178 * W2K seems to want this. JRA.
4180 case SMB_QUERY_FILE_STREAM_INFO:
4182 case SMB_FILE_STREAM_INFORMATION:
4183 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4187 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4188 SIVAL(pdata,0,0); /* ??? */
4189 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4190 SOFF_T(pdata,8,file_size);
4191 SOFF_T(pdata,16,allocation_size);
4192 data_size = 24 + byte_len;
4196 case SMB_QUERY_COMPRESSION_INFO:
4197 case SMB_FILE_COMPRESSION_INFORMATION:
4198 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4199 SOFF_T(pdata,0,file_size);
4200 SIVAL(pdata,8,0); /* ??? */
4201 SIVAL(pdata,12,0); /* ??? */
4205 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4206 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4207 put_long_date_timespec(pdata,create_time_ts);
4208 put_long_date_timespec(pdata+8,atime_ts);
4209 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4210 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4211 SOFF_T(pdata,32,allocation_size);
4212 SOFF_T(pdata,40,file_size);
4213 SIVAL(pdata,48,mode);
4214 SIVAL(pdata,52,0); /* ??? */
4218 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4219 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4220 SIVAL(pdata,0,mode);
4226 * CIFS UNIX Extensions.
4229 case SMB_QUERY_FILE_UNIX_BASIC:
4231 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4232 data_size = PTR_DIFF(pdata,(*ppdata));
4236 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4238 for (i=0; i<100; i++)
4239 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4245 case SMB_QUERY_FILE_UNIX_INFO2:
4247 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4248 data_size = PTR_DIFF(pdata,(*ppdata));
4252 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4254 for (i=0; i<100; i++)
4255 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4261 case SMB_QUERY_FILE_UNIX_LINK:
4263 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4266 reply_nterror(req, NT_STATUS_NO_MEMORY);
4270 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4272 if(!S_ISLNK(sbuf.st_mode)) {
4273 reply_unixerror(req, ERRSRV,
4278 reply_unixerror(req, ERRDOS, ERRbadlink);
4281 len = SMB_VFS_READLINK(conn,fullpathname,
4284 reply_unixerror(req, ERRDOS,
4289 len = srvstr_push(dstart, req->flags2,
4291 PTR_DIFF(dend, pdata),
4294 data_size = PTR_DIFF(pdata,(*ppdata));
4299 #if defined(HAVE_POSIX_ACLS)
4300 case SMB_QUERY_POSIX_ACL:
4302 SMB_ACL_T file_acl = NULL;
4303 SMB_ACL_T def_acl = NULL;
4304 uint16 num_file_acls = 0;
4305 uint16 num_def_acls = 0;
4307 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4308 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4310 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4313 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4314 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4318 NT_STATUS_NOT_IMPLEMENTED);
4322 if (S_ISDIR(sbuf.st_mode)) {
4323 if (fsp && fsp->is_directory) {
4324 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4326 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4328 def_acl = free_empty_sys_acl(conn, def_acl);
4331 num_file_acls = count_acl_entries(conn, file_acl);
4332 num_def_acls = count_acl_entries(conn, def_acl);
4334 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4335 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4337 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4338 SMB_POSIX_ACL_HEADER_SIZE) ));
4340 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4343 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4347 NT_STATUS_BUFFER_TOO_SMALL);
4351 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4352 SSVAL(pdata,2,num_file_acls);
4353 SSVAL(pdata,4,num_def_acls);
4354 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4356 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4359 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4362 req, NT_STATUS_INTERNAL_ERROR);
4365 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4367 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4370 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4374 NT_STATUS_INTERNAL_ERROR);
4379 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4382 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4384 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4390 case SMB_QUERY_POSIX_LOCK:
4392 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4394 SMB_BIG_UINT offset;
4396 enum brl_type lock_type;
4398 if (total_data != POSIX_LOCK_DATA_SIZE) {
4400 req, NT_STATUS_INVALID_PARAMETER);
4404 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4405 case POSIX_LOCK_TYPE_READ:
4406 lock_type = READ_LOCK;
4408 case POSIX_LOCK_TYPE_WRITE:
4409 lock_type = WRITE_LOCK;
4411 case POSIX_LOCK_TYPE_UNLOCK:
4413 /* There's no point in asking for an unlock... */
4416 NT_STATUS_INVALID_PARAMETER);
4420 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4421 #if defined(HAVE_LONGLONG)
4422 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4423 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4424 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4425 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4426 #else /* HAVE_LONGLONG */
4427 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4428 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4429 #endif /* HAVE_LONGLONG */
4431 status = query_lock(fsp,
4438 if (ERROR_WAS_LOCK_DENIED(status)) {
4439 /* Here we need to report who has it locked... */
4440 data_size = POSIX_LOCK_DATA_SIZE;
4442 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4443 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4444 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4445 #if defined(HAVE_LONGLONG)
4446 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4447 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4448 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4449 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4450 #else /* HAVE_LONGLONG */
4451 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4452 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4453 #endif /* HAVE_LONGLONG */
4455 } else if (NT_STATUS_IS_OK(status)) {
4456 /* For success we just return a copy of what we sent
4457 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4458 data_size = POSIX_LOCK_DATA_SIZE;
4459 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4460 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4462 reply_nterror(req, status);
4469 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4473 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4479 /****************************************************************************
4480 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4482 ****************************************************************************/
4484 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4485 connection_struct *conn,
4486 const char *oldname_in,
4487 const char *newname_in)
4489 SMB_STRUCT_STAT sbuf1, sbuf2;
4490 char *last_component_oldname = NULL;
4491 char *last_component_newname = NULL;
4492 char *oldname = NULL;
4493 char *newname = NULL;
4494 NTSTATUS status = NT_STATUS_OK;
4499 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4500 &last_component_oldname, &sbuf1);
4501 if (!NT_STATUS_IS_OK(status)) {
4505 status = check_name(conn, oldname);
4506 if (!NT_STATUS_IS_OK(status)) {
4510 /* source must already exist. */
4511 if (!VALID_STAT(sbuf1)) {
4512 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4515 status = unix_convert(ctx, conn, newname_in, False, &newname,
4516 &last_component_newname, &sbuf2);
4517 if (!NT_STATUS_IS_OK(status)) {
4521 status = check_name(conn, newname);
4522 if (!NT_STATUS_IS_OK(status)) {
4526 /* Disallow if newname already exists. */
4527 if (VALID_STAT(sbuf2)) {
4528 return NT_STATUS_OBJECT_NAME_COLLISION;
4531 /* No links from a directory. */
4532 if (S_ISDIR(sbuf1.st_mode)) {
4533 return NT_STATUS_FILE_IS_A_DIRECTORY;
4536 /* Ensure this is within the share. */
4537 status = check_reduced_name(conn, oldname);
4538 if (!NT_STATUS_IS_OK(status)) {
4542 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4544 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4545 status = map_nt_error_from_unix(errno);
4546 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4547 nt_errstr(status), newname, oldname));
4553 /****************************************************************************
4554 Deal with setting the time from any of the setfilepathinfo functions.
4555 ****************************************************************************/
4557 static NTSTATUS smb_set_file_time(connection_struct *conn,
4560 const SMB_STRUCT_STAT *psbuf,
4561 struct timespec ts[2],
4562 bool setting_write_time)
4565 FILE_NOTIFY_CHANGE_LAST_ACCESS
4566 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4568 if (!VALID_STAT(*psbuf)) {
4569 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4572 /* get some defaults (no modifications) if any info is zero or -1. */
4573 if (null_timespec(ts[0])) {
4574 ts[0] = get_atimespec(psbuf);
4575 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4578 if (null_timespec(ts[1])) {
4579 ts[1] = get_mtimespec(psbuf);
4580 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4583 if (!setting_write_time) {
4584 /* ts[1] comes from change time, not write time. */
4585 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4588 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4589 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4592 * Try and set the times of this file if
4593 * they are different from the current values.
4597 struct timespec mts = get_mtimespec(psbuf);
4598 struct timespec ats = get_atimespec(psbuf);
4599 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4600 return NT_STATUS_OK;
4606 * This was a setfileinfo on an open file.
4607 * NT does this a lot. We also need to
4608 * set the time here, as it can be read by
4609 * FindFirst/FindNext and with the patch for bug #2045
4610 * in smbd/fileio.c it ensures that this timestamp is
4611 * kept sticky even after a write. We save the request
4612 * away and will set it on file close and after a write. JRA.
4615 if (!null_timespec(ts[1])) {
4616 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4617 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4618 fsp_set_pending_modtime(fsp, ts[1]);
4622 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4624 if(file_ntimes(conn, fname, ts)!=0) {
4625 return map_nt_error_from_unix(errno);
4627 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4629 return NT_STATUS_OK;
4632 /****************************************************************************
4633 Deal with setting the dosmode from any of the setfilepathinfo functions.
4634 ****************************************************************************/
4636 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4638 SMB_STRUCT_STAT *psbuf,
4641 if (!VALID_STAT(*psbuf)) {
4642 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4646 if (S_ISDIR(psbuf->st_mode)) {
4653 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4655 /* check the mode isn't different, before changing it */
4656 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4658 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4659 fname, (unsigned int)dosmode ));
4661 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4662 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4663 fname, strerror(errno)));
4664 return map_nt_error_from_unix(errno);
4667 return NT_STATUS_OK;
4670 /****************************************************************************
4671 Deal with setting the size from any of the setfilepathinfo functions.
4672 ****************************************************************************/
4674 static NTSTATUS smb_set_file_size(connection_struct *conn,
4675 struct smb_request *req,
4678 SMB_STRUCT_STAT *psbuf,
4681 NTSTATUS status = NT_STATUS_OK;
4682 files_struct *new_fsp = NULL;
4684 if (!VALID_STAT(*psbuf)) {
4685 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4688 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4690 if (size == get_file_size(*psbuf)) {
4691 return NT_STATUS_OK;
4694 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4695 fname, (double)size ));
4697 if (fsp && fsp->fh->fd != -1) {
4698 /* Handle based call. */
4699 if (vfs_set_filelen(fsp, size) == -1) {
4700 return map_nt_error_from_unix(errno);
4702 return NT_STATUS_OK;
4705 status = open_file_ntcreate(conn, req, fname, psbuf,
4707 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4710 FILE_ATTRIBUTE_NORMAL,
4711 FORCE_OPLOCK_BREAK_TO_NONE,
4714 if (!NT_STATUS_IS_OK(status)) {
4715 /* NB. We check for open_was_deferred in the caller. */
4719 if (vfs_set_filelen(new_fsp, size) == -1) {
4720 status = map_nt_error_from_unix(errno);
4721 close_file(new_fsp,NORMAL_CLOSE);
4725 close_file(new_fsp,NORMAL_CLOSE);
4726 return NT_STATUS_OK;
4729 /****************************************************************************
4730 Deal with SMB_INFO_SET_EA.
4731 ****************************************************************************/
4733 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4739 struct ea_list *ea_list = NULL;
4740 TALLOC_CTX *ctx = NULL;
4741 NTSTATUS status = NT_STATUS_OK;
4743 if (total_data < 10) {
4745 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4746 length. They seem to have no effect. Bug #3212. JRA */
4748 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4749 /* We're done. We only get EA info in this call. */
4750 return NT_STATUS_OK;
4753 return NT_STATUS_INVALID_PARAMETER;
4756 if (IVAL(pdata,0) > total_data) {
4757 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4758 IVAL(pdata,0), (unsigned int)total_data));
4759 return NT_STATUS_INVALID_PARAMETER;
4762 ctx = talloc_init("SMB_INFO_SET_EA");
4764 return NT_STATUS_NO_MEMORY;
4766 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4768 talloc_destroy(ctx);
4769 return NT_STATUS_INVALID_PARAMETER;
4771 status = set_ea(conn, fsp, fname, ea_list);
4772 talloc_destroy(ctx);
4777 /****************************************************************************
4778 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4779 ****************************************************************************/
4781 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4786 SMB_STRUCT_STAT *psbuf)
4788 NTSTATUS status = NT_STATUS_OK;
4789 bool delete_on_close;
4792 if (total_data < 1) {
4793 return NT_STATUS_INVALID_PARAMETER;
4797 return NT_STATUS_INVALID_HANDLE;
4800 delete_on_close = (CVAL(pdata,0) ? True : False);
4801 dosmode = dos_mode(conn, fname, psbuf);
4803 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4804 "delete_on_close = %u\n",
4806 (unsigned int)dosmode,
4807 (unsigned int)delete_on_close ));
4809 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4811 if (!NT_STATUS_IS_OK(status)) {
4815 /* The set is across all open files on this dev/inode pair. */
4816 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4817 return NT_STATUS_ACCESS_DENIED;
4819 return NT_STATUS_OK;
4822 /****************************************************************************
4823 Deal with SMB_FILE_POSITION_INFORMATION.
4824 ****************************************************************************/
4826 static NTSTATUS smb_file_position_information(connection_struct *conn,
4831 SMB_BIG_UINT position_information;
4833 if (total_data < 8) {
4834 return NT_STATUS_INVALID_PARAMETER;
4838 /* Ignore on pathname based set. */
4839 return NT_STATUS_OK;
4842 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4843 #ifdef LARGE_SMB_OFF_T
4844 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4845 #else /* LARGE_SMB_OFF_T */
4846 if (IVAL(pdata,4) != 0) {
4847 /* more than 32 bits? */
4848 return NT_STATUS_INVALID_PARAMETER;
4850 #endif /* LARGE_SMB_OFF_T */
4852 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4853 fsp->fsp_name, (double)position_information ));
4854 fsp->fh->position_information = position_information;
4855 return NT_STATUS_OK;
4858 /****************************************************************************
4859 Deal with SMB_FILE_MODE_INFORMATION.
4860 ****************************************************************************/
4862 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4868 if (total_data < 4) {
4869 return NT_STATUS_INVALID_PARAMETER;
4871 mode = IVAL(pdata,0);
4872 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4873 return NT_STATUS_INVALID_PARAMETER;
4875 return NT_STATUS_OK;
4878 /****************************************************************************
4879 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4880 ****************************************************************************/
4882 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4883 struct smb_request *req,
4888 char *link_target = NULL;
4889 const char *newname = fname;
4890 NTSTATUS status = NT_STATUS_OK;
4891 TALLOC_CTX *ctx = talloc_tos();
4893 /* Set a symbolic link. */
4894 /* Don't allow this if follow links is false. */
4896 if (total_data == 0) {
4897 return NT_STATUS_INVALID_PARAMETER;
4900 if (!lp_symlinks(SNUM(conn))) {
4901 return NT_STATUS_ACCESS_DENIED;
4904 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
4905 total_data, STR_TERMINATE);
4908 return NT_STATUS_INVALID_PARAMETER;
4911 /* !widelinks forces the target path to be within the share. */
4912 /* This means we can interpret the target as a pathname. */
4913 if (!lp_widelinks(SNUM(conn))) {
4914 char *rel_name = NULL;
4915 char *last_dirp = NULL;
4917 if (*link_target == '/') {
4918 /* No absolute paths allowed. */
4919 return NT_STATUS_ACCESS_DENIED;
4921 rel_name = talloc_strdup(ctx,newname);
4923 return NT_STATUS_NO_MEMORY;
4925 last_dirp = strrchr_m(rel_name, '/');
4927 last_dirp[1] = '\0';
4929 rel_name = talloc_strdup(ctx,"./");
4931 return NT_STATUS_NO_MEMORY;
4934 rel_name = talloc_asprintf_append(rel_name,
4938 return NT_STATUS_NO_MEMORY;
4941 status = check_name(conn, rel_name);
4942 if (!NT_STATUS_IS_OK(status)) {
4947 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4948 newname, link_target ));
4950 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4951 return map_nt_error_from_unix(errno);
4954 return NT_STATUS_OK;
4957 /****************************************************************************
4958 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4959 ****************************************************************************/
4961 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4962 struct smb_request *req,
4963 const char *pdata, int total_data,
4966 char *oldname = NULL;
4967 TALLOC_CTX *ctx = talloc_tos();
4968 NTSTATUS status = NT_STATUS_OK;
4970 /* Set a hard link. */
4971 if (total_data == 0) {
4972 return NT_STATUS_INVALID_PARAMETER;
4975 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
4976 total_data, STR_TERMINATE, &status);
4977 if (!NT_STATUS_IS_OK(status)) {
4981 status = resolve_dfspath(ctx, conn,
4982 req->flags2 & FLAGS2_DFS_PATHNAMES,
4985 if (!NT_STATUS_IS_OK(status)) {
4989 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4992 return hardlink_internals(ctx, conn, oldname, fname);
4995 /****************************************************************************
4996 Deal with SMB_FILE_RENAME_INFORMATION.
4997 ****************************************************************************/
4999 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5000 struct smb_request *req,
5009 char *newname = NULL;
5010 char *base_name = NULL;
5011 bool dest_has_wcard = False;
5012 NTSTATUS status = NT_STATUS_OK;
5014 TALLOC_CTX *ctx = talloc_tos();
5016 if (total_data < 13) {
5017 return NT_STATUS_INVALID_PARAMETER;
5020 overwrite = (CVAL(pdata,0) ? True : False);
5021 root_fid = IVAL(pdata,4);
5022 len = IVAL(pdata,8);
5024 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5025 return NT_STATUS_INVALID_PARAMETER;
5028 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5031 if (!NT_STATUS_IS_OK(status)) {
5035 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5038 status = resolve_dfspath_wcard(ctx, conn,
5039 req->flags2 & FLAGS2_DFS_PATHNAMES,
5043 if (!NT_STATUS_IS_OK(status)) {
5047 /* Check the new name has no '/' characters. */
5048 if (strchr_m(newname, '/')) {
5049 return NT_STATUS_NOT_SUPPORTED;
5052 /* Create the base directory. */
5053 base_name = talloc_strdup(ctx, fname);
5055 return NT_STATUS_NO_MEMORY;
5057 p = strrchr_m(base_name, '/');
5061 base_name = talloc_strdup(ctx, "./");
5063 return NT_STATUS_NO_MEMORY;
5066 /* Append the new name. */
5067 base_name = talloc_asprintf_append(base_name,
5071 return NT_STATUS_NO_MEMORY;
5075 SMB_STRUCT_STAT sbuf;
5076 char *newname_last_component = NULL;
5080 status = unix_convert(ctx, conn, newname, False,
5082 &newname_last_component,
5085 /* If an error we expect this to be
5086 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5088 if (!NT_STATUS_IS_OK(status)
5089 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5094 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5095 fsp->fnum, fsp->fsp_name, base_name ));
5096 status = rename_internals_fsp(conn, fsp, base_name,
5097 newname_last_component, 0,
5100 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5101 fname, base_name ));
5102 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5103 overwrite, False, dest_has_wcard);
5109 /****************************************************************************
5110 Deal with SMB_SET_POSIX_ACL.
5111 ****************************************************************************/
5113 #if defined(HAVE_POSIX_ACLS)
5114 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5119 SMB_STRUCT_STAT *psbuf)
5121 uint16 posix_acl_version;
5122 uint16 num_file_acls;
5123 uint16 num_def_acls;
5124 bool valid_file_acls = True;
5125 bool valid_def_acls = True;
5127 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5128 return NT_STATUS_INVALID_PARAMETER;
5130 posix_acl_version = SVAL(pdata,0);
5131 num_file_acls = SVAL(pdata,2);
5132 num_def_acls = SVAL(pdata,4);
5134 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5135 valid_file_acls = False;
5139 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5140 valid_def_acls = False;
5144 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5145 return NT_STATUS_INVALID_PARAMETER;
5148 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5149 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5150 return NT_STATUS_INVALID_PARAMETER;
5153 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5154 fname ? fname : fsp->fsp_name,
5155 (unsigned int)num_file_acls,
5156 (unsigned int)num_def_acls));
5158 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5159 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5160 return map_nt_error_from_unix(errno);
5163 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5164 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5165 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5166 return map_nt_error_from_unix(errno);
5168 return NT_STATUS_OK;
5172 /****************************************************************************
5173 Deal with SMB_SET_POSIX_LOCK.
5174 ****************************************************************************/
5176 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5177 const struct smb_request *req,
5183 SMB_BIG_UINT offset;
5185 bool blocking_lock = False;
5186 enum brl_type lock_type;
5188 NTSTATUS status = NT_STATUS_OK;
5190 if (fsp == NULL || fsp->fh->fd == -1) {
5191 return NT_STATUS_INVALID_HANDLE;
5194 if (total_data != POSIX_LOCK_DATA_SIZE) {
5195 return NT_STATUS_INVALID_PARAMETER;
5198 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5199 case POSIX_LOCK_TYPE_READ:
5200 lock_type = READ_LOCK;
5202 case POSIX_LOCK_TYPE_WRITE:
5203 /* Return the right POSIX-mappable error code for files opened read-only. */
5204 if (!fsp->can_write) {
5205 return NT_STATUS_INVALID_HANDLE;
5207 lock_type = WRITE_LOCK;
5209 case POSIX_LOCK_TYPE_UNLOCK:
5210 lock_type = UNLOCK_LOCK;
5213 return NT_STATUS_INVALID_PARAMETER;
5216 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5217 blocking_lock = False;
5218 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5219 blocking_lock = True;
5221 return NT_STATUS_INVALID_PARAMETER;
5224 if (!lp_blocking_locks(SNUM(conn))) {
5225 blocking_lock = False;
5228 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5229 #if defined(HAVE_LONGLONG)
5230 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5231 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5232 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5233 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5234 #else /* HAVE_LONGLONG */
5235 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5236 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5237 #endif /* HAVE_LONGLONG */
5239 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5240 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5242 (unsigned int)lock_type,
5243 (unsigned int)lock_pid,
5247 if (lock_type == UNLOCK_LOCK) {
5248 status = do_unlock(smbd_messaging_context(),
5255 uint32 block_smbpid;
5257 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5268 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5270 * A blocking lock was requested. Package up
5271 * this smb into a queued request and push it
5272 * onto the blocking lock queue.
5274 if(push_blocking_lock_request(br_lck,
5277 -1, /* infinite timeout. */
5285 TALLOC_FREE(br_lck);
5289 TALLOC_FREE(br_lck);
5295 /****************************************************************************
5296 Deal with SMB_INFO_STANDARD.
5297 ****************************************************************************/
5299 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5304 const SMB_STRUCT_STAT *psbuf)
5306 struct timespec ts[2];
5308 if (total_data < 12) {
5309 return NT_STATUS_INVALID_PARAMETER;
5313 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5315 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5317 DEBUG(10,("smb_set_info_standard: file %s\n",
5318 fname ? fname : fsp->fsp_name ));
5320 return smb_set_file_time(conn,
5328 /****************************************************************************
5329 Deal with SMB_SET_FILE_BASIC_INFO.
5330 ****************************************************************************/
5332 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5337 SMB_STRUCT_STAT *psbuf)
5339 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5340 struct timespec write_time;
5341 struct timespec changed_time;
5343 struct timespec ts[2];
5344 NTSTATUS status = NT_STATUS_OK;
5345 bool setting_write_time = true;
5347 if (total_data < 36) {
5348 return NT_STATUS_INVALID_PARAMETER;
5351 /* Set the attributes */
5352 dosmode = IVAL(pdata,32);
5353 status = smb_set_file_dosmode(conn,
5357 if (!NT_STATUS_IS_OK(status)) {
5361 /* Ignore create time at offset pdata. */
5364 ts[0] = interpret_long_date(pdata+8);
5366 write_time = interpret_long_date(pdata+16);
5367 changed_time = interpret_long_date(pdata+24);
5370 ts[1] = timespec_min(&write_time, &changed_time);
5372 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5376 /* Prefer a defined time to an undefined one. */
5377 if (null_timespec(ts[1])) {
5378 if (null_timespec(write_time)) {
5379 ts[1] = changed_time;
5380 setting_write_time = false;
5386 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5387 fname ? fname : fsp->fsp_name ));
5389 return smb_set_file_time(conn,
5394 setting_write_time);
5397 /****************************************************************************
5398 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5399 ****************************************************************************/
5401 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5402 struct smb_request *req,
5407 SMB_STRUCT_STAT *psbuf)
5409 SMB_BIG_UINT allocation_size = 0;
5410 NTSTATUS status = NT_STATUS_OK;
5411 files_struct *new_fsp = NULL;
5413 if (!VALID_STAT(*psbuf)) {
5414 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5417 if (total_data < 8) {
5418 return NT_STATUS_INVALID_PARAMETER;
5421 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5422 #ifdef LARGE_SMB_OFF_T
5423 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5424 #else /* LARGE_SMB_OFF_T */
5425 if (IVAL(pdata,4) != 0) {
5426 /* more than 32 bits? */
5427 return NT_STATUS_INVALID_PARAMETER;
5429 #endif /* LARGE_SMB_OFF_T */
5431 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5432 fname, (double)allocation_size ));
5434 if (allocation_size) {
5435 allocation_size = smb_roundup(conn, allocation_size);
5438 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5439 fname, (double)allocation_size ));
5441 if (fsp && fsp->fh->fd != -1) {
5442 /* Open file handle. */
5443 /* Only change if needed. */
5444 if (allocation_size != get_file_size(*psbuf)) {
5445 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5446 return map_nt_error_from_unix(errno);
5449 /* But always update the time. */
5450 if (null_timespec(fsp->pending_modtime)) {
5452 * This is equivalent to a write. Ensure it's seen immediately
5453 * if there are no pending writes.
5455 set_filetime(fsp->conn, fsp->fsp_name,
5456 timespec_current());
5458 return NT_STATUS_OK;
5461 /* Pathname or stat or directory file. */
5463 status = open_file_ntcreate(conn, req, fname, psbuf,
5465 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5468 FILE_ATTRIBUTE_NORMAL,
5469 FORCE_OPLOCK_BREAK_TO_NONE,
5472 if (!NT_STATUS_IS_OK(status)) {
5473 /* NB. We check for open_was_deferred in the caller. */
5477 /* Only change if needed. */
5478 if (allocation_size != get_file_size(*psbuf)) {
5479 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5480 status = map_nt_error_from_unix(errno);
5481 close_file(new_fsp,NORMAL_CLOSE);
5486 /* Changing the allocation size should set the last mod time. */
5487 /* Don't need to call set_filetime as this will be flushed on
5490 fsp_set_pending_modtime(new_fsp, timespec_current());
5492 close_file(new_fsp,NORMAL_CLOSE);
5493 return NT_STATUS_OK;
5496 /****************************************************************************
5497 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5498 ****************************************************************************/
5500 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5501 struct smb_request *req,
5506 SMB_STRUCT_STAT *psbuf)
5510 if (total_data < 8) {
5511 return NT_STATUS_INVALID_PARAMETER;
5514 size = IVAL(pdata,0);
5515 #ifdef LARGE_SMB_OFF_T
5516 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5517 #else /* LARGE_SMB_OFF_T */
5518 if (IVAL(pdata,4) != 0) {
5519 /* more than 32 bits? */
5520 return NT_STATUS_INVALID_PARAMETER;
5522 #endif /* LARGE_SMB_OFF_T */
5523 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5524 "file %s to %.0f\n", fname, (double)size ));
5526 return smb_set_file_size(conn, req,
5533 /****************************************************************************
5534 Allow a UNIX info mknod.
5535 ****************************************************************************/
5537 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5541 SMB_STRUCT_STAT *psbuf)
5543 uint32 file_type = IVAL(pdata,56);
5544 #if defined(HAVE_MAKEDEV)
5545 uint32 dev_major = IVAL(pdata,60);
5546 uint32 dev_minor = IVAL(pdata,68);
5548 SMB_DEV_T dev = (SMB_DEV_T)0;
5549 uint32 raw_unixmode = IVAL(pdata,84);
5553 if (total_data < 100) {
5554 return NT_STATUS_INVALID_PARAMETER;
5557 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5558 if (!NT_STATUS_IS_OK(status)) {
5562 #if defined(HAVE_MAKEDEV)
5563 dev = makedev(dev_major, dev_minor);
5566 switch (file_type) {
5567 #if defined(S_IFIFO)
5568 case UNIX_TYPE_FIFO:
5569 unixmode |= S_IFIFO;
5572 #if defined(S_IFSOCK)
5573 case UNIX_TYPE_SOCKET:
5574 unixmode |= S_IFSOCK;
5577 #if defined(S_IFCHR)
5578 case UNIX_TYPE_CHARDEV:
5579 unixmode |= S_IFCHR;
5582 #if defined(S_IFBLK)
5583 case UNIX_TYPE_BLKDEV:
5584 unixmode |= S_IFBLK;
5588 return NT_STATUS_INVALID_PARAMETER;
5591 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5592 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5594 /* Ok - do the mknod. */
5595 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5596 return map_nt_error_from_unix(errno);
5599 /* If any of the other "set" calls fail we
5600 * don't want to end up with a half-constructed mknod.
5603 if (lp_inherit_perms(SNUM(conn))) {
5605 conn, parent_dirname(fname),
5609 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5610 status = map_nt_error_from_unix(errno);
5611 SMB_VFS_UNLINK(conn,fname);
5614 return NT_STATUS_OK;
5617 /****************************************************************************
5618 Deal with SMB_SET_FILE_UNIX_BASIC.
5619 ****************************************************************************/
5621 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5622 struct smb_request *req,
5627 SMB_STRUCT_STAT *psbuf)
5629 struct timespec ts[2];
5630 uint32 raw_unixmode;
5633 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5634 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5635 NTSTATUS status = NT_STATUS_OK;
5636 bool delete_on_fail = False;
5637 enum perm_type ptype;
5639 if (total_data < 100) {
5640 return NT_STATUS_INVALID_PARAMETER;
5643 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5644 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5645 size=IVAL(pdata,0); /* first 8 Bytes are size */
5646 #ifdef LARGE_SMB_OFF_T
5647 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5648 #else /* LARGE_SMB_OFF_T */
5649 if (IVAL(pdata,4) != 0) {
5650 /* more than 32 bits? */
5651 return NT_STATUS_INVALID_PARAMETER;
5653 #endif /* LARGE_SMB_OFF_T */
5656 ts[0] = interpret_long_date(pdata+24); /* access_time */
5657 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5658 set_owner = (uid_t)IVAL(pdata,40);
5659 set_grp = (gid_t)IVAL(pdata,48);
5660 raw_unixmode = IVAL(pdata,84);
5662 if (VALID_STAT(*psbuf)) {
5663 if (S_ISDIR(psbuf->st_mode)) {
5664 ptype = PERM_EXISTING_DIR;
5666 ptype = PERM_EXISTING_FILE;
5669 ptype = PERM_NEW_FILE;
5672 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5673 if (!NT_STATUS_IS_OK(status)) {
5677 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5678 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5679 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5681 if (!VALID_STAT(*psbuf)) {
5683 * The only valid use of this is to create character and block
5684 * devices, and named pipes. This is deprecated (IMHO) and
5685 * a new info level should be used for mknod. JRA.
5688 status = smb_unix_mknod(conn,
5693 if (!NT_STATUS_IS_OK(status)) {
5697 /* Ensure we don't try and change anything else. */
5698 raw_unixmode = SMB_MODE_NO_CHANGE;
5699 size = get_file_size(*psbuf);
5700 ts[0] = get_atimespec(psbuf);
5701 ts[1] = get_mtimespec(psbuf);
5703 * We continue here as we might want to change the
5706 delete_on_fail = True;
5710 /* Horrible backwards compatibility hack as an old server bug
5711 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5715 size = get_file_size(*psbuf);
5720 * Deal with the UNIX specific mode set.
5723 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5724 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5725 (unsigned int)unixmode, fname ));
5726 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5727 return map_nt_error_from_unix(errno);
5732 * Deal with the UNIX specific uid set.
5735 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5738 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5739 (unsigned int)set_owner, fname ));
5741 if (S_ISLNK(psbuf->st_mode)) {
5742 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5744 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5748 status = map_nt_error_from_unix(errno);
5749 if (delete_on_fail) {
5750 SMB_VFS_UNLINK(conn,fname);
5757 * Deal with the UNIX specific gid set.
5760 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5761 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5762 (unsigned int)set_owner, fname ));
5763 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5764 status = map_nt_error_from_unix(errno);
5765 if (delete_on_fail) {
5766 SMB_VFS_UNLINK(conn,fname);
5772 /* Deal with any size changes. */
5774 status = smb_set_file_size(conn, req,
5779 if (!NT_STATUS_IS_OK(status)) {
5783 /* Deal with any time changes. */
5785 return smb_set_file_time(conn,
5793 /****************************************************************************
5794 Deal with SMB_SET_FILE_UNIX_INFO2.
5795 ****************************************************************************/
5797 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5798 struct smb_request *req,
5803 SMB_STRUCT_STAT *psbuf)
5809 if (total_data < 116) {
5810 return NT_STATUS_INVALID_PARAMETER;
5813 /* Start by setting all the fields that are common between UNIX_BASIC
5816 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5818 if (!NT_STATUS_IS_OK(status)) {
5822 smb_fflags = IVAL(pdata, 108);
5823 smb_fmask = IVAL(pdata, 112);
5825 /* NB: We should only attempt to alter the file flags if the client
5826 * sends a non-zero mask.
5828 if (smb_fmask != 0) {
5829 int stat_fflags = 0;
5831 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5833 /* Client asked to alter a flag we don't understand. */
5834 return NT_STATUS_INVALID_PARAMETER;
5837 if (fsp && fsp->fh->fd != -1) {
5838 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5839 return NT_STATUS_NOT_SUPPORTED;
5841 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5842 return map_nt_error_from_unix(errno);
5847 /* XXX: need to add support for changing the create_time here. You
5848 * can do this for paths on Darwin with setattrlist(2). The right way
5849 * to hook this up is probably by extending the VFS utimes interface.
5852 return NT_STATUS_OK;
5855 /****************************************************************************
5856 Create a directory with POSIX semantics.
5857 ****************************************************************************/
5859 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5860 struct smb_request *req,
5864 SMB_STRUCT_STAT *psbuf,
5865 int *pdata_return_size)
5867 NTSTATUS status = NT_STATUS_OK;
5868 uint32 raw_unixmode = 0;
5869 uint32 mod_unixmode = 0;
5870 mode_t unixmode = (mode_t)0;
5871 files_struct *fsp = NULL;
5872 uint16 info_level_return = 0;
5874 char *pdata = *ppdata;
5876 if (total_data < 18) {
5877 return NT_STATUS_INVALID_PARAMETER;
5880 raw_unixmode = IVAL(pdata,8);
5881 /* Next 4 bytes are not yet defined. */
5883 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5884 if (!NT_STATUS_IS_OK(status)) {
5888 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5890 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5891 fname, (unsigned int)unixmode ));
5893 status = open_directory(conn, req,
5896 FILE_READ_ATTRIBUTES, /* Just a stat open */
5897 FILE_SHARE_NONE, /* Ignored for stat opens */
5904 if (NT_STATUS_IS_OK(status)) {
5905 close_file(fsp, NORMAL_CLOSE);
5908 info_level_return = SVAL(pdata,16);
5910 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5911 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5912 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5913 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5915 *pdata_return_size = 12;
5918 /* Realloc the data size */
5919 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5920 if (*ppdata == NULL) {
5921 *pdata_return_size = 0;
5922 return NT_STATUS_NO_MEMORY;
5926 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5927 SSVAL(pdata,2,0); /* No fnum. */
5928 SIVAL(pdata,4,info); /* Was directory created. */
5930 switch (info_level_return) {
5931 case SMB_QUERY_FILE_UNIX_BASIC:
5932 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5933 SSVAL(pdata,10,0); /* Padding. */
5934 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5936 case SMB_QUERY_FILE_UNIX_INFO2:
5937 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5938 SSVAL(pdata,10,0); /* Padding. */
5939 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5942 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5943 SSVAL(pdata,10,0); /* Padding. */
5950 /****************************************************************************
5951 Open/Create a file with POSIX semantics.
5952 ****************************************************************************/
5954 static NTSTATUS smb_posix_open(connection_struct *conn,
5955 struct smb_request *req,
5959 SMB_STRUCT_STAT *psbuf,
5960 int *pdata_return_size)
5962 bool extended_oplock_granted = False;
5963 char *pdata = *ppdata;
5965 uint32 wire_open_mode = 0;
5966 uint32 raw_unixmode = 0;
5967 uint32 mod_unixmode = 0;
5968 uint32 create_disp = 0;
5969 uint32 access_mask = 0;
5970 uint32 create_options = 0;
5971 NTSTATUS status = NT_STATUS_OK;
5972 mode_t unixmode = (mode_t)0;
5973 files_struct *fsp = NULL;
5974 int oplock_request = 0;
5976 uint16 info_level_return = 0;
5978 if (total_data < 18) {
5979 return NT_STATUS_INVALID_PARAMETER;
5982 flags = IVAL(pdata,0);
5983 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5984 if (oplock_request) {
5985 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5988 wire_open_mode = IVAL(pdata,4);
5990 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5991 return smb_posix_mkdir(conn, req,
5999 switch (wire_open_mode & SMB_ACCMODE) {
6001 access_mask = FILE_READ_DATA;
6004 access_mask = FILE_WRITE_DATA;
6007 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6010 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6011 (unsigned int)wire_open_mode ));
6012 return NT_STATUS_INVALID_PARAMETER;
6015 wire_open_mode &= ~SMB_ACCMODE;
6017 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6018 create_disp = FILE_CREATE;
6019 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6020 create_disp = FILE_OVERWRITE_IF;
6021 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6022 create_disp = FILE_OPEN_IF;
6024 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6025 (unsigned int)wire_open_mode ));
6026 return NT_STATUS_INVALID_PARAMETER;
6029 raw_unixmode = IVAL(pdata,8);
6030 /* Next 4 bytes are not yet defined. */
6032 status = unix_perms_from_wire(conn,
6035 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6038 if (!NT_STATUS_IS_OK(status)) {
6042 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6044 if (wire_open_mode & SMB_O_SYNC) {
6045 create_options |= FILE_WRITE_THROUGH;
6047 if (wire_open_mode & SMB_O_APPEND) {
6048 access_mask |= FILE_APPEND_DATA;
6050 if (wire_open_mode & SMB_O_DIRECT) {
6051 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6054 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6056 (unsigned int)wire_open_mode,
6057 (unsigned int)unixmode ));
6059 status = open_file_ntcreate(conn, req,
6063 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6065 0, /* no create options yet. */
6071 if (!NT_STATUS_IS_OK(status)) {
6075 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6076 extended_oplock_granted = True;
6079 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6080 extended_oplock_granted = True;
6083 info_level_return = SVAL(pdata,16);
6085 /* Allocate the correct return size. */
6087 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6088 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6089 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6090 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6092 *pdata_return_size = 12;
6095 /* Realloc the data size */
6096 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6097 if (*ppdata == NULL) {
6098 close_file(fsp,ERROR_CLOSE);
6099 *pdata_return_size = 0;
6100 return NT_STATUS_NO_MEMORY;
6104 if (extended_oplock_granted) {
6105 if (flags & REQUEST_BATCH_OPLOCK) {
6106 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6108 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6110 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6111 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6113 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6116 SSVAL(pdata,2,fsp->fnum);
6117 SIVAL(pdata,4,info); /* Was file created etc. */
6119 switch (info_level_return) {
6120 case SMB_QUERY_FILE_UNIX_BASIC:
6121 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6122 SSVAL(pdata,10,0); /* padding. */
6123 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6125 case SMB_QUERY_FILE_UNIX_INFO2:
6126 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6127 SSVAL(pdata,10,0); /* padding. */
6128 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6131 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6132 SSVAL(pdata,10,0); /* padding. */
6135 return NT_STATUS_OK;
6138 /****************************************************************************
6139 Delete a file with POSIX semantics.
6140 ****************************************************************************/
6142 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6143 struct smb_request *req,
6147 SMB_STRUCT_STAT *psbuf)
6149 NTSTATUS status = NT_STATUS_OK;
6150 files_struct *fsp = NULL;
6155 struct share_mode_lock *lck = NULL;
6157 if (total_data < 2) {
6158 return NT_STATUS_INVALID_PARAMETER;
6161 flags = SVAL(pdata,0);
6163 if (!VALID_STAT(*psbuf)) {
6164 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6167 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6168 !VALID_STAT_OF_DIR(*psbuf)) {
6169 return NT_STATUS_NOT_A_DIRECTORY;
6172 DEBUG(10,("smb_posix_unlink: %s %s\n",
6173 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6176 if (VALID_STAT_OF_DIR(*psbuf)) {
6177 status = open_directory(conn, req,
6181 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6184 FILE_FLAG_POSIX_SEMANTICS|0777,
6189 status = open_file_ntcreate(conn, req,
6193 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6196 FILE_FLAG_POSIX_SEMANTICS|0777,
6197 0, /* No oplock, but break existing ones. */
6202 if (!NT_STATUS_IS_OK(status)) {
6207 * Don't lie to client. If we can't really delete due to
6208 * non-POSIX opens return SHARING_VIOLATION.
6211 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
6213 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6214 "lock for file %s\n", fsp->fsp_name));
6215 close_file(fsp, NORMAL_CLOSE);
6216 return NT_STATUS_INVALID_PARAMETER;
6220 * See if others still have the file open. If this is the case, then
6221 * don't delete. If all opens are POSIX delete we can set the delete
6222 * on close disposition.
6224 for (i=0; i<lck->num_share_modes; i++) {
6225 struct share_mode_entry *e = &lck->share_modes[i];
6226 if (is_valid_share_mode_entry(e)) {
6227 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6230 /* Fail with sharing violation. */
6231 close_file(fsp, NORMAL_CLOSE);
6233 return NT_STATUS_SHARING_VIOLATION;
6238 * Set the delete on close.
6240 status = smb_set_file_disposition_info(conn,
6247 if (!NT_STATUS_IS_OK(status)) {
6248 close_file(fsp, NORMAL_CLOSE);
6253 return close_file(fsp, NORMAL_CLOSE);
6256 /****************************************************************************
6257 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6258 ****************************************************************************/
6260 static void call_trans2setfilepathinfo(connection_struct *conn,
6261 struct smb_request *req,
6262 unsigned int tran_call,
6263 char **pparams, int total_params,
6264 char **ppdata, int total_data,
6265 unsigned int max_data_bytes)
6267 char *params = *pparams;
6268 char *pdata = *ppdata;
6270 SMB_STRUCT_STAT sbuf;
6272 files_struct *fsp = NULL;
6273 NTSTATUS status = NT_STATUS_OK;
6274 int data_return_size = 0;
6275 TALLOC_CTX *ctx = talloc_tos();
6278 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6284 if (tran_call == TRANSACT2_SETFILEINFO) {
6285 if (total_params < 4) {
6286 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6290 fsp = file_fsp(SVAL(params,0));
6291 /* Basic check for non-null fsp. */
6292 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
6295 info_level = SVAL(params,2);
6297 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6299 reply_nterror(req, NT_STATUS_NO_MEMORY);
6303 if(fsp->is_directory || fsp->fh->fd == -1) {
6305 * This is actually a SETFILEINFO on a directory
6306 * handle (returned from an NT SMB). NT5.0 seems
6307 * to do this call. JRA.
6309 if (INFO_LEVEL_IS_UNIX(info_level)) {
6310 /* Always do lstat for UNIX calls. */
6311 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6312 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6313 reply_unixerror(req,ERRDOS,ERRbadpath);
6317 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6318 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6319 reply_unixerror(req,ERRDOS,ERRbadpath);
6323 } else if (fsp->print_file) {
6325 * Doing a DELETE_ON_CLOSE should cancel a print job.
6327 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6328 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6330 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6333 send_trans2_replies(conn, req, params, 2,
6338 reply_unixerror(req, ERRDOS, ERRbadpath);
6343 * Original code - this is an open file.
6345 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6349 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6350 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6351 reply_unixerror(req, ERRDOS, ERRbadfid);
6357 if (total_params < 7) {
6358 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6362 info_level = SVAL(params,0);
6363 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6364 total_params - 6, STR_TERMINATE,
6366 if (!NT_STATUS_IS_OK(status)) {
6367 reply_nterror(req, status);
6371 status = resolve_dfspath(ctx, conn,
6372 req->flags2 & FLAGS2_DFS_PATHNAMES,
6375 if (!NT_STATUS_IS_OK(status)) {
6376 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6377 reply_botherror(req,
6378 NT_STATUS_PATH_NOT_COVERED,
6379 ERRSRV, ERRbadpath);
6382 reply_nterror(req, status);
6386 status = unix_convert(ctx, conn, fname, False,
6387 &fname, NULL, &sbuf);
6388 if (!NT_STATUS_IS_OK(status)) {
6389 reply_nterror(req, status);
6393 status = check_name(conn, fname);
6394 if (!NT_STATUS_IS_OK(status)) {
6395 reply_nterror(req, status);
6399 if (INFO_LEVEL_IS_UNIX(info_level)) {
6401 * For CIFS UNIX extensions the target name may not exist.
6404 /* Always do lstat for UNIX calls. */
6405 SMB_VFS_LSTAT(conn,fname,&sbuf);
6407 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6408 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6409 reply_unixerror(req, ERRDOS, ERRbadpath);
6414 if (!CAN_WRITE(conn)) {
6415 reply_doserror(req, ERRSRV, ERRaccess);
6419 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6420 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6424 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6425 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6427 /* Realloc the parameter size */
6428 *pparams = (char *)SMB_REALLOC(*pparams,2);
6429 if (*pparams == NULL) {
6430 reply_nterror(req, NT_STATUS_NO_MEMORY);
6437 if (fsp && !null_timespec(fsp->pending_modtime)) {
6438 /* the pending modtime overrides the current modtime */
6439 set_mtimespec(&sbuf, fsp->pending_modtime);
6442 switch (info_level) {
6444 case SMB_INFO_STANDARD:
6446 status = smb_set_info_standard(conn,
6455 case SMB_INFO_SET_EA:
6457 status = smb_info_set_ea(conn,
6465 case SMB_SET_FILE_BASIC_INFO:
6466 case SMB_FILE_BASIC_INFORMATION:
6468 status = smb_set_file_basic_info(conn,
6477 case SMB_FILE_ALLOCATION_INFORMATION:
6478 case SMB_SET_FILE_ALLOCATION_INFO:
6480 status = smb_set_file_allocation_info(conn, req,
6489 case SMB_FILE_END_OF_FILE_INFORMATION:
6490 case SMB_SET_FILE_END_OF_FILE_INFO:
6492 status = smb_set_file_end_of_file_info(conn, req,
6501 case SMB_FILE_DISPOSITION_INFORMATION:
6502 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6505 /* JRA - We used to just ignore this on a path ?
6506 * Shouldn't this be invalid level on a pathname
6509 if (tran_call != TRANSACT2_SETFILEINFO) {
6510 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6513 status = smb_set_file_disposition_info(conn,
6522 case SMB_FILE_POSITION_INFORMATION:
6524 status = smb_file_position_information(conn,
6531 /* From tridge Samba4 :
6532 * MODE_INFORMATION in setfileinfo (I have no
6533 * idea what "mode information" on a file is - it takes a value of 0,
6534 * 2, 4 or 6. What could it be?).
6537 case SMB_FILE_MODE_INFORMATION:
6539 status = smb_file_mode_information(conn,
6546 * CIFS UNIX extensions.
6549 case SMB_SET_FILE_UNIX_BASIC:
6551 status = smb_set_file_unix_basic(conn, req,
6560 case SMB_SET_FILE_UNIX_INFO2:
6562 status = smb_set_file_unix_info2(conn, req,
6571 case SMB_SET_FILE_UNIX_LINK:
6573 if (tran_call != TRANSACT2_SETPATHINFO) {
6574 /* We must have a pathname for this. */
6575 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6578 status = smb_set_file_unix_link(conn, req, pdata,
6583 case SMB_SET_FILE_UNIX_HLINK:
6585 if (tran_call != TRANSACT2_SETPATHINFO) {
6586 /* We must have a pathname for this. */
6587 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6590 status = smb_set_file_unix_hlink(conn, req,
6596 case SMB_FILE_RENAME_INFORMATION:
6598 status = smb_file_rename_information(conn, req,
6604 #if defined(HAVE_POSIX_ACLS)
6605 case SMB_SET_POSIX_ACL:
6607 status = smb_set_posix_acl(conn,
6617 case SMB_SET_POSIX_LOCK:
6619 if (tran_call != TRANSACT2_SETFILEINFO) {
6620 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6623 status = smb_set_posix_lock(conn, req,
6624 pdata, total_data, fsp);
6628 case SMB_POSIX_PATH_OPEN:
6630 if (tran_call != TRANSACT2_SETPATHINFO) {
6631 /* We must have a pathname for this. */
6632 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6636 status = smb_posix_open(conn, req,
6645 case SMB_POSIX_PATH_UNLINK:
6647 if (tran_call != TRANSACT2_SETPATHINFO) {
6648 /* We must have a pathname for this. */
6649 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6653 status = smb_posix_unlink(conn, req,
6662 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6667 if (!NT_STATUS_IS_OK(status)) {
6668 if (open_was_deferred(req->mid)) {
6669 /* We have re-scheduled this call. */
6672 if (blocking_lock_was_deferred(req->mid)) {
6673 /* We have re-scheduled this call. */
6676 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6677 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6678 ERRSRV, ERRbadpath);
6681 if (info_level == SMB_POSIX_PATH_OPEN) {
6682 reply_openerror(req, status);
6686 reply_nterror(req, status);
6691 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
6697 /****************************************************************************
6698 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6699 ****************************************************************************/
6701 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6702 char **pparams, int total_params,
6703 char **ppdata, int total_data,
6704 unsigned int max_data_bytes)
6706 char *params = *pparams;
6707 char *pdata = *ppdata;
6708 char *directory = NULL;
6709 SMB_STRUCT_STAT sbuf;
6710 NTSTATUS status = NT_STATUS_OK;
6711 struct ea_list *ea_list = NULL;
6712 TALLOC_CTX *ctx = talloc_tos();
6714 if (!CAN_WRITE(conn)) {
6715 reply_doserror(req, ERRSRV, ERRaccess);
6719 if (total_params < 5) {
6720 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6724 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
6725 total_params - 4, STR_TERMINATE,
6727 if (!NT_STATUS_IS_OK(status)) {
6728 reply_nterror(req, status);
6732 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6734 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6735 if (!NT_STATUS_IS_OK(status)) {
6736 reply_nterror(req, status);
6740 status = check_name(conn, directory);
6741 if (!NT_STATUS_IS_OK(status)) {
6742 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6743 reply_nterror(req, status);
6747 /* Any data in this call is an EA list. */
6748 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6749 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6754 * OS/2 workplace shell seems to send SET_EA requests of "null"
6755 * length (4 bytes containing IVAL 4).
6756 * They seem to have no effect. Bug #3212. JRA.
6759 if (total_data != 4) {
6760 if (total_data < 10) {
6761 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6765 if (IVAL(pdata,0) > total_data) {
6766 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6767 IVAL(pdata,0), (unsigned int)total_data));
6768 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6772 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6775 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6778 } else if (IVAL(pdata,0) != 4) {
6779 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6783 status = create_directory(conn, req, directory);
6785 if (!NT_STATUS_IS_OK(status)) {
6786 reply_nterror(req, status);
6790 /* Try and set any given EA. */
6792 status = set_ea(conn, NULL, directory, ea_list);
6793 if (!NT_STATUS_IS_OK(status)) {
6794 reply_nterror(req, status);
6799 /* Realloc the parameter and data sizes */
6800 *pparams = (char *)SMB_REALLOC(*pparams,2);
6801 if(*pparams == NULL) {
6802 reply_nterror(req, NT_STATUS_NO_MEMORY);
6809 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
6814 /****************************************************************************
6815 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6816 We don't actually do this - we just send a null response.
6817 ****************************************************************************/
6819 static void call_trans2findnotifyfirst(connection_struct *conn,
6820 struct smb_request *req,
6821 char **pparams, int total_params,
6822 char **ppdata, int total_data,
6823 unsigned int max_data_bytes)
6825 static uint16 fnf_handle = 257;
6826 char *params = *pparams;
6829 if (total_params < 6) {
6830 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6834 info_level = SVAL(params,4);
6835 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6837 switch (info_level) {
6842 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6846 /* Realloc the parameter and data sizes */
6847 *pparams = (char *)SMB_REALLOC(*pparams,6);
6848 if (*pparams == NULL) {
6849 reply_nterror(req, NT_STATUS_NO_MEMORY);
6854 SSVAL(params,0,fnf_handle);
6855 SSVAL(params,2,0); /* No changes */
6856 SSVAL(params,4,0); /* No EA errors */
6863 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
6868 /****************************************************************************
6869 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6870 changes). Currently this does nothing.
6871 ****************************************************************************/
6873 static void call_trans2findnotifynext(connection_struct *conn,
6874 struct smb_request *req,
6875 char **pparams, int total_params,
6876 char **ppdata, int total_data,
6877 unsigned int max_data_bytes)
6879 char *params = *pparams;
6881 DEBUG(3,("call_trans2findnotifynext\n"));
6883 /* Realloc the parameter and data sizes */
6884 *pparams = (char *)SMB_REALLOC(*pparams,4);
6885 if (*pparams == NULL) {
6886 reply_nterror(req, NT_STATUS_NO_MEMORY);
6891 SSVAL(params,0,0); /* No changes */
6892 SSVAL(params,2,0); /* No EA errors */
6894 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
6899 /****************************************************************************
6900 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6901 ****************************************************************************/
6903 static void call_trans2getdfsreferral(connection_struct *conn,
6904 struct smb_request *req,
6905 char **pparams, int total_params,
6906 char **ppdata, int total_data,
6907 unsigned int max_data_bytes)
6909 char *params = *pparams;
6910 char *pathname = NULL;
6912 int max_referral_level;
6913 NTSTATUS status = NT_STATUS_OK;
6914 TALLOC_CTX *ctx = talloc_tos();
6916 DEBUG(10,("call_trans2getdfsreferral\n"));
6918 if (total_params < 3) {
6919 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6923 max_referral_level = SVAL(params,0);
6925 if(!lp_host_msdfs()) {
6926 reply_doserror(req, ERRDOS, ERRbadfunc);
6930 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
6931 total_params - 2, STR_TERMINATE);
6933 reply_nterror(req, NT_STATUS_NOT_FOUND);
6936 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6937 ppdata,&status)) < 0) {
6938 reply_nterror(req, status);
6942 SSVAL(req->inbuf, smb_flg2,
6943 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6944 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
6949 #define LMCAT_SPL 0x53
6950 #define LMFUNC_GETJOBID 0x60
6952 /****************************************************************************
6953 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6954 ****************************************************************************/
6956 static void call_trans2ioctl(connection_struct *conn,
6957 struct smb_request *req,
6958 char **pparams, int total_params,
6959 char **ppdata, int total_data,
6960 unsigned int max_data_bytes)
6962 char *pdata = *ppdata;
6963 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6965 /* check for an invalid fid before proceeding */
6968 reply_doserror(req, ERRDOS, ERRbadfid);
6972 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6973 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6974 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6975 if (*ppdata == NULL) {
6976 reply_nterror(req, NT_STATUS_NO_MEMORY);
6981 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6982 CAN ACCEPT THIS IN UNICODE. JRA. */
6984 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6985 srvstr_push(pdata, req->flags2, pdata + 2,
6986 global_myname(), 15,
6987 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6988 srvstr_push(pdata, req->flags2, pdata+18,
6989 lp_servicename(SNUM(conn)), 13,
6990 STR_ASCII|STR_TERMINATE); /* Service name */
6991 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
6996 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6997 reply_doserror(req, ERRSRV, ERRerror);
7000 /****************************************************************************
7001 Reply to a SMBfindclose (stop trans2 directory search).
7002 ****************************************************************************/
7004 void reply_findclose(connection_struct *conn, struct smb_request *req)
7008 START_PROFILE(SMBfindclose);
7011 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7012 END_PROFILE(SMBfindclose);
7016 dptr_num = SVALS(req->inbuf,smb_vwv0);
7018 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7020 dptr_close(&dptr_num);
7022 reply_outbuf(req, 0, 0);
7024 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7026 END_PROFILE(SMBfindclose);
7030 /****************************************************************************
7031 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7032 ****************************************************************************/
7034 void reply_findnclose(connection_struct *conn, struct smb_request *req)
7038 START_PROFILE(SMBfindnclose);
7041 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7042 END_PROFILE(SMBfindnclose);
7046 dptr_num = SVAL(req->inbuf,smb_vwv0);
7048 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7050 /* We never give out valid handles for a
7051 findnotifyfirst - so any dptr_num is ok here.
7054 reply_outbuf(req, 0, 0);
7056 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7058 END_PROFILE(SMBfindnclose);
7062 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7063 struct trans_state *state)
7065 if (Protocol >= PROTOCOL_NT1) {
7066 req->flags2 |= 0x40; /* IS_LONG_NAME */
7067 SSVAL(req->inbuf,smb_flg2,req->flags2);
7070 if (conn->encrypt_level == Required && SVAL(req->inbuf,4) != 0x45FF ) {
7071 if (state->call != TRANSACT2_QFSINFO &&
7072 state->call != TRANSACT2_SETFSINFO) {
7073 DEBUG(0,("handle_trans2: encryption required "
7075 (unsigned int)state->call));
7076 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7081 /* Now we must call the relevant TRANS2 function */
7082 switch(state->call) {
7083 case TRANSACT2_OPEN:
7085 START_PROFILE(Trans2_open);
7086 call_trans2open(conn, req,
7087 &state->param, state->total_param,
7088 &state->data, state->total_data,
7089 state->max_data_return);
7090 END_PROFILE(Trans2_open);
7094 case TRANSACT2_FINDFIRST:
7096 START_PROFILE(Trans2_findfirst);
7097 call_trans2findfirst(conn, req,
7098 &state->param, state->total_param,
7099 &state->data, state->total_data,
7100 state->max_data_return);
7101 END_PROFILE(Trans2_findfirst);
7105 case TRANSACT2_FINDNEXT:
7107 START_PROFILE(Trans2_findnext);
7108 call_trans2findnext(conn, req,
7109 &state->param, state->total_param,
7110 &state->data, state->total_data,
7111 state->max_data_return);
7112 END_PROFILE(Trans2_findnext);
7116 case TRANSACT2_QFSINFO:
7118 START_PROFILE(Trans2_qfsinfo);
7119 call_trans2qfsinfo(conn, req,
7120 &state->param, state->total_param,
7121 &state->data, state->total_data,
7122 state->max_data_return);
7123 END_PROFILE(Trans2_qfsinfo);
7127 case TRANSACT2_SETFSINFO:
7129 START_PROFILE(Trans2_setfsinfo);
7130 call_trans2setfsinfo(conn, req,
7131 &state->param, state->total_param,
7132 &state->data, state->total_data,
7133 state->max_data_return);
7134 END_PROFILE(Trans2_setfsinfo);
7138 case TRANSACT2_QPATHINFO:
7139 case TRANSACT2_QFILEINFO:
7141 START_PROFILE(Trans2_qpathinfo);
7142 call_trans2qfilepathinfo(conn, req, state->call,
7143 &state->param, state->total_param,
7144 &state->data, state->total_data,
7145 state->max_data_return);
7146 END_PROFILE(Trans2_qpathinfo);
7150 case TRANSACT2_SETPATHINFO:
7151 case TRANSACT2_SETFILEINFO:
7153 START_PROFILE(Trans2_setpathinfo);
7154 call_trans2setfilepathinfo(conn, req, state->call,
7155 &state->param, state->total_param,
7156 &state->data, state->total_data,
7157 state->max_data_return);
7158 END_PROFILE(Trans2_setpathinfo);
7162 case TRANSACT2_FINDNOTIFYFIRST:
7164 START_PROFILE(Trans2_findnotifyfirst);
7165 call_trans2findnotifyfirst(conn, req,
7166 &state->param, state->total_param,
7167 &state->data, state->total_data,
7168 state->max_data_return);
7169 END_PROFILE(Trans2_findnotifyfirst);
7173 case TRANSACT2_FINDNOTIFYNEXT:
7175 START_PROFILE(Trans2_findnotifynext);
7176 call_trans2findnotifynext(conn, req,
7177 &state->param, state->total_param,
7178 &state->data, state->total_data,
7179 state->max_data_return);
7180 END_PROFILE(Trans2_findnotifynext);
7184 case TRANSACT2_MKDIR:
7186 START_PROFILE(Trans2_mkdir);
7187 call_trans2mkdir(conn, req,
7188 &state->param, state->total_param,
7189 &state->data, state->total_data,
7190 state->max_data_return);
7191 END_PROFILE(Trans2_mkdir);
7195 case TRANSACT2_GET_DFS_REFERRAL:
7197 START_PROFILE(Trans2_get_dfs_referral);
7198 call_trans2getdfsreferral(conn, req,
7199 &state->param, state->total_param,
7200 &state->data, state->total_data,
7201 state->max_data_return);
7202 END_PROFILE(Trans2_get_dfs_referral);
7206 case TRANSACT2_IOCTL:
7208 START_PROFILE(Trans2_ioctl);
7209 call_trans2ioctl(conn, req,
7210 &state->param, state->total_param,
7211 &state->data, state->total_data,
7212 state->max_data_return);
7213 END_PROFILE(Trans2_ioctl);
7218 /* Error in request */
7219 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7220 reply_doserror(req, ERRSRV,ERRerror);
7224 /****************************************************************************
7225 Reply to a SMBtrans2.
7226 ****************************************************************************/
7228 void reply_trans2(connection_struct *conn, struct smb_request *req)
7234 unsigned int tran_call;
7236 struct trans_state *state;
7239 START_PROFILE(SMBtrans2);
7241 if (req->wct < 14) {
7242 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7243 END_PROFILE(SMBtrans2);
7247 dsoff = SVAL(req->inbuf, smb_dsoff);
7248 dscnt = SVAL(req->inbuf, smb_dscnt);
7249 psoff = SVAL(req->inbuf, smb_psoff);
7250 pscnt = SVAL(req->inbuf, smb_pscnt);
7251 tran_call = SVAL(req->inbuf, smb_setup0);
7252 size = smb_len(req->inbuf) + 4;
7254 result = allow_new_trans(conn->pending_trans, req->mid);
7255 if (!NT_STATUS_IS_OK(result)) {
7256 DEBUG(2, ("Got invalid trans2 request: %s\n",
7257 nt_errstr(result)));
7258 reply_nterror(req, result);
7259 END_PROFILE(SMBtrans2);
7264 switch (tran_call) {
7265 /* List the allowed trans2 calls on IPC$ */
7266 case TRANSACT2_OPEN:
7267 case TRANSACT2_GET_DFS_REFERRAL:
7268 case TRANSACT2_QFILEINFO:
7269 case TRANSACT2_QFSINFO:
7270 case TRANSACT2_SETFSINFO:
7273 reply_doserror(req, ERRSRV, ERRaccess);
7274 END_PROFILE(SMBtrans2);
7279 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7280 DEBUG(0, ("talloc failed\n"));
7281 reply_nterror(req, NT_STATUS_NO_MEMORY);
7282 END_PROFILE(SMBtrans2);
7286 state->cmd = SMBtrans2;
7288 state->mid = req->mid;
7289 state->vuid = req->vuid;
7290 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7291 state->setup = NULL;
7292 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7293 state->param = NULL;
7294 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7296 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7297 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7298 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7299 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7300 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7302 state->call = tran_call;
7304 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7305 is so as a sanity check */
7306 if (state->setup_count != 1) {
7308 * Need to have rc=0 for ioctl to get job id for OS/2.
7309 * Network printing will fail if function is not successful.
7310 * Similar function in reply.c will be used if protocol
7311 * is LANMAN1.0 instead of LM1.2X002.
7312 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7313 * outbuf doesn't have to be set(only job id is used).
7315 if ( (state->setup_count == 4)
7316 && (tran_call == TRANSACT2_IOCTL)
7317 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7318 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7319 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7321 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7322 DEBUG(2,("Transaction is %d\n",tran_call));
7324 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7325 END_PROFILE(SMBtrans2);
7330 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7333 if (state->total_data) {
7334 /* Can't use talloc here, the core routines do realloc on the
7335 * params and data. */
7336 state->data = (char *)SMB_MALLOC(state->total_data);
7337 if (state->data == NULL) {
7338 DEBUG(0,("reply_trans2: data malloc fail for %u "
7339 "bytes !\n", (unsigned int)state->total_data));
7341 reply_nterror(req, NT_STATUS_NO_MEMORY);
7342 END_PROFILE(SMBtrans2);
7345 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7347 if ((smb_base(req->inbuf)+dsoff+dscnt
7348 > (char *)req->inbuf + size) ||
7349 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7352 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7355 if (state->total_param) {
7356 /* Can't use talloc here, the core routines do realloc on the
7357 * params and data. */
7358 state->param = (char *)SMB_MALLOC(state->total_param);
7359 if (state->param == NULL) {
7360 DEBUG(0,("reply_trans: param malloc fail for %u "
7361 "bytes !\n", (unsigned int)state->total_param));
7362 SAFE_FREE(state->data);
7364 reply_nterror(req, NT_STATUS_NO_MEMORY);
7365 END_PROFILE(SMBtrans2);
7368 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7370 if ((smb_base(req->inbuf)+psoff+pscnt
7371 > (char *)req->inbuf + size) ||
7372 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7375 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7378 state->received_data = dscnt;
7379 state->received_param = pscnt;
7381 if ((state->received_param == state->total_param) &&
7382 (state->received_data == state->total_data)) {
7384 handle_trans2(conn, req, state);
7386 SAFE_FREE(state->data);
7387 SAFE_FREE(state->param);
7389 END_PROFILE(SMBtrans2);
7393 DLIST_ADD(conn->pending_trans, state);
7395 /* We need to send an interim response then receive the rest
7396 of the parameter/data bytes */
7397 reply_outbuf(req, 0, 0);
7398 show_msg((char *)req->outbuf);
7399 END_PROFILE(SMBtrans2);
7404 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7405 SAFE_FREE(state->data);
7406 SAFE_FREE(state->param);
7408 END_PROFILE(SMBtrans2);
7409 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7413 /****************************************************************************
7414 Reply to a SMBtranss2
7415 ****************************************************************************/
7417 void reply_transs2(connection_struct *conn, struct smb_request *req)
7419 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7420 struct trans_state *state;
7423 START_PROFILE(SMBtranss2);
7425 show_msg((char *)req->inbuf);
7428 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7429 END_PROFILE(SMBtranss2);
7433 size = smb_len(req->inbuf)+4;
7435 for (state = conn->pending_trans; state != NULL;
7436 state = state->next) {
7437 if (state->mid == req->mid) {
7442 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7443 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7444 END_PROFILE(SMBtranss2);
7448 /* Revise state->total_param and state->total_data in case they have
7449 changed downwards */
7451 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7452 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7453 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7454 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7456 pcnt = SVAL(req->inbuf, smb_spscnt);
7457 poff = SVAL(req->inbuf, smb_spsoff);
7458 pdisp = SVAL(req->inbuf, smb_spsdisp);
7460 dcnt = SVAL(req->inbuf, smb_sdscnt);
7461 doff = SVAL(req->inbuf, smb_sdsoff);
7462 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7464 state->received_param += pcnt;
7465 state->received_data += dcnt;
7467 if ((state->received_data > state->total_data) ||
7468 (state->received_param > state->total_param))
7472 if (pdisp+pcnt > state->total_param)
7474 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7476 if (pdisp > state->total_param)
7478 if ((smb_base(req->inbuf) + poff + pcnt
7479 > (char *)req->inbuf + size) ||
7480 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7482 if (state->param + pdisp < state->param)
7485 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7490 if (ddisp+dcnt > state->total_data)
7492 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7494 if (ddisp > state->total_data)
7496 if ((smb_base(req->inbuf) + doff + dcnt
7497 > (char *)req->inbuf + size) ||
7498 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7500 if (state->data + ddisp < state->data)
7503 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7507 if ((state->received_param < state->total_param) ||
7508 (state->received_data < state->total_data)) {
7509 END_PROFILE(SMBtranss2);
7514 * construct_reply_common will copy smb_com from inbuf to
7515 * outbuf. SMBtranss2 is wrong here.
7517 SCVAL(req->inbuf,smb_com,SMBtrans2);
7519 handle_trans2(conn, req, state);
7521 DLIST_REMOVE(conn->pending_trans, state);
7522 SAFE_FREE(state->data);
7523 SAFE_FREE(state->param);
7526 END_PROFILE(SMBtranss2);
7531 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7532 DLIST_REMOVE(conn->pending_trans, state);
7533 SAFE_FREE(state->data);
7534 SAFE_FREE(state->param);
7536 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7537 END_PROFILE(SMBtranss2);