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 int smb_read_error;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
37 static char *store_file_unix_basic(connection_struct *conn,
40 const SMB_STRUCT_STAT *psbuf);
42 static char *store_file_unix_basic_info2(connection_struct *conn,
45 const SMB_STRUCT_STAT *psbuf);
47 /********************************************************************
48 Roundup a value to the nearest allocation roundup size boundary.
49 Only do this for Windows clients.
50 ********************************************************************/
52 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
54 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
56 /* Only roundup for Windows clients. */
57 enum remote_arch_types ra_type = get_remote_arch();
58 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
59 val = SMB_ROUNDUP(val,rval);
64 /********************************************************************
65 Given a stat buffer return the allocated size on disk, taking into
67 ********************************************************************/
69 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
73 if(S_ISDIR(sbuf->st_mode)) {
77 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
78 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
80 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
83 if (fsp && fsp->initial_allocation_size)
84 ret = MAX(ret,fsp->initial_allocation_size);
86 return smb_roundup(conn, ret);
89 /****************************************************************************
90 Utility functions for dealing with extended attributes.
91 ****************************************************************************/
93 /****************************************************************************
94 Refuse to allow clients to overwrite our private xattrs.
95 ****************************************************************************/
97 static bool samba_private_attr_name(const char *unix_ea_name)
99 static const char *prohibited_ea_names[] = {
100 SAMBA_POSIX_INHERITANCE_EA_NAME,
101 SAMBA_XATTR_DOS_ATTRIB,
107 for (i = 0; prohibited_ea_names[i]; i++) {
108 if (strequal( prohibited_ea_names[i], unix_ea_name))
114 /****************************************************************************
115 Get one EA value. Fill in a struct ea_struct.
116 ****************************************************************************/
118 static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
119 const char *fname, char *ea_name, struct ea_struct *pea)
121 /* Get the value of this xattr. Max size is 64k. */
122 size_t attr_size = 256;
128 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
133 if (fsp && fsp->fh->fd != -1) {
134 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
136 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
139 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
148 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
149 dump_data(10, (uint8 *)val, sizeret);
152 if (strnequal(ea_name, "user.", 5)) {
153 pea->name = &ea_name[5];
157 pea->value.data = (unsigned char *)val;
158 pea->value.length = (size_t)sizeret;
162 /****************************************************************************
163 Return a linked list of the total EA's. Plus the total size
164 ****************************************************************************/
166 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
167 const char *fname, size_t *pea_total_len)
169 /* Get a list of all xattrs. Max namesize is 64k. */
170 size_t ea_namelist_size = 1024;
175 struct ea_list *ea_list_head = NULL;
179 if (!lp_ea_support(SNUM(conn))) {
183 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
184 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
190 if (fsp && fsp->fh->fd != -1) {
191 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
193 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
196 if (sizeret == -1 && errno == ERANGE) {
197 ea_namelist_size *= 2;
206 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
209 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
210 struct ea_list *listp;
212 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
215 listp = TALLOC_P(mem_ctx, struct ea_list);
219 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
225 push_ascii_fstring(dos_ea_name, listp->ea.name);
226 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
227 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
228 (unsigned int)*pea_total_len, dos_ea_name,
229 (unsigned int)listp->ea.value.length ));
231 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
233 /* Add on 4 for total length. */
234 if (*pea_total_len) {
239 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
243 /****************************************************************************
244 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
246 ****************************************************************************/
248 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
249 connection_struct *conn, struct ea_list *ea_list)
251 unsigned int ret_data_size = 4;
254 SMB_ASSERT(total_data_size >= 4);
256 if (!lp_ea_support(SNUM(conn))) {
261 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
264 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
265 dos_namelen = strlen(dos_ea_name);
266 if (dos_namelen > 255 || dos_namelen == 0) {
269 if (ea_list->ea.value.length > 65535) {
272 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
276 /* We know we have room. */
277 SCVAL(p,0,ea_list->ea.flags);
278 SCVAL(p,1,dos_namelen);
279 SSVAL(p,2,ea_list->ea.value.length);
280 fstrcpy(p+4, dos_ea_name);
281 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
283 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
284 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
287 ret_data_size = PTR_DIFF(p, pdata);
288 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
289 SIVAL(pdata,0,ret_data_size);
290 return ret_data_size;
293 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
295 size_t total_ea_len = 0;
296 TALLOC_CTX *mem_ctx = NULL;
298 if (!lp_ea_support(SNUM(conn))) {
301 mem_ctx = talloc_init("estimate_ea_size");
302 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
303 talloc_destroy(mem_ctx);
307 /****************************************************************************
308 Ensure the EA name is case insensitive by matching any existing EA name.
309 ****************************************************************************/
311 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
314 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
315 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
317 for (; ea_list; ea_list = ea_list->next) {
318 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
319 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
320 &unix_ea_name[5], ea_list->ea.name));
321 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
325 talloc_destroy(mem_ctx);
328 /****************************************************************************
329 Set or delete an extended attribute.
330 ****************************************************************************/
332 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
334 if (!lp_ea_support(SNUM(conn))) {
335 return NT_STATUS_EAS_NOT_SUPPORTED;
338 for (;ea_list; ea_list = ea_list->next) {
340 fstring unix_ea_name;
342 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
343 fstrcat(unix_ea_name, ea_list->ea.name);
345 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
347 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
349 if (samba_private_attr_name(unix_ea_name)) {
350 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
351 return NT_STATUS_ACCESS_DENIED;
354 if (ea_list->ea.value.length == 0) {
355 /* Remove the attribute. */
356 if (fsp && (fsp->fh->fd != -1)) {
357 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
358 unix_ea_name, fsp->fsp_name));
359 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
361 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
362 unix_ea_name, fname));
363 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
366 /* Removing a non existent attribute always succeeds. */
367 if (ret == -1 && errno == ENOATTR) {
368 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
374 if (fsp && (fsp->fh->fd != -1)) {
375 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
376 unix_ea_name, fsp->fsp_name));
377 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
378 ea_list->ea.value.data, ea_list->ea.value.length, 0);
380 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
381 unix_ea_name, fname));
382 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
383 ea_list->ea.value.data, ea_list->ea.value.length, 0);
389 if (errno == ENOTSUP) {
390 return NT_STATUS_EAS_NOT_SUPPORTED;
393 return map_nt_error_from_unix(errno);
399 /****************************************************************************
400 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
401 ****************************************************************************/
403 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
405 struct ea_list *ea_list_head = NULL;
408 while (offset + 2 < data_size) {
409 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
410 unsigned int namelen = CVAL(pdata,offset);
412 offset++; /* Go past the namelen byte. */
414 /* integer wrap paranioa. */
415 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
416 (offset > data_size) || (namelen > data_size) ||
417 (offset + namelen >= data_size)) {
420 /* Ensure the name is null terminated. */
421 if (pdata[offset + namelen] != '\0') {
424 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
429 offset += (namelen + 1); /* Go past the name + terminating zero. */
430 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
431 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
437 /****************************************************************************
438 Read one EA list entry from the buffer.
439 ****************************************************************************/
441 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
443 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
445 unsigned int namelen;
455 eal->ea.flags = CVAL(pdata,0);
456 namelen = CVAL(pdata,1);
457 val_len = SVAL(pdata,2);
459 if (4 + namelen + 1 + val_len > data_size) {
463 /* Ensure the name is null terminated. */
464 if (pdata[namelen + 4] != '\0') {
467 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
472 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
473 if (!eal->ea.value.data) {
477 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
479 /* Ensure we're null terminated just in case we print the value. */
480 eal->ea.value.data[val_len] = '\0';
481 /* But don't count the null. */
482 eal->ea.value.length--;
485 *pbytes_used = 4 + namelen + 1 + val_len;
488 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
489 dump_data(10, eal->ea.value.data, eal->ea.value.length);
494 /****************************************************************************
495 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
496 ****************************************************************************/
498 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
500 struct ea_list *ea_list_head = NULL;
502 size_t bytes_used = 0;
504 while (offset < data_size) {
505 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
511 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
512 offset += bytes_used;
518 /****************************************************************************
519 Count the total EA size needed.
520 ****************************************************************************/
522 static size_t ea_list_size(struct ea_list *ealist)
525 struct ea_list *listp;
528 for (listp = ealist; listp; listp = listp->next) {
529 push_ascii_fstring(dos_ea_name, listp->ea.name);
530 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
532 /* Add on 4 for total length. */
540 /****************************************************************************
541 Return a union of EA's from a file list and a list of names.
542 The TALLOC context for the two lists *MUST* be identical as we steal
543 memory from one list to add to another. JRA.
544 ****************************************************************************/
546 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
548 struct ea_list *nlistp, *flistp;
550 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
551 for (flistp = file_list; flistp; flistp = flistp->next) {
552 if (strequal(nlistp->ea.name, flistp->ea.name)) {
558 /* Copy the data from this entry. */
559 nlistp->ea.flags = flistp->ea.flags;
560 nlistp->ea.value = flistp->ea.value;
563 nlistp->ea.flags = 0;
564 ZERO_STRUCT(nlistp->ea.value);
568 *total_ea_len = ea_list_size(name_list);
572 /****************************************************************************
573 Send the required number of replies back.
574 We assume all fields other than the data fields are
575 set correctly for the type of call.
576 HACK ! Always assumes smb_setup field is zero.
577 ****************************************************************************/
579 void send_trans2_replies(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 (!send_smb(smbd_server_fd(),(char *)req->outbuf))
742 exit_server_cleanly("send_trans2_replies: send_smb failed.");
744 TALLOC_FREE(req->outbuf);
746 pp += params_sent_thistime;
747 pd += data_sent_thistime;
749 params_to_send -= params_sent_thistime;
750 data_to_send -= data_sent_thistime;
753 if(params_to_send < 0 || data_to_send < 0) {
754 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
755 params_to_send, data_to_send));
763 /****************************************************************************
764 Reply to a TRANSACT2_OPEN.
765 ****************************************************************************/
767 static void call_trans2open(connection_struct *conn,
768 struct smb_request *req,
769 char **pparams, int total_params,
770 char **ppdata, int total_data,
771 unsigned int max_data_bytes)
773 char *params = *pparams;
774 char *pdata = *ppdata;
779 bool return_additional_info;
790 SMB_STRUCT_STAT sbuf;
793 struct ea_list *ea_list = NULL;
798 uint32 create_disposition;
799 uint32 create_options = 0;
800 TALLOC_CTX *ctx = talloc_tos();
803 * Ensure we have enough parameters to perform the operation.
806 if (total_params < 29) {
807 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
811 flags = SVAL(params, 0);
812 deny_mode = SVAL(params, 2);
813 open_attr = SVAL(params,6);
814 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
815 if (oplock_request) {
816 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
820 return_additional_info = BITSETW(params,0);
821 open_sattr = SVAL(params, 4);
822 open_time = make_unix_date3(params+8);
824 open_ofun = SVAL(params,12);
825 open_size = IVAL(params,14);
829 reply_doserror(req, ERRSRV, ERRaccess);
833 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
834 total_params - 28, STR_TERMINATE,
836 if (!NT_STATUS_IS_OK(status)) {
837 reply_nterror(req, status);
841 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
842 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
843 (unsigned int)open_ofun, open_size));
845 /* XXXX we need to handle passed times, sattr and flags */
847 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
848 if (!NT_STATUS_IS_OK(status)) {
849 reply_nterror(req, status);
853 status = check_name(conn, fname);
854 if (!NT_STATUS_IS_OK(status)) {
855 reply_nterror(req, status);
859 if (open_ofun == 0) {
860 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
864 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
869 reply_doserror(req, ERRDOS, ERRbadaccess);
873 /* Any data in this call is an EA list. */
874 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
875 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
879 if (total_data != 4) {
880 if (total_data < 10) {
881 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
885 if (IVAL(pdata,0) > total_data) {
886 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
887 IVAL(pdata,0), (unsigned int)total_data));
888 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
892 ea_list = read_ea_list(talloc_tos(), pdata + 4,
895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
898 } else if (IVAL(pdata,0) != 4) {
899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
903 status = open_file_ntcreate(conn, req, fname, &sbuf,
912 if (!NT_STATUS_IS_OK(status)) {
913 if (open_was_deferred(req->mid)) {
914 /* We have re-scheduled this call. */
917 reply_openerror(req, status);
921 size = get_file_size(sbuf);
922 fattr = dos_mode(conn,fname,&sbuf);
923 mtime = sbuf.st_mtime;
926 close_file(fsp,ERROR_CLOSE);
927 reply_doserror(req, ERRDOS,ERRnoaccess);
931 /* Save the requested allocation size. */
932 /* Allocate space for the file if a size hint is supplied */
933 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
934 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
935 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
936 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
937 if (fsp->is_directory) {
938 close_file(fsp,ERROR_CLOSE);
939 /* Can't set allocation size on a directory. */
940 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
943 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
944 close_file(fsp,ERROR_CLOSE);
945 reply_nterror(req, NT_STATUS_DISK_FULL);
949 /* Adjust size here to return the right size in the reply.
950 Windows does it this way. */
951 size = fsp->initial_allocation_size;
953 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
957 if (ea_list && smb_action == FILE_WAS_CREATED) {
958 status = set_ea(conn, fsp, fname, ea_list);
959 if (!NT_STATUS_IS_OK(status)) {
960 close_file(fsp,ERROR_CLOSE);
961 reply_nterror(req, status);
966 /* Realloc the size of parameters and data we will return */
967 *pparams = (char *)SMB_REALLOC(*pparams, 30);
968 if(*pparams == NULL ) {
969 reply_nterror(req, NT_STATUS_NO_MEMORY);
974 SSVAL(params,0,fsp->fnum);
975 SSVAL(params,2,fattr);
976 srv_put_dos_date2(params,4, mtime);
977 SIVAL(params,8, (uint32)size);
978 SSVAL(params,12,deny_mode);
979 SSVAL(params,14,0); /* open_type - file or directory. */
980 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
982 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
983 smb_action |= EXTENDED_OPLOCK_GRANTED;
986 SSVAL(params,18,smb_action);
989 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
991 SIVAL(params,20,inode);
992 SSVAL(params,24,0); /* Padding. */
994 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
995 SIVAL(params, 26, ea_size);
997 SIVAL(params, 26, 0);
1000 /* Send the required number of replies */
1001 send_trans2_replies(req, params, 30, *ppdata, 0, max_data_bytes);
1004 /*********************************************************
1005 Routine to check if a given string matches exactly.
1006 as a special case a mask of "." does NOT match. That
1007 is required for correct wildcard semantics
1008 Case can be significant or not.
1009 **********************************************************/
1011 static bool exact_match(connection_struct *conn,
1015 if (mask[0] == '.' && mask[1] == 0)
1017 if (conn->case_sensitive)
1018 return strcmp(str,mask)==0;
1019 if (StrCaseCmp(str,mask) != 0) {
1022 if (dptr_has_wild(conn->dirptr)) {
1028 /****************************************************************************
1029 Return the filetype for UNIX extensions.
1030 ****************************************************************************/
1032 static uint32 unix_filetype(mode_t mode)
1035 return UNIX_TYPE_FILE;
1036 else if(S_ISDIR(mode))
1037 return UNIX_TYPE_DIR;
1039 else if(S_ISLNK(mode))
1040 return UNIX_TYPE_SYMLINK;
1043 else if(S_ISCHR(mode))
1044 return UNIX_TYPE_CHARDEV;
1047 else if(S_ISBLK(mode))
1048 return UNIX_TYPE_BLKDEV;
1051 else if(S_ISFIFO(mode))
1052 return UNIX_TYPE_FIFO;
1055 else if(S_ISSOCK(mode))
1056 return UNIX_TYPE_SOCKET;
1059 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1060 return UNIX_TYPE_UNKNOWN;
1063 /****************************************************************************
1064 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1065 ****************************************************************************/
1067 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1069 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1070 SMB_STRUCT_STAT *psbuf,
1072 enum perm_type ptype,
1077 if (perms == SMB_MODE_NO_CHANGE) {
1078 if (!VALID_STAT(*psbuf)) {
1079 return NT_STATUS_INVALID_PARAMETER;
1081 *ret_perms = psbuf->st_mode;
1082 return NT_STATUS_OK;
1086 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1087 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1088 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1089 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1090 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1091 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1092 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1093 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1094 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1096 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1099 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1102 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1107 /* Apply mode mask */
1108 ret &= lp_create_mask(SNUM(conn));
1109 /* Add in force bits */
1110 ret |= lp_force_create_mode(SNUM(conn));
1113 ret &= lp_dir_mask(SNUM(conn));
1114 /* Add in force bits */
1115 ret |= lp_force_dir_mode(SNUM(conn));
1117 case PERM_EXISTING_FILE:
1118 /* Apply mode mask */
1119 ret &= lp_security_mask(SNUM(conn));
1120 /* Add in force bits */
1121 ret |= lp_force_security_mode(SNUM(conn));
1123 case PERM_EXISTING_DIR:
1124 /* Apply mode mask */
1125 ret &= lp_dir_security_mask(SNUM(conn));
1126 /* Add in force bits */
1127 ret |= lp_force_dir_security_mode(SNUM(conn));
1132 return NT_STATUS_OK;
1135 /****************************************************************************
1136 Get a level dependent lanman2 dir entry.
1137 ****************************************************************************/
1139 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1140 connection_struct *conn,
1142 const char *path_mask,
1145 int requires_resume_key,
1150 int space_remaining,
1152 bool *got_exact_match,
1153 int *last_entry_off,
1154 struct ea_list *name_list)
1158 SMB_STRUCT_STAT sbuf;
1159 const char *mask = NULL;
1160 char *pathreal = NULL;
1161 const char *fname = NULL;
1162 char *p, *q, *pdata = *ppdata;
1166 SMB_OFF_T file_size = 0;
1167 SMB_BIG_UINT allocation_size = 0;
1169 struct timespec mdate_ts, adate_ts, create_date_ts;
1170 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1172 char *last_entry_ptr;
1174 uint32 nt_extmode; /* Used for NT connections instead of mode */
1175 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1176 bool check_mangled_names = lp_manglednames(conn->params);
1177 char mangled_name[13]; /* mangled 8.3 name. */
1179 *out_of_space = False;
1180 *got_exact_match = False;
1182 ZERO_STRUCT(mdate_ts);
1183 ZERO_STRUCT(adate_ts);
1184 ZERO_STRUCT(create_date_ts);
1186 if (!conn->dirptr) {
1190 p = strrchr_m(path_mask,'/');
1193 mask = talloc_strdup(ctx,"*.*");
1203 bool ms_dfs_link = False;
1205 /* Needed if we run out of space */
1206 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1207 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1210 * Due to bugs in NT client redirectors we are not using
1211 * resume keys any more - set them to zero.
1212 * Check out the related comments in findfirst/findnext.
1218 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1219 (long)conn->dirptr,curr_dirpos));
1226 * fname may get mangled, dname is never mangled.
1227 * Whenever we're accessing the filesystem we use
1228 * pathreal which is composed from dname.
1234 /* Mangle fname if it's an illegal name. */
1235 if (mangle_must_mangle(dname,conn->params)) {
1236 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1237 continue; /* Error - couldn't mangle. */
1239 fname = mangled_name;
1242 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1243 got_match = mask_match(fname, mask, conn->case_sensitive);
1246 if(!got_match && check_mangled_names &&
1247 !mangle_is_8_3(fname, False, conn->params)) {
1249 * It turns out that NT matches wildcards against
1250 * both long *and* short names. This may explain some
1251 * of the wildcard wierdness from old DOS clients
1252 * that some people have been seeing.... JRA.
1254 /* Force the mangling into 8.3. */
1255 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1256 continue; /* Error - couldn't mangle. */
1259 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1260 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1265 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1267 if (dont_descend && !isdots) {
1273 pathreal = talloc_asprintf(ctx,
1278 pathreal = talloc_asprintf(ctx,
1288 if (INFO_LEVEL_IS_UNIX(info_level)) {
1289 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1290 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1291 pathreal,strerror(errno)));
1292 TALLOC_FREE(pathreal);
1295 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1296 /* Needed to show the msdfs symlinks as
1299 if(lp_host_msdfs() &&
1300 lp_msdfs_root(SNUM(conn)) &&
1301 ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) {
1302 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1305 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1309 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1310 pathreal,strerror(errno)));
1311 TALLOC_FREE(pathreal);
1317 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1319 mode = dos_mode(conn,pathreal,&sbuf);
1322 if (!dir_check_ftype(conn,mode,dirtype)) {
1323 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1324 TALLOC_FREE(pathreal);
1328 if (!(mode & aDIR)) {
1329 file_size = get_file_size(sbuf);
1331 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1333 mdate_ts = get_mtimespec(&sbuf);
1334 adate_ts = get_atimespec(&sbuf);
1335 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1337 if (lp_dos_filetime_resolution(SNUM(conn))) {
1338 dos_filetime_timespec(&create_date_ts);
1339 dos_filetime_timespec(&mdate_ts);
1340 dos_filetime_timespec(&adate_ts);
1343 create_date = convert_timespec_to_time_t(create_date_ts);
1344 mdate = convert_timespec_to_time_t(mdate_ts);
1345 adate = convert_timespec_to_time_t(adate_ts);
1347 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1351 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1358 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1360 switch (info_level) {
1361 case SMB_FIND_INFO_STANDARD:
1362 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1363 if(requires_resume_key) {
1367 srv_put_dos_date2(p,0,create_date);
1368 srv_put_dos_date2(p,4,adate);
1369 srv_put_dos_date2(p,8,mdate);
1370 SIVAL(p,12,(uint32)file_size);
1371 SIVAL(p,16,(uint32)allocation_size);
1375 p += align_string(pdata, p, 0);
1376 len = srvstr_push(base_data, flags2, p,
1377 fname, PTR_DIFF(end_data, p),
1379 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1381 SCVAL(nameptr, -1, len - 2);
1383 SCVAL(nameptr, -1, 0);
1387 SCVAL(nameptr, -1, len - 1);
1389 SCVAL(nameptr, -1, 0);
1395 case SMB_FIND_EA_SIZE:
1396 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1397 if(requires_resume_key) {
1401 srv_put_dos_date2(p,0,create_date);
1402 srv_put_dos_date2(p,4,adate);
1403 srv_put_dos_date2(p,8,mdate);
1404 SIVAL(p,12,(uint32)file_size);
1405 SIVAL(p,16,(uint32)allocation_size);
1408 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1409 SIVAL(p,22,ea_size); /* Extended attributes */
1413 len = srvstr_push(base_data, flags2,
1414 p, fname, PTR_DIFF(end_data, p),
1415 STR_TERMINATE | STR_NOALIGN);
1416 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1429 SCVAL(nameptr,0,len);
1431 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1434 case SMB_FIND_EA_LIST:
1436 struct ea_list *file_list = NULL;
1439 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1443 if(requires_resume_key) {
1447 srv_put_dos_date2(p,0,create_date);
1448 srv_put_dos_date2(p,4,adate);
1449 srv_put_dos_date2(p,8,mdate);
1450 SIVAL(p,12,(uint32)file_size);
1451 SIVAL(p,16,(uint32)allocation_size);
1453 p += 22; /* p now points to the EA area. */
1455 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1456 name_list = ea_list_union(name_list, file_list, &ea_len);
1458 /* We need to determine if this entry will fit in the space available. */
1459 /* Max string size is 255 bytes. */
1460 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1461 /* Move the dirptr back to prev_dirpos */
1462 dptr_SeekDir(conn->dirptr, prev_dirpos);
1463 *out_of_space = True;
1464 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1465 return False; /* Not finished - just out of space */
1468 /* Push the ea_data followed by the name. */
1469 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1471 len = srvstr_push(base_data, flags2,
1472 p + 1, fname, PTR_DIFF(end_data, p+1),
1473 STR_TERMINATE | STR_NOALIGN);
1474 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1487 SCVAL(nameptr,0,len);
1489 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1493 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1494 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1495 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1497 SIVAL(p,0,reskey); p += 4;
1498 put_long_date_timespec(p,create_date_ts); p += 8;
1499 put_long_date_timespec(p,adate_ts); p += 8;
1500 put_long_date_timespec(p,mdate_ts); p += 8;
1501 put_long_date_timespec(p,mdate_ts); p += 8;
1502 SOFF_T(p,0,file_size); p += 8;
1503 SOFF_T(p,0,allocation_size); p += 8;
1504 SIVAL(p,0,nt_extmode); p += 4;
1505 q = p; p += 4; /* q is placeholder for name length. */
1507 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1508 SIVAL(p,0,ea_size); /* Extended attributes */
1511 /* Clear the short name buffer. This is
1512 * IMPORTANT as not doing so will trigger
1513 * a Win2k client bug. JRA.
1515 if (!was_8_3 && check_mangled_names) {
1516 if (!name_to_8_3(fname,mangled_name,True,
1518 /* Error - mangle failed ! */
1519 memset(mangled_name,'\0',12);
1521 mangled_name[12] = 0;
1522 len = srvstr_push(base_data, flags2,
1523 p+2, mangled_name, 24,
1524 STR_UPPER|STR_UNICODE);
1526 memset(p + 2 + len,'\0',24 - len);
1533 len = srvstr_push(base_data, flags2, p,
1534 fname, PTR_DIFF(end_data, p),
1535 STR_TERMINATE_ASCII);
1538 SIVAL(p,0,0); /* Ensure any padding is null. */
1539 len = PTR_DIFF(p, pdata);
1540 len = (len + 3) & ~3;
1545 case SMB_FIND_FILE_DIRECTORY_INFO:
1546 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1548 SIVAL(p,0,reskey); p += 4;
1549 put_long_date_timespec(p,create_date_ts); p += 8;
1550 put_long_date_timespec(p,adate_ts); p += 8;
1551 put_long_date_timespec(p,mdate_ts); p += 8;
1552 put_long_date_timespec(p,mdate_ts); p += 8;
1553 SOFF_T(p,0,file_size); p += 8;
1554 SOFF_T(p,0,allocation_size); p += 8;
1555 SIVAL(p,0,nt_extmode); p += 4;
1556 len = srvstr_push(base_data, flags2,
1557 p + 4, fname, PTR_DIFF(end_data, p+4),
1558 STR_TERMINATE_ASCII);
1561 SIVAL(p,0,0); /* Ensure any padding is null. */
1562 len = PTR_DIFF(p, pdata);
1563 len = (len + 3) & ~3;
1568 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1569 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1571 SIVAL(p,0,reskey); p += 4;
1572 put_long_date_timespec(p,create_date_ts); p += 8;
1573 put_long_date_timespec(p,adate_ts); p += 8;
1574 put_long_date_timespec(p,mdate_ts); p += 8;
1575 put_long_date_timespec(p,mdate_ts); p += 8;
1576 SOFF_T(p,0,file_size); p += 8;
1577 SOFF_T(p,0,allocation_size); p += 8;
1578 SIVAL(p,0,nt_extmode); p += 4;
1579 q = p; p += 4; /* q is placeholder for name length. */
1581 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1582 SIVAL(p,0,ea_size); /* Extended attributes */
1585 len = srvstr_push(base_data, flags2, p,
1586 fname, PTR_DIFF(end_data, p),
1587 STR_TERMINATE_ASCII);
1591 SIVAL(p,0,0); /* Ensure any padding is null. */
1592 len = PTR_DIFF(p, pdata);
1593 len = (len + 3) & ~3;
1598 case SMB_FIND_FILE_NAMES_INFO:
1599 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1601 SIVAL(p,0,reskey); p += 4;
1603 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1604 acl on a dir (tridge) */
1605 len = srvstr_push(base_data, flags2, p,
1606 fname, PTR_DIFF(end_data, p),
1607 STR_TERMINATE_ASCII);
1610 SIVAL(p,0,0); /* Ensure any padding is null. */
1611 len = PTR_DIFF(p, pdata);
1612 len = (len + 3) & ~3;
1617 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1618 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1620 SIVAL(p,0,reskey); p += 4;
1621 put_long_date_timespec(p,create_date_ts); p += 8;
1622 put_long_date_timespec(p,adate_ts); p += 8;
1623 put_long_date_timespec(p,mdate_ts); p += 8;
1624 put_long_date_timespec(p,mdate_ts); p += 8;
1625 SOFF_T(p,0,file_size); p += 8;
1626 SOFF_T(p,0,allocation_size); p += 8;
1627 SIVAL(p,0,nt_extmode); p += 4;
1628 q = p; p += 4; /* q is placeholder for name length. */
1630 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1631 SIVAL(p,0,ea_size); /* Extended attributes */
1634 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1635 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1636 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1637 len = srvstr_push(base_data, flags2, p,
1638 fname, PTR_DIFF(end_data, p),
1639 STR_TERMINATE_ASCII);
1642 SIVAL(p,0,0); /* Ensure any padding is null. */
1643 len = PTR_DIFF(p, pdata);
1644 len = (len + 3) & ~3;
1649 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1650 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1651 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1653 SIVAL(p,0,reskey); p += 4;
1654 put_long_date_timespec(p,create_date_ts); p += 8;
1655 put_long_date_timespec(p,adate_ts); p += 8;
1656 put_long_date_timespec(p,mdate_ts); p += 8;
1657 put_long_date_timespec(p,mdate_ts); p += 8;
1658 SOFF_T(p,0,file_size); p += 8;
1659 SOFF_T(p,0,allocation_size); p += 8;
1660 SIVAL(p,0,nt_extmode); p += 4;
1661 q = p; p += 4; /* q is placeholder for name length */
1663 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1664 SIVAL(p,0,ea_size); /* Extended attributes */
1667 /* Clear the short name buffer. This is
1668 * IMPORTANT as not doing so will trigger
1669 * a Win2k client bug. JRA.
1671 if (!was_8_3 && check_mangled_names) {
1672 if (!name_to_8_3(fname,mangled_name,True,
1674 /* Error - mangle failed ! */
1675 memset(mangled_name,'\0',12);
1677 mangled_name[12] = 0;
1678 len = srvstr_push(base_data, flags2,
1679 p+2, mangled_name, 24,
1680 STR_UPPER|STR_UNICODE);
1683 memset(p + 2 + len,'\0',24 - len);
1690 SSVAL(p,0,0); p += 2; /* Reserved ? */
1691 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1692 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1693 len = srvstr_push(base_data, flags2, p,
1694 fname, PTR_DIFF(end_data, p),
1695 STR_TERMINATE_ASCII);
1698 SIVAL(p,0,0); /* Ensure any padding is null. */
1699 len = PTR_DIFF(p, pdata);
1700 len = (len + 3) & ~3;
1705 /* CIFS UNIX Extension. */
1707 case SMB_FIND_FILE_UNIX:
1708 case SMB_FIND_FILE_UNIX_INFO2:
1710 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1712 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1714 if (info_level == SMB_FIND_FILE_UNIX) {
1715 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1716 p = store_file_unix_basic(conn, p,
1718 len = srvstr_push(base_data, flags2, p,
1719 fname, PTR_DIFF(end_data, p),
1722 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1723 p = store_file_unix_basic_info2(conn, p,
1727 len = srvstr_push(base_data, flags2, p, fname,
1728 PTR_DIFF(end_data, p), 0);
1729 SIVAL(nameptr, 0, len);
1733 SIVAL(p,0,0); /* Ensure any padding is null. */
1735 len = PTR_DIFF(p, pdata);
1736 len = (len + 3) & ~3;
1737 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1739 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1748 if (PTR_DIFF(p,pdata) > space_remaining) {
1749 /* Move the dirptr back to prev_dirpos */
1750 dptr_SeekDir(conn->dirptr, prev_dirpos);
1751 *out_of_space = True;
1752 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1753 return False; /* Not finished - just out of space */
1756 /* Setup the last entry pointer, as an offset from base_data */
1757 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1758 /* Advance the data pointer to the next slot */
1764 /****************************************************************************
1765 Reply to a TRANS2_FINDFIRST.
1766 ****************************************************************************/
1768 static void call_trans2findfirst(connection_struct *conn,
1769 struct smb_request *req,
1770 char **pparams, int total_params,
1771 char **ppdata, int total_data,
1772 unsigned int max_data_bytes)
1774 /* We must be careful here that we don't return more than the
1775 allowed number of data bytes. If this means returning fewer than
1776 maxentries then so be it. We assume that the redirector has
1777 enough room for the fixed number of parameter bytes it has
1779 char *params = *pparams;
1780 char *pdata = *ppdata;
1784 uint16 findfirst_flags;
1785 bool close_after_first;
1787 bool requires_resume_key;
1789 char *directory = NULL;
1790 const char *mask = NULL;
1792 int last_entry_off=0;
1796 bool finished = False;
1797 bool dont_descend = False;
1798 bool out_of_space = False;
1799 int space_remaining;
1800 bool mask_contains_wcard = False;
1801 SMB_STRUCT_STAT sbuf;
1802 struct ea_list *ea_list = NULL;
1803 NTSTATUS ntstatus = NT_STATUS_OK;
1804 TALLOC_CTX *ctx = talloc_tos();
1806 if (total_params < 13) {
1807 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1811 dirtype = SVAL(params,0);
1812 maxentries = SVAL(params,2);
1813 findfirst_flags = SVAL(params,4);
1814 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1815 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1816 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1817 info_level = SVAL(params,6);
1819 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1820 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1821 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1822 info_level, max_data_bytes));
1825 /* W2K3 seems to treat zero as 1. */
1829 switch (info_level) {
1830 case SMB_FIND_INFO_STANDARD:
1831 case SMB_FIND_EA_SIZE:
1832 case SMB_FIND_EA_LIST:
1833 case SMB_FIND_FILE_DIRECTORY_INFO:
1834 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1835 case SMB_FIND_FILE_NAMES_INFO:
1836 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1837 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1838 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1840 case SMB_FIND_FILE_UNIX:
1841 case SMB_FIND_FILE_UNIX_INFO2:
1842 if (!lp_unix_extensions()) {
1843 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1848 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1852 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1853 params+12, total_params - 12,
1854 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1855 if (!NT_STATUS_IS_OK(ntstatus)) {
1856 reply_nterror(req, ntstatus);
1860 ntstatus = resolve_dfspath_wcard(ctx, conn,
1861 req->flags2 & FLAGS2_DFS_PATHNAMES,
1864 &mask_contains_wcard);
1865 if (!NT_STATUS_IS_OK(ntstatus)) {
1866 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1867 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1868 ERRSRV, ERRbadpath);
1871 reply_nterror(req, ntstatus);
1875 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1876 if (!NT_STATUS_IS_OK(ntstatus)) {
1877 reply_nterror(req, ntstatus);
1881 ntstatus = check_name(conn, directory);
1882 if (!NT_STATUS_IS_OK(ntstatus)) {
1883 reply_nterror(req, ntstatus);
1887 p = strrchr_m(directory,'/');
1889 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1890 if((directory[0] == '.') && (directory[1] == '\0')) {
1892 mask_contains_wcard = True;
1896 directory = talloc_strdup(talloc_tos(), "./");
1898 reply_nterror(req, NT_STATUS_NO_MEMORY);
1906 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1908 if (info_level == SMB_FIND_EA_LIST) {
1911 if (total_data < 4) {
1912 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1916 ea_size = IVAL(pdata,0);
1917 if (ea_size != total_data) {
1918 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1919 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1920 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1924 if (!lp_ea_support(SNUM(conn))) {
1925 reply_doserror(req, ERRDOS, ERReasnotsupported);
1929 /* Pull out the list of names. */
1930 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1932 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1937 *ppdata = (char *)SMB_REALLOC(
1938 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1939 if(*ppdata == NULL ) {
1940 reply_nterror(req, NT_STATUS_NO_MEMORY);
1944 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1946 /* Realloc the params space */
1947 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1948 if (*pparams == NULL) {
1949 reply_nterror(req, NT_STATUS_NO_MEMORY);
1954 /* Save the wildcard match and attribs we are using on this directory -
1955 needed as lanman2 assumes these are being saved between calls */
1957 ntstatus = dptr_create(conn,
1963 mask_contains_wcard,
1967 if (!NT_STATUS_IS_OK(ntstatus)) {
1968 reply_nterror(req, ntstatus);
1972 dptr_num = dptr_dnum(conn->dirptr);
1973 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1975 /* We don't need to check for VOL here as this is returned by
1976 a different TRANS2 call. */
1978 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1979 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1980 dont_descend = True;
1983 space_remaining = max_data_bytes;
1984 out_of_space = False;
1986 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1987 bool got_exact_match = False;
1989 /* this is a heuristic to avoid seeking the dirptr except when
1990 absolutely necessary. It allows for a filename of about 40 chars */
1991 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1992 out_of_space = True;
1995 TALLOC_CTX *sub_ctx = talloc_stackframe();
1997 finished = !get_lanman2_dir_entry(sub_ctx,
2000 mask,dirtype,info_level,
2001 requires_resume_key,dont_descend,
2003 space_remaining, &out_of_space,
2005 &last_entry_off, ea_list);
2007 TALLOC_FREE(sub_ctx);
2010 if (finished && out_of_space)
2013 if (!finished && !out_of_space)
2017 * As an optimisation if we know we aren't looking
2018 * for a wildcard name (ie. the name matches the wildcard exactly)
2019 * then we can finish on any (first) match.
2020 * This speeds up large directory searches. JRA.
2026 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2029 /* Check if we can close the dirptr */
2030 if(close_after_first || (finished && close_if_end)) {
2031 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2032 dptr_close(&dptr_num);
2036 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2037 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2038 * the protocol level is less than NT1. Tested with smbclient. JRA.
2039 * This should fix the OS/2 client bug #2335.
2042 if(numentries == 0) {
2043 dptr_close(&dptr_num);
2044 if (Protocol < PROTOCOL_NT1) {
2045 reply_doserror(req, ERRDOS, ERRnofiles);
2048 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2049 ERRDOS, ERRbadfile);
2054 /* At this point pdata points to numentries directory entries. */
2056 /* Set up the return parameter block */
2057 SSVAL(params,0,dptr_num);
2058 SSVAL(params,2,numentries);
2059 SSVAL(params,4,finished);
2060 SSVAL(params,6,0); /* Never an EA error */
2061 SSVAL(params,8,last_entry_off);
2063 send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
2066 if ((! *directory) && dptr_path(dptr_num)) {
2067 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2069 reply_nterror(req, NT_STATUS_NO_MEMORY);
2073 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2074 smb_fn_name(CVAL(req->inbuf,smb_com)),
2075 mask, directory, dirtype, numentries ) );
2078 * Force a name mangle here to ensure that the
2079 * mask as an 8.3 name is top of the mangled cache.
2080 * The reasons for this are subtle. Don't remove
2081 * this code unless you know what you are doing
2082 * (see PR#13758). JRA.
2085 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2086 char mangled_name[13];
2087 name_to_8_3(mask, mangled_name, True, conn->params);
2093 /****************************************************************************
2094 Reply to a TRANS2_FINDNEXT.
2095 ****************************************************************************/
2097 static void call_trans2findnext(connection_struct *conn,
2098 struct smb_request *req,
2099 char **pparams, int total_params,
2100 char **ppdata, int total_data,
2101 unsigned int max_data_bytes)
2103 /* We must be careful here that we don't return more than the
2104 allowed number of data bytes. If this means returning fewer than
2105 maxentries then so be it. We assume that the redirector has
2106 enough room for the fixed number of parameter bytes it has
2108 char *params = *pparams;
2109 char *pdata = *ppdata;
2115 uint16 findnext_flags;
2116 bool close_after_request;
2118 bool requires_resume_key;
2120 bool mask_contains_wcard = False;
2121 char *resume_name = NULL;
2122 const char *mask = NULL;
2123 const char *directory = NULL;
2127 int i, last_entry_off=0;
2128 bool finished = False;
2129 bool dont_descend = False;
2130 bool out_of_space = False;
2131 int space_remaining;
2132 struct ea_list *ea_list = NULL;
2133 NTSTATUS ntstatus = NT_STATUS_OK;
2134 TALLOC_CTX *ctx = talloc_tos();
2136 if (total_params < 13) {
2137 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2141 dptr_num = SVAL(params,0);
2142 maxentries = SVAL(params,2);
2143 info_level = SVAL(params,4);
2144 resume_key = IVAL(params,6);
2145 findnext_flags = SVAL(params,10);
2146 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2147 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2148 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2149 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2151 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2153 total_params - 12, STR_TERMINATE, &ntstatus,
2154 &mask_contains_wcard);
2155 if (!NT_STATUS_IS_OK(ntstatus)) {
2156 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2157 complain (it thinks we're asking for the directory above the shared
2158 path or an invalid name). Catch this as the resume name is only compared, never used in
2159 a file access. JRA. */
2160 srvstr_pull_talloc(ctx, params, req->flags2,
2161 &resume_name, params+12,
2165 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2166 reply_nterror(req, ntstatus);
2171 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2172 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2173 resume_key = %d resume name = %s continue=%d level = %d\n",
2174 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2175 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2178 /* W2K3 seems to treat zero as 1. */
2182 switch (info_level) {
2183 case SMB_FIND_INFO_STANDARD:
2184 case SMB_FIND_EA_SIZE:
2185 case SMB_FIND_EA_LIST:
2186 case SMB_FIND_FILE_DIRECTORY_INFO:
2187 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2188 case SMB_FIND_FILE_NAMES_INFO:
2189 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2190 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2191 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2193 case SMB_FIND_FILE_UNIX:
2194 case SMB_FIND_FILE_UNIX_INFO2:
2195 if (!lp_unix_extensions()) {
2196 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2201 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2205 if (info_level == SMB_FIND_EA_LIST) {
2208 if (total_data < 4) {
2209 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2213 ea_size = IVAL(pdata,0);
2214 if (ea_size != total_data) {
2215 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2216 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2217 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2221 if (!lp_ea_support(SNUM(conn))) {
2222 reply_doserror(req, ERRDOS, ERReasnotsupported);
2226 /* Pull out the list of names. */
2227 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2229 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2234 *ppdata = (char *)SMB_REALLOC(
2235 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2236 if(*ppdata == NULL) {
2237 reply_nterror(req, NT_STATUS_NO_MEMORY);
2242 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2244 /* Realloc the params space */
2245 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2246 if(*pparams == NULL ) {
2247 reply_nterror(req, NT_STATUS_NO_MEMORY);
2253 /* Check that the dptr is valid */
2254 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2255 reply_doserror(req, ERRDOS, ERRnofiles);
2259 string_set(&conn->dirpath,dptr_path(dptr_num));
2261 /* Get the wildcard mask from the dptr */
2262 if((p = dptr_wcard(dptr_num))== NULL) {
2263 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2264 reply_doserror(req, ERRDOS, ERRnofiles);
2269 directory = conn->dirpath;
2271 /* Get the attr mask from the dptr */
2272 dirtype = dptr_attr(dptr_num);
2274 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2275 dptr_num, mask, dirtype,
2277 dptr_TellDir(conn->dirptr)));
2279 /* We don't need to check for VOL here as this is returned by
2280 a different TRANS2 call. */
2282 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2283 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2284 dont_descend = True;
2287 space_remaining = max_data_bytes;
2288 out_of_space = False;
2291 * Seek to the correct position. We no longer use the resume key but
2292 * depend on the last file name instead.
2295 if(*resume_name && !continue_bit) {
2298 long current_pos = 0;
2300 * Remember, name_to_8_3 is called by
2301 * get_lanman2_dir_entry(), so the resume name
2302 * could be mangled. Ensure we check the unmangled name.
2305 if (mangle_is_mangled(resume_name, conn->params)) {
2306 char *new_resume_name = NULL;
2307 mangle_lookup_name_from_8_3(ctx,
2311 if (new_resume_name) {
2312 resume_name = new_resume_name;
2317 * Fix for NT redirector problem triggered by resume key indexes
2318 * changing between directory scans. We now return a resume key of 0
2319 * and instead look for the filename to continue from (also given
2320 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2321 * findfirst/findnext (as is usual) then the directory pointer
2322 * should already be at the correct place.
2325 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2326 } /* end if resume_name && !continue_bit */
2328 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2329 bool got_exact_match = False;
2331 /* this is a heuristic to avoid seeking the dirptr except when
2332 absolutely necessary. It allows for a filename of about 40 chars */
2333 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2334 out_of_space = True;
2337 TALLOC_CTX *sub_ctx = talloc_stackframe();
2339 finished = !get_lanman2_dir_entry(sub_ctx,
2342 mask,dirtype,info_level,
2343 requires_resume_key,dont_descend,
2345 space_remaining, &out_of_space,
2347 &last_entry_off, ea_list);
2349 TALLOC_FREE(sub_ctx);
2352 if (finished && out_of_space)
2355 if (!finished && !out_of_space)
2359 * As an optimisation if we know we aren't looking
2360 * for a wildcard name (ie. the name matches the wildcard exactly)
2361 * then we can finish on any (first) match.
2362 * This speeds up large directory searches. JRA.
2368 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2371 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2372 smb_fn_name(CVAL(req->inbuf,smb_com)),
2373 mask, directory, dirtype, numentries ) );
2375 /* Check if we can close the dirptr */
2376 if(close_after_request || (finished && close_if_end)) {
2377 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2378 dptr_close(&dptr_num); /* This frees up the saved mask */
2381 /* Set up the return parameter block */
2382 SSVAL(params,0,numentries);
2383 SSVAL(params,2,finished);
2384 SSVAL(params,4,0); /* Never an EA error */
2385 SSVAL(params,6,last_entry_off);
2387 send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata),
2393 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2395 E_md4hash(lp_servicename(SNUM(conn)),objid);
2399 /****************************************************************************
2400 Reply to a TRANS2_QFSINFO (query filesystem info).
2401 ****************************************************************************/
2403 static void call_trans2qfsinfo(connection_struct *conn,
2404 struct smb_request *req,
2405 char **pparams, int total_params,
2406 char **ppdata, int total_data,
2407 unsigned int max_data_bytes)
2409 char *pdata, *end_data;
2410 char *params = *pparams;
2414 const char *vname = volume_label(SNUM(conn));
2415 int snum = SNUM(conn);
2416 char *fstype = lp_fstype(SNUM(conn));
2419 if (total_params < 2) {
2420 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2424 info_level = SVAL(params,0);
2426 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2428 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2429 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2430 reply_doserror(req, ERRSRV, ERRinvdevice);
2434 *ppdata = (char *)SMB_REALLOC(
2435 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2436 if (*ppdata == NULL ) {
2437 reply_nterror(req, NT_STATUS_NO_MEMORY);
2442 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2443 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2445 switch (info_level) {
2446 case SMB_INFO_ALLOCATION:
2448 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2450 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2451 reply_unixerror(req, ERRHRD, ERRgeneral);
2455 block_size = lp_block_size(snum);
2456 if (bsize < block_size) {
2457 SMB_BIG_UINT factor = block_size/bsize;
2462 if (bsize > block_size) {
2463 SMB_BIG_UINT factor = bsize/block_size;
2468 bytes_per_sector = 512;
2469 sectors_per_unit = bsize/bytes_per_sector;
2471 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2472 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2473 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2475 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2476 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2477 SIVAL(pdata,l1_cUnit,dsize);
2478 SIVAL(pdata,l1_cUnitAvail,dfree);
2479 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2483 case SMB_INFO_VOLUME:
2484 /* Return volume name */
2486 * Add volume serial number - hash of a combination of
2487 * the called hostname and the service name.
2489 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2491 * Win2k3 and previous mess this up by sending a name length
2492 * one byte short. I believe only older clients (OS/2 Win9x) use
2493 * this call so try fixing this by adding a terminating null to
2494 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2498 pdata+l2_vol_szVolLabel, vname,
2499 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2500 STR_NOALIGN|STR_TERMINATE);
2501 SCVAL(pdata,l2_vol_cch,len);
2502 data_len = l2_vol_szVolLabel + len;
2503 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2504 (unsigned)st.st_ctime, len, vname));
2507 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2508 case SMB_FS_ATTRIBUTE_INFORMATION:
2511 #if defined(HAVE_SYS_QUOTAS)
2512 quota_flag = FILE_VOLUME_QUOTAS;
2515 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2516 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2517 FILE_SUPPORTS_OBJECT_IDS|
2518 FILE_UNICODE_ON_DISK|
2519 quota_flag); /* FS ATTRIBUTES */
2521 SIVAL(pdata,4,255); /* Max filename component length */
2522 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2523 and will think we can't do long filenames */
2524 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2525 PTR_DIFF(end_data, pdata+12),
2528 data_len = 12 + len;
2531 case SMB_QUERY_FS_LABEL_INFO:
2532 case SMB_FS_LABEL_INFORMATION:
2533 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2534 PTR_DIFF(end_data, pdata+4), 0);
2539 case SMB_QUERY_FS_VOLUME_INFO:
2540 case SMB_FS_VOLUME_INFORMATION:
2543 * Add volume serial number - hash of a combination of
2544 * the called hostname and the service name.
2546 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2547 (str_checksum(get_local_machine_name())<<16));
2549 /* Max label len is 32 characters. */
2550 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2551 PTR_DIFF(end_data, pdata+18),
2553 SIVAL(pdata,12,len);
2556 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2557 (int)strlen(vname),vname, lp_servicename(snum)));
2560 case SMB_QUERY_FS_SIZE_INFO:
2561 case SMB_FS_SIZE_INFORMATION:
2563 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2565 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2566 reply_unixerror(req, ERRHRD, ERRgeneral);
2569 block_size = lp_block_size(snum);
2570 if (bsize < block_size) {
2571 SMB_BIG_UINT factor = block_size/bsize;
2576 if (bsize > block_size) {
2577 SMB_BIG_UINT factor = bsize/block_size;
2582 bytes_per_sector = 512;
2583 sectors_per_unit = bsize/bytes_per_sector;
2584 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2585 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2586 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2587 SBIG_UINT(pdata,0,dsize);
2588 SBIG_UINT(pdata,8,dfree);
2589 SIVAL(pdata,16,sectors_per_unit);
2590 SIVAL(pdata,20,bytes_per_sector);
2594 case SMB_FS_FULL_SIZE_INFORMATION:
2596 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2598 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2599 reply_unixerror(req, ERRHRD, ERRgeneral);
2602 block_size = lp_block_size(snum);
2603 if (bsize < block_size) {
2604 SMB_BIG_UINT factor = block_size/bsize;
2609 if (bsize > block_size) {
2610 SMB_BIG_UINT factor = bsize/block_size;
2615 bytes_per_sector = 512;
2616 sectors_per_unit = bsize/bytes_per_sector;
2617 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2618 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2619 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2620 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2621 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2622 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2623 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2624 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2628 case SMB_QUERY_FS_DEVICE_INFO:
2629 case SMB_FS_DEVICE_INFORMATION:
2631 SIVAL(pdata,0,0); /* dev type */
2632 SIVAL(pdata,4,0); /* characteristics */
2635 #ifdef HAVE_SYS_QUOTAS
2636 case SMB_FS_QUOTA_INFORMATION:
2638 * what we have to send --metze:
2640 * Unknown1: 24 NULL bytes
2641 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2642 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2643 * Quota Flags: 2 byte :
2644 * Unknown3: 6 NULL bytes
2648 * details for Quota Flags:
2650 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2651 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2652 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2653 * 0x0001 Enable Quotas: enable quota for this fs
2657 /* we need to fake up a fsp here,
2658 * because its not send in this call
2661 SMB_NTQUOTA_STRUCT quotas;
2664 ZERO_STRUCT(quotas);
2670 if (current_user.ut.uid != 0) {
2671 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2672 lp_servicename(SNUM(conn)),conn->user));
2673 reply_doserror(req, ERRDOS, ERRnoaccess);
2677 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2678 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2679 reply_doserror(req, ERRSRV, ERRerror);
2685 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2687 /* Unknown1 24 NULL bytes*/
2688 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2689 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2690 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2692 /* Default Soft Quota 8 bytes */
2693 SBIG_UINT(pdata,24,quotas.softlim);
2695 /* Default Hard Quota 8 bytes */
2696 SBIG_UINT(pdata,32,quotas.hardlim);
2698 /* Quota flag 2 bytes */
2699 SSVAL(pdata,40,quotas.qflags);
2701 /* Unknown3 6 NULL bytes */
2707 #endif /* HAVE_SYS_QUOTAS */
2708 case SMB_FS_OBJECTID_INFORMATION:
2710 unsigned char objid[16];
2711 memcpy(pdata,create_volume_objectid(conn, objid),16);
2717 * Query the version and capabilities of the CIFS UNIX extensions
2721 case SMB_QUERY_CIFS_UNIX_INFO:
2723 bool large_write = lp_min_receive_file_size() &&
2724 !srv_is_signing_active();
2726 if (!lp_unix_extensions()) {
2727 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2731 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2732 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2733 /* We have POSIX ACLs, pathname and locking capability. */
2734 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2735 CIFS_UNIX_POSIX_ACLS_CAP|
2736 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2737 CIFS_UNIX_FCNTL_LOCKS_CAP|
2738 CIFS_UNIX_EXTATTR_CAP|
2739 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2740 CIFS_UNIX_LARGE_READ_CAP|
2742 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2746 case SMB_QUERY_POSIX_FS_INFO:
2749 vfs_statvfs_struct svfs;
2751 if (!lp_unix_extensions()) {
2752 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2756 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2760 SIVAL(pdata,0,svfs.OptimalTransferSize);
2761 SIVAL(pdata,4,svfs.BlockSize);
2762 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2763 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2764 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2765 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2766 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2767 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2768 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2770 } else if (rc == EOPNOTSUPP) {
2771 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2773 #endif /* EOPNOTSUPP */
2775 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2776 reply_doserror(req, ERRSRV, ERRerror);
2782 case SMB_QUERY_POSIX_WHOAMI:
2788 if (!lp_unix_extensions()) {
2789 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2793 if (max_data_bytes < 40) {
2794 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2798 /* We ARE guest if global_sid_Builtin_Guests is
2799 * in our list of SIDs.
2801 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2802 current_user.nt_user_token)) {
2803 flags |= SMB_WHOAMI_GUEST;
2806 /* We are NOT guest if global_sid_Authenticated_Users
2807 * is in our list of SIDs.
2809 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2810 current_user.nt_user_token)) {
2811 flags &= ~SMB_WHOAMI_GUEST;
2814 /* NOTE: 8 bytes for UID/GID, irrespective of native
2815 * platform size. This matches
2816 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2818 data_len = 4 /* flags */
2825 + 4 /* pad/reserved */
2826 + (current_user.ut.ngroups * 8)
2828 + (current_user.nt_user_token->num_sids *
2832 SIVAL(pdata, 0, flags);
2833 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2834 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2835 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2838 if (data_len >= max_data_bytes) {
2839 /* Potential overflow, skip the GIDs and SIDs. */
2841 SIVAL(pdata, 24, 0); /* num_groups */
2842 SIVAL(pdata, 28, 0); /* num_sids */
2843 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2844 SIVAL(pdata, 36, 0); /* reserved */
2850 SIVAL(pdata, 24, current_user.ut.ngroups);
2852 current_user.nt_user_token->num_sids);
2854 /* We walk the SID list twice, but this call is fairly
2855 * infrequent, and I don't expect that it's performance
2856 * sensitive -- jpeach
2858 for (i = 0, sid_bytes = 0;
2859 i < current_user.nt_user_token->num_sids; ++i) {
2861 sid_size(¤t_user.nt_user_token->user_sids[i]);
2864 /* SID list byte count */
2865 SIVAL(pdata, 32, sid_bytes);
2867 /* 4 bytes pad/reserved - must be zero */
2868 SIVAL(pdata, 36, 0);
2872 for (i = 0; i < current_user.ut.ngroups; ++i) {
2873 SBIG_UINT(pdata, data_len,
2874 (SMB_BIG_UINT)current_user.ut.groups[i]);
2880 i < current_user.nt_user_token->num_sids; ++i) {
2882 sid_size(¤t_user.nt_user_token->user_sids[i]);
2884 sid_linearize(pdata + data_len, sid_len,
2885 ¤t_user.nt_user_token->user_sids[i]);
2886 data_len += sid_len;
2892 case SMB_MAC_QUERY_FS_INFO:
2894 * Thursby MAC extension... ONLY on NTFS filesystems
2895 * once we do streams then we don't need this
2897 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2899 SIVAL(pdata,84,0x100); /* Don't support mac... */
2904 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2909 send_trans2_replies(req, params, 0, pdata, data_len,
2912 DEBUG( 4, ( "%s info_level = %d\n",
2913 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2918 /****************************************************************************
2919 Reply to a TRANS2_SETFSINFO (set filesystem info).
2920 ****************************************************************************/
2922 static void call_trans2setfsinfo(connection_struct *conn,
2923 struct smb_request *req,
2924 char **pparams, int total_params,
2925 char **ppdata, int total_data,
2926 unsigned int max_data_bytes)
2928 char *pdata = *ppdata;
2929 char *params = *pparams;
2932 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2935 if (total_params < 4) {
2936 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2938 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2942 info_level = SVAL(params,2);
2944 switch(info_level) {
2945 case SMB_SET_CIFS_UNIX_INFO:
2947 uint16 client_unix_major;
2948 uint16 client_unix_minor;
2949 uint32 client_unix_cap_low;
2950 uint32 client_unix_cap_high;
2952 if (!lp_unix_extensions()) {
2954 NT_STATUS_INVALID_LEVEL);
2958 /* There should be 12 bytes of capabilities set. */
2959 if (total_data < 8) {
2962 NT_STATUS_INVALID_PARAMETER);
2965 client_unix_major = SVAL(pdata,0);
2966 client_unix_minor = SVAL(pdata,2);
2967 client_unix_cap_low = IVAL(pdata,4);
2968 client_unix_cap_high = IVAL(pdata,8);
2969 /* Just print these values for now. */
2970 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2971 cap_low = 0x%x, cap_high = 0x%x\n",
2972 (unsigned int)client_unix_major,
2973 (unsigned int)client_unix_minor,
2974 (unsigned int)client_unix_cap_low,
2975 (unsigned int)client_unix_cap_high ));
2977 /* Here is where we must switch to posix pathname processing... */
2978 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2979 lp_set_posix_pathnames();
2980 mangle_change_to_posix();
2983 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2984 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2985 /* Client that knows how to do posix locks,
2986 * but not posix open/mkdir operations. Set a
2987 * default type for read/write checks. */
2989 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2994 case SMB_FS_QUOTA_INFORMATION:
2996 files_struct *fsp = NULL;
2997 SMB_NTQUOTA_STRUCT quotas;
2999 ZERO_STRUCT(quotas);
3002 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3003 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3004 lp_servicename(SNUM(conn)),conn->user));
3005 reply_doserror(req, ERRSRV, ERRaccess);
3009 /* note: normaly there're 48 bytes,
3010 * but we didn't use the last 6 bytes for now
3013 fsp = file_fsp(SVAL(params,0));
3014 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3015 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3017 req, NT_STATUS_INVALID_HANDLE);
3021 if (total_data < 42) {
3022 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3026 NT_STATUS_INVALID_PARAMETER);
3030 /* unknown_1 24 NULL bytes in pdata*/
3032 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3033 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3034 #ifdef LARGE_SMB_OFF_T
3035 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3036 #else /* LARGE_SMB_OFF_T */
3037 if ((IVAL(pdata,28) != 0)&&
3038 ((quotas.softlim != 0xFFFFFFFF)||
3039 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3040 /* more than 32 bits? */
3043 NT_STATUS_INVALID_PARAMETER);
3046 #endif /* LARGE_SMB_OFF_T */
3048 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3049 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3050 #ifdef LARGE_SMB_OFF_T
3051 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3052 #else /* LARGE_SMB_OFF_T */
3053 if ((IVAL(pdata,36) != 0)&&
3054 ((quotas.hardlim != 0xFFFFFFFF)||
3055 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3056 /* more than 32 bits? */
3059 NT_STATUS_INVALID_PARAMETER);
3062 #endif /* LARGE_SMB_OFF_T */
3064 /* quota_flags 2 bytes **/
3065 quotas.qflags = SVAL(pdata,40);
3067 /* unknown_2 6 NULL bytes follow*/
3069 /* now set the quotas */
3070 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3071 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3072 reply_doserror(req, ERRSRV, ERRerror);
3079 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3081 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3087 * sending this reply works fine,
3088 * but I'm not sure it's the same
3089 * like windows do...
3092 reply_outbuf(req, 10, 0);
3095 #if defined(HAVE_POSIX_ACLS)
3096 /****************************************************************************
3097 Utility function to count the number of entries in a POSIX acl.
3098 ****************************************************************************/
3100 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3102 unsigned int ace_count = 0;
3103 int entry_id = SMB_ACL_FIRST_ENTRY;
3104 SMB_ACL_ENTRY_T entry;
3106 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3108 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3109 entry_id = SMB_ACL_NEXT_ENTRY;
3116 /****************************************************************************
3117 Utility function to marshall a POSIX acl into wire format.
3118 ****************************************************************************/
3120 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3122 int entry_id = SMB_ACL_FIRST_ENTRY;
3123 SMB_ACL_ENTRY_T entry;
3125 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3126 SMB_ACL_TAG_T tagtype;
3127 SMB_ACL_PERMSET_T permset;
3128 unsigned char perms = 0;
3129 unsigned int own_grp;
3132 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3133 entry_id = SMB_ACL_NEXT_ENTRY;
3136 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3137 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3141 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3142 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3146 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3147 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3148 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3150 SCVAL(pdata,1,perms);
3153 case SMB_ACL_USER_OBJ:
3154 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3155 own_grp = (unsigned int)pst->st_uid;
3156 SIVAL(pdata,2,own_grp);
3161 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3163 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3166 own_grp = (unsigned int)*puid;
3167 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3168 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3169 SIVAL(pdata,2,own_grp);
3173 case SMB_ACL_GROUP_OBJ:
3174 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3175 own_grp = (unsigned int)pst->st_gid;
3176 SIVAL(pdata,2,own_grp);
3181 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3183 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3186 own_grp = (unsigned int)*pgid;
3187 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3188 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3189 SIVAL(pdata,2,own_grp);
3194 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3195 SIVAL(pdata,2,0xFFFFFFFF);
3196 SIVAL(pdata,6,0xFFFFFFFF);
3199 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3200 SIVAL(pdata,2,0xFFFFFFFF);
3201 SIVAL(pdata,6,0xFFFFFFFF);
3204 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3207 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3214 /****************************************************************************
3215 Store the FILE_UNIX_BASIC info.
3216 ****************************************************************************/
3218 static char *store_file_unix_basic(connection_struct *conn,
3221 const SMB_STRUCT_STAT *psbuf)
3223 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3224 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3226 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3229 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3232 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3233 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3234 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3237 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3241 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3245 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3248 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3252 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3256 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3259 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3263 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3270 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3271 * the chflags(2) (or equivalent) flags.
3273 * XXX: this really should be behind the VFS interface. To do this, we would
3274 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3275 * Each VFS module could then implement it's own mapping as appropriate for the
3276 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3278 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3282 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3286 { UF_IMMUTABLE, EXT_IMMUTABLE },
3290 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3294 { UF_HIDDEN, EXT_HIDDEN },
3297 /* Do not remove. We need to guarantee that this array has at least one
3298 * entry to build on HP-UX.
3304 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3305 uint32 *smb_fflags, uint32 *smb_fmask)
3307 #ifdef HAVE_STAT_ST_FLAGS
3310 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3311 *smb_fmask |= info2_flags_map[i].smb_fflag;
3312 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3313 *smb_fflags |= info2_flags_map[i].smb_fflag;
3316 #endif /* HAVE_STAT_ST_FLAGS */
3319 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3320 const uint32 smb_fflags,
3321 const uint32 smb_fmask,
3324 #ifdef HAVE_STAT_ST_FLAGS
3325 uint32 max_fmask = 0;
3328 *stat_fflags = psbuf->st_flags;
3330 /* For each flags requested in smb_fmask, check the state of the
3331 * corresponding flag in smb_fflags and set or clear the matching
3335 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3336 max_fmask |= info2_flags_map[i].smb_fflag;
3337 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3338 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3339 *stat_fflags |= info2_flags_map[i].stat_fflag;
3341 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3346 /* If smb_fmask is asking to set any bits that are not supported by
3347 * our flag mappings, we should fail.
3349 if ((smb_fmask & max_fmask) != smb_fmask) {
3356 #endif /* HAVE_STAT_ST_FLAGS */
3360 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3361 * of file flags and birth (create) time.
3363 static char *store_file_unix_basic_info2(connection_struct *conn,
3366 const SMB_STRUCT_STAT *psbuf)
3368 uint32 file_flags = 0;
3369 uint32 flags_mask = 0;
3371 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3373 /* Create (birth) time 64 bit */
3374 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3377 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3378 SIVAL(pdata, 0, file_flags); /* flags */
3379 SIVAL(pdata, 4, flags_mask); /* mask */
3385 /****************************************************************************
3386 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3387 ****************************************************************************/
3389 static void call_trans2qpipeinfo(connection_struct *conn,
3390 struct smb_request *req,
3391 unsigned int tran_call,
3392 char **pparams, int total_params,
3393 char **ppdata, int total_data,
3394 unsigned int max_data_bytes)
3396 char *params = *pparams;
3397 char *pdata = *ppdata;
3398 unsigned int data_size = 0;
3399 unsigned int param_size = 2;
3401 smb_np_struct *p_pipe = NULL;
3404 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3408 if (total_params < 4) {
3409 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3413 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3414 if (p_pipe == NULL) {
3415 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3419 info_level = SVAL(params,2);
3421 *pparams = (char *)SMB_REALLOC(*pparams,2);
3422 if (*pparams == NULL) {
3423 reply_nterror(req, NT_STATUS_NO_MEMORY);
3428 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3429 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3430 if (*ppdata == NULL ) {
3431 reply_nterror(req, NT_STATUS_NO_MEMORY);
3436 switch (info_level) {
3437 case SMB_FILE_STANDARD_INFORMATION:
3439 SOFF_T(pdata,0,4096LL);
3446 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3450 send_trans2_replies(req, params, param_size, *ppdata, data_size,
3456 /****************************************************************************
3457 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3458 file name or file id).
3459 ****************************************************************************/
3461 static void call_trans2qfilepathinfo(connection_struct *conn,
3462 struct smb_request *req,
3463 unsigned int tran_call,
3464 char **pparams, int total_params,
3465 char **ppdata, int total_data,
3466 unsigned int max_data_bytes)
3468 char *params = *pparams;
3469 char *pdata = *ppdata;
3470 char *dstart, *dend;
3474 SMB_OFF_T file_size=0;
3475 SMB_BIG_UINT allocation_size=0;
3476 unsigned int data_size = 0;
3477 unsigned int param_size = 2;
3478 SMB_STRUCT_STAT sbuf;
3479 char *dos_fname = NULL;
3485 bool delete_pending = False;
3487 time_t create_time, mtime, atime;
3488 struct timespec create_time_ts, mtime_ts, atime_ts;
3489 files_struct *fsp = NULL;
3490 struct file_id fileid;
3491 struct ea_list *ea_list = NULL;
3492 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3493 char *lock_data = NULL;
3494 TALLOC_CTX *ctx = talloc_tos();
3497 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3503 if (tran_call == TRANSACT2_QFILEINFO) {
3504 if (total_params < 4) {
3505 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3510 call_trans2qpipeinfo(conn, req, tran_call,
3511 pparams, total_params,
3517 fsp = file_fsp(SVAL(params,0));
3518 info_level = SVAL(params,2);
3520 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3522 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3523 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3527 /* Initial check for valid fsp ptr. */
3528 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
3532 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3534 reply_nterror(req, NT_STATUS_NO_MEMORY);
3538 if(fsp->fake_file_handle) {
3540 * This is actually for the QUOTA_FAKE_FILE --metze
3543 /* We know this name is ok, it's already passed the checks. */
3545 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3547 * This is actually a QFILEINFO on a directory
3548 * handle (returned from an NT SMB). NT5.0 seems
3549 * to do this call. JRA.
3552 if (INFO_LEVEL_IS_UNIX(info_level)) {
3553 /* Always do lstat for UNIX calls. */
3554 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3555 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3556 reply_unixerror(req,ERRDOS,ERRbadpath);
3559 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3560 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3561 reply_unixerror(req, ERRDOS, ERRbadpath);
3565 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3566 delete_pending = get_delete_on_close_flag(fileid);
3569 * Original code - this is an open file.
3571 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3575 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3576 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3577 reply_unixerror(req, ERRDOS, ERRbadfid);
3580 pos = fsp->fh->position_information;
3581 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3582 delete_pending = get_delete_on_close_flag(fileid);
3583 access_mask = fsp->access_mask;
3587 NTSTATUS status = NT_STATUS_OK;
3590 if (total_params < 7) {
3591 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3595 info_level = SVAL(params,0);
3597 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3599 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3600 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3604 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3606 STR_TERMINATE, &status);
3607 if (!NT_STATUS_IS_OK(status)) {
3608 reply_nterror(req, status);
3612 status = resolve_dfspath(ctx,
3614 req->flags2 & FLAGS2_DFS_PATHNAMES,
3617 if (!NT_STATUS_IS_OK(status)) {
3618 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3619 reply_botherror(req,
3620 NT_STATUS_PATH_NOT_COVERED,
3621 ERRSRV, ERRbadpath);
3623 reply_nterror(req, status);
3627 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3628 if (!NT_STATUS_IS_OK(status)) {
3629 reply_nterror(req, status);
3632 status = check_name(conn, fname);
3633 if (!NT_STATUS_IS_OK(status)) {
3634 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3635 reply_nterror(req, status);
3639 if (INFO_LEVEL_IS_UNIX(info_level)) {
3640 /* Always do lstat for UNIX calls. */
3641 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3642 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3643 reply_unixerror(req, ERRDOS, ERRbadpath);
3646 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3647 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3648 reply_unixerror(req, ERRDOS, ERRbadpath);
3652 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3653 delete_pending = get_delete_on_close_flag(fileid);
3654 if (delete_pending) {
3655 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3660 nlink = sbuf.st_nlink;
3662 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3663 /* NTFS does not seem to count ".." */
3667 if ((nlink > 0) && delete_pending) {
3671 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3672 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3676 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3677 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3679 p = strrchr_m(fname,'/');
3685 mode = dos_mode(conn,fname,&sbuf);
3687 mode = FILE_ATTRIBUTE_NORMAL;
3689 fullpathname = fname;
3691 file_size = get_file_size(sbuf);
3693 /* Pull out any data sent here before we realloc. */
3694 switch (info_level) {
3695 case SMB_INFO_QUERY_EAS_FROM_LIST:
3697 /* Pull any EA list from the data portion. */
3700 if (total_data < 4) {
3702 req, NT_STATUS_INVALID_PARAMETER);
3705 ea_size = IVAL(pdata,0);
3707 if (total_data > 0 && ea_size != total_data) {
3708 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3709 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3711 req, NT_STATUS_INVALID_PARAMETER);
3715 if (!lp_ea_support(SNUM(conn))) {
3716 reply_doserror(req, ERRDOS,
3717 ERReasnotsupported);
3721 /* Pull out the list of names. */
3722 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3725 req, NT_STATUS_INVALID_PARAMETER);
3731 case SMB_QUERY_POSIX_LOCK:
3733 if (fsp == NULL || fsp->fh->fd == -1) {
3734 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3738 if (total_data != POSIX_LOCK_DATA_SIZE) {
3740 req, NT_STATUS_INVALID_PARAMETER);
3744 /* Copy the lock range data. */
3745 lock_data = (char *)TALLOC_MEMDUP(
3746 ctx, pdata, total_data);
3748 reply_nterror(req, NT_STATUS_NO_MEMORY);
3756 *pparams = (char *)SMB_REALLOC(*pparams,2);
3757 if (*pparams == NULL) {
3758 reply_nterror(req, NT_STATUS_NO_MEMORY);
3763 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3764 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3765 if (*ppdata == NULL ) {
3766 reply_nterror(req, NT_STATUS_NO_MEMORY);
3771 dend = dstart + data_size - 1;
3773 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3774 mtime_ts = get_mtimespec(&sbuf);
3775 atime_ts = get_atimespec(&sbuf);
3777 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3780 if (!null_timespec(fsp->pending_modtime)) {
3781 /* the pending modtime overrides the current modtime */
3782 mtime_ts = fsp->pending_modtime;
3786 /* Do we have this path open ? */
3787 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3788 fsp1 = file_find_di_first(fileid);
3789 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3790 /* the pending modtime overrides the current modtime */
3791 mtime_ts = fsp1->pending_modtime;
3793 if (fsp1 && fsp1->initial_allocation_size) {
3794 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3798 if (lp_dos_filetime_resolution(SNUM(conn))) {
3799 dos_filetime_timespec(&create_time_ts);
3800 dos_filetime_timespec(&mtime_ts);
3801 dos_filetime_timespec(&atime_ts);
3804 create_time = convert_timespec_to_time_t(create_time_ts);
3805 mtime = convert_timespec_to_time_t(mtime_ts);
3806 atime = convert_timespec_to_time_t(atime_ts);
3808 /* NT expects the name to be in an exact form of the *full*
3809 filename. See the trans2 torture test */
3810 if (ISDOT(base_name)) {
3811 dos_fname = talloc_strdup(ctx, "\\");
3813 reply_nterror(req, NT_STATUS_NO_MEMORY);
3817 dos_fname = talloc_asprintf(ctx,
3821 reply_nterror(req, NT_STATUS_NO_MEMORY);
3824 string_replace(dos_fname, '/', '\\');
3827 switch (info_level) {
3828 case SMB_INFO_STANDARD:
3829 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3831 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3832 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3833 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3834 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3835 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3836 SSVAL(pdata,l1_attrFile,mode);
3839 case SMB_INFO_QUERY_EA_SIZE:
3841 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3842 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3844 srv_put_dos_date2(pdata,0,create_time);
3845 srv_put_dos_date2(pdata,4,atime);
3846 srv_put_dos_date2(pdata,8,mtime); /* write time */
3847 SIVAL(pdata,12,(uint32)file_size);
3848 SIVAL(pdata,16,(uint32)allocation_size);
3849 SSVAL(pdata,20,mode);
3850 SIVAL(pdata,22,ea_size);
3854 case SMB_INFO_IS_NAME_VALID:
3855 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3856 if (tran_call == TRANSACT2_QFILEINFO) {
3857 /* os/2 needs this ? really ?*/
3858 reply_doserror(req, ERRDOS, ERRbadfunc);
3865 case SMB_INFO_QUERY_EAS_FROM_LIST:
3867 size_t total_ea_len = 0;
3868 struct ea_list *ea_file_list = NULL;
3870 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3872 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3873 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3875 if (!ea_list || (total_ea_len > data_size)) {
3877 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3881 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3885 case SMB_INFO_QUERY_ALL_EAS:
3887 /* We have data_size bytes to put EA's into. */
3888 size_t total_ea_len = 0;
3890 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3892 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3893 if (!ea_list || (total_ea_len > data_size)) {
3895 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3899 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3903 case SMB_FILE_BASIC_INFORMATION:
3904 case SMB_QUERY_FILE_BASIC_INFO:
3906 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3907 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3908 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3910 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3914 put_long_date_timespec(pdata,create_time_ts);
3915 put_long_date_timespec(pdata+8,atime_ts);
3916 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3917 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3918 SIVAL(pdata,32,mode);
3920 DEBUG(5,("SMB_QFBI - "));
3921 DEBUG(5,("create: %s ", ctime(&create_time)));
3922 DEBUG(5,("access: %s ", ctime(&atime)));
3923 DEBUG(5,("write: %s ", ctime(&mtime)));
3924 DEBUG(5,("change: %s ", ctime(&mtime)));
3925 DEBUG(5,("mode: %x\n", mode));
3928 case SMB_FILE_STANDARD_INFORMATION:
3929 case SMB_QUERY_FILE_STANDARD_INFO:
3931 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3933 SOFF_T(pdata,0,allocation_size);
3934 SOFF_T(pdata,8,file_size);
3935 SIVAL(pdata,16,nlink);
3936 SCVAL(pdata,20,delete_pending?1:0);
3937 SCVAL(pdata,21,(mode&aDIR)?1:0);
3938 SSVAL(pdata,22,0); /* Padding. */
3941 case SMB_FILE_EA_INFORMATION:
3942 case SMB_QUERY_FILE_EA_INFO:
3944 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3945 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3947 SIVAL(pdata,0,ea_size);
3951 /* Get the 8.3 name - used if NT SMB was negotiated. */
3952 case SMB_QUERY_FILE_ALT_NAME_INFO:
3953 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3955 char mangled_name[13];
3956 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3957 if (!name_to_8_3(base_name,mangled_name,
3958 True,conn->params)) {
3961 NT_STATUS_NO_MEMORY);
3963 len = srvstr_push(dstart, req->flags2,
3964 pdata+4, mangled_name,
3965 PTR_DIFF(dend, pdata+4),
3967 data_size = 4 + len;
3972 case SMB_QUERY_FILE_NAME_INFO:
3974 this must be *exactly* right for ACLs on mapped drives to work
3976 len = srvstr_push(dstart, req->flags2,
3978 PTR_DIFF(dend, pdata+4),
3980 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3981 data_size = 4 + len;
3985 case SMB_FILE_ALLOCATION_INFORMATION:
3986 case SMB_QUERY_FILE_ALLOCATION_INFO:
3987 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3989 SOFF_T(pdata,0,allocation_size);
3992 case SMB_FILE_END_OF_FILE_INFORMATION:
3993 case SMB_QUERY_FILE_END_OF_FILEINFO:
3994 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3996 SOFF_T(pdata,0,file_size);
3999 case SMB_QUERY_FILE_ALL_INFO:
4000 case SMB_FILE_ALL_INFORMATION:
4002 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4003 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4004 put_long_date_timespec(pdata,create_time_ts);
4005 put_long_date_timespec(pdata+8,atime_ts);
4006 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4007 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4008 SIVAL(pdata,32,mode);
4009 SIVAL(pdata,36,0); /* padding. */
4011 SOFF_T(pdata,0,allocation_size);
4012 SOFF_T(pdata,8,file_size);
4013 SIVAL(pdata,16,nlink);
4014 SCVAL(pdata,20,delete_pending);
4015 SCVAL(pdata,21,(mode&aDIR)?1:0);
4018 SIVAL(pdata,0,ea_size);
4019 pdata += 4; /* EA info */
4020 len = srvstr_push(dstart, req->flags2,
4022 PTR_DIFF(dend, pdata+4),
4026 data_size = PTR_DIFF(pdata,(*ppdata));
4029 case SMB_FILE_INTERNAL_INFORMATION:
4030 /* This should be an index number - looks like
4033 I think this causes us to fail the IFSKIT
4034 BasicFileInformationTest. -tpot */
4036 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4037 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4038 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4042 case SMB_FILE_ACCESS_INFORMATION:
4043 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4044 SIVAL(pdata,0,access_mask);
4048 case SMB_FILE_NAME_INFORMATION:
4049 /* Pathname with leading '\'. */
4052 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4053 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4054 SIVAL(pdata,0,byte_len);
4055 data_size = 4 + byte_len;
4059 case SMB_FILE_DISPOSITION_INFORMATION:
4060 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4062 SCVAL(pdata,0,delete_pending);
4065 case SMB_FILE_POSITION_INFORMATION:
4066 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4068 SOFF_T(pdata,0,pos);
4071 case SMB_FILE_MODE_INFORMATION:
4072 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4073 SIVAL(pdata,0,mode);
4077 case SMB_FILE_ALIGNMENT_INFORMATION:
4078 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4079 SIVAL(pdata,0,0); /* No alignment needed. */
4085 * NT4 server just returns "invalid query" to this - if we try to answer
4086 * it then NTws gets a BSOD! (tridge).
4087 * W2K seems to want this. JRA.
4089 case SMB_QUERY_FILE_STREAM_INFO:
4091 case SMB_FILE_STREAM_INFORMATION:
4092 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4096 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4097 SIVAL(pdata,0,0); /* ??? */
4098 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4099 SOFF_T(pdata,8,file_size);
4100 SOFF_T(pdata,16,allocation_size);
4101 data_size = 24 + byte_len;
4105 case SMB_QUERY_COMPRESSION_INFO:
4106 case SMB_FILE_COMPRESSION_INFORMATION:
4107 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4108 SOFF_T(pdata,0,file_size);
4109 SIVAL(pdata,8,0); /* ??? */
4110 SIVAL(pdata,12,0); /* ??? */
4114 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4115 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4116 put_long_date_timespec(pdata,create_time_ts);
4117 put_long_date_timespec(pdata+8,atime_ts);
4118 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4119 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4120 SOFF_T(pdata,32,allocation_size);
4121 SOFF_T(pdata,40,file_size);
4122 SIVAL(pdata,48,mode);
4123 SIVAL(pdata,52,0); /* ??? */
4127 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4128 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4129 SIVAL(pdata,0,mode);
4135 * CIFS UNIX Extensions.
4138 case SMB_QUERY_FILE_UNIX_BASIC:
4140 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4141 data_size = PTR_DIFF(pdata,(*ppdata));
4145 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4147 for (i=0; i<100; i++)
4148 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4154 case SMB_QUERY_FILE_UNIX_INFO2:
4156 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4157 data_size = PTR_DIFF(pdata,(*ppdata));
4161 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4163 for (i=0; i<100; i++)
4164 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4170 case SMB_QUERY_FILE_UNIX_LINK:
4172 char *buffer = TALLOC_ARRAY(ctx, char, 1024);
4175 reply_nterror(req, NT_STATUS_NO_MEMORY);
4179 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4181 if(!S_ISLNK(sbuf.st_mode)) {
4182 reply_unixerror(req, ERRSRV,
4187 reply_unixerror(req, ERRDOS, ERRbadlink);
4190 len = SMB_VFS_READLINK(conn,fullpathname,
4193 reply_unixerror(req, ERRDOS,
4198 len = srvstr_push(dstart, req->flags2,
4200 PTR_DIFF(dend, pdata),
4203 data_size = PTR_DIFF(pdata,(*ppdata));
4208 #if defined(HAVE_POSIX_ACLS)
4209 case SMB_QUERY_POSIX_ACL:
4211 SMB_ACL_T file_acl = NULL;
4212 SMB_ACL_T def_acl = NULL;
4213 uint16 num_file_acls = 0;
4214 uint16 num_def_acls = 0;
4216 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4217 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4219 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4222 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4223 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4227 NT_STATUS_NOT_IMPLEMENTED);
4231 if (S_ISDIR(sbuf.st_mode)) {
4232 if (fsp && fsp->is_directory) {
4233 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4235 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4237 def_acl = free_empty_sys_acl(conn, def_acl);
4240 num_file_acls = count_acl_entries(conn, file_acl);
4241 num_def_acls = count_acl_entries(conn, def_acl);
4243 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4244 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4246 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4247 SMB_POSIX_ACL_HEADER_SIZE) ));
4249 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4252 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4256 NT_STATUS_BUFFER_TOO_SMALL);
4260 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4261 SSVAL(pdata,2,num_file_acls);
4262 SSVAL(pdata,4,num_def_acls);
4263 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4265 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4268 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4271 req, NT_STATUS_INTERNAL_ERROR);
4274 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4276 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4279 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4283 NT_STATUS_INTERNAL_ERROR);
4288 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4291 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4293 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4299 case SMB_QUERY_POSIX_LOCK:
4301 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4303 SMB_BIG_UINT offset;
4305 enum brl_type lock_type;
4307 if (total_data != POSIX_LOCK_DATA_SIZE) {
4309 req, NT_STATUS_INVALID_PARAMETER);
4313 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4314 case POSIX_LOCK_TYPE_READ:
4315 lock_type = READ_LOCK;
4317 case POSIX_LOCK_TYPE_WRITE:
4318 lock_type = WRITE_LOCK;
4320 case POSIX_LOCK_TYPE_UNLOCK:
4322 /* There's no point in asking for an unlock... */
4325 NT_STATUS_INVALID_PARAMETER);
4329 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4330 #if defined(HAVE_LONGLONG)
4331 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4332 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4333 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4334 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4335 #else /* HAVE_LONGLONG */
4336 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4337 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4338 #endif /* HAVE_LONGLONG */
4340 status = query_lock(fsp,
4347 if (ERROR_WAS_LOCK_DENIED(status)) {
4348 /* Here we need to report who has it locked... */
4349 data_size = POSIX_LOCK_DATA_SIZE;
4351 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4352 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4353 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4354 #if defined(HAVE_LONGLONG)
4355 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4356 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4357 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4358 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4359 #else /* HAVE_LONGLONG */
4360 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4361 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4362 #endif /* HAVE_LONGLONG */
4364 } else if (NT_STATUS_IS_OK(status)) {
4365 /* For success we just return a copy of what we sent
4366 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4367 data_size = POSIX_LOCK_DATA_SIZE;
4368 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4369 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4371 reply_nterror(req, status);
4378 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4382 send_trans2_replies(req, params, param_size, *ppdata, data_size,
4388 /****************************************************************************
4389 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4391 ****************************************************************************/
4393 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4394 connection_struct *conn,
4395 const char *oldname_in,
4396 const char *newname_in)
4398 SMB_STRUCT_STAT sbuf1, sbuf2;
4399 char *last_component_oldname = NULL;
4400 char *last_component_newname = NULL;
4401 char *oldname = NULL;
4402 char *newname = NULL;
4403 NTSTATUS status = NT_STATUS_OK;
4408 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4409 &last_component_oldname, &sbuf1);
4410 if (!NT_STATUS_IS_OK(status)) {
4414 status = check_name(conn, oldname);
4415 if (!NT_STATUS_IS_OK(status)) {
4419 /* source must already exist. */
4420 if (!VALID_STAT(sbuf1)) {
4421 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4424 status = unix_convert(ctx, conn, newname_in, False, &newname,
4425 &last_component_newname, &sbuf2);
4426 if (!NT_STATUS_IS_OK(status)) {
4430 status = check_name(conn, newname);
4431 if (!NT_STATUS_IS_OK(status)) {
4435 /* Disallow if newname already exists. */
4436 if (VALID_STAT(sbuf2)) {
4437 return NT_STATUS_OBJECT_NAME_COLLISION;
4440 /* No links from a directory. */
4441 if (S_ISDIR(sbuf1.st_mode)) {
4442 return NT_STATUS_FILE_IS_A_DIRECTORY;
4445 /* Ensure this is within the share. */
4446 status = check_reduced_name(conn, oldname);
4447 if (!NT_STATUS_IS_OK(status)) {
4451 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4453 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4454 status = map_nt_error_from_unix(errno);
4455 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4456 nt_errstr(status), newname, oldname));
4462 /****************************************************************************
4463 Deal with setting the time from any of the setfilepathinfo functions.
4464 ****************************************************************************/
4466 static NTSTATUS smb_set_file_time(connection_struct *conn,
4469 const SMB_STRUCT_STAT *psbuf,
4470 struct timespec ts[2],
4471 bool setting_write_time)
4474 FILE_NOTIFY_CHANGE_LAST_ACCESS
4475 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4477 if (!VALID_STAT(*psbuf)) {
4478 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4481 /* get some defaults (no modifications) if any info is zero or -1. */
4482 if (null_timespec(ts[0])) {
4483 ts[0] = get_atimespec(psbuf);
4484 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4487 if (null_timespec(ts[1])) {
4488 ts[1] = get_mtimespec(psbuf);
4489 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4492 if (!setting_write_time) {
4493 /* ts[1] comes from change time, not write time. */
4494 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4497 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4498 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4501 * Try and set the times of this file if
4502 * they are different from the current values.
4506 struct timespec mts = get_mtimespec(psbuf);
4507 struct timespec ats = get_atimespec(psbuf);
4508 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4509 return NT_STATUS_OK;
4515 * This was a setfileinfo on an open file.
4516 * NT does this a lot. We also need to
4517 * set the time here, as it can be read by
4518 * FindFirst/FindNext and with the patch for bug #2045
4519 * in smbd/fileio.c it ensures that this timestamp is
4520 * kept sticky even after a write. We save the request
4521 * away and will set it on file close and after a write. JRA.
4524 if (!null_timespec(ts[1])) {
4525 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4526 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4527 fsp_set_pending_modtime(fsp, ts[1]);
4531 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4533 if(file_ntimes(conn, fname, ts)!=0) {
4534 return map_nt_error_from_unix(errno);
4536 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4538 return NT_STATUS_OK;
4541 /****************************************************************************
4542 Deal with setting the dosmode from any of the setfilepathinfo functions.
4543 ****************************************************************************/
4545 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4547 SMB_STRUCT_STAT *psbuf,
4550 if (!VALID_STAT(*psbuf)) {
4551 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4555 if (S_ISDIR(psbuf->st_mode)) {
4562 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4564 /* check the mode isn't different, before changing it */
4565 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4567 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4568 fname, (unsigned int)dosmode ));
4570 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4571 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4572 fname, strerror(errno)));
4573 return map_nt_error_from_unix(errno);
4576 return NT_STATUS_OK;
4579 /****************************************************************************
4580 Deal with setting the size from any of the setfilepathinfo functions.
4581 ****************************************************************************/
4583 static NTSTATUS smb_set_file_size(connection_struct *conn,
4584 struct smb_request *req,
4587 SMB_STRUCT_STAT *psbuf,
4590 NTSTATUS status = NT_STATUS_OK;
4591 files_struct *new_fsp = NULL;
4593 if (!VALID_STAT(*psbuf)) {
4594 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4597 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4599 if (size == get_file_size(*psbuf)) {
4600 return NT_STATUS_OK;
4603 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4604 fname, (double)size ));
4606 if (fsp && fsp->fh->fd != -1) {
4607 /* Handle based call. */
4608 if (vfs_set_filelen(fsp, size) == -1) {
4609 return map_nt_error_from_unix(errno);
4611 return NT_STATUS_OK;
4614 status = open_file_ntcreate(conn, req, fname, psbuf,
4616 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4619 FILE_ATTRIBUTE_NORMAL,
4620 FORCE_OPLOCK_BREAK_TO_NONE,
4623 if (!NT_STATUS_IS_OK(status)) {
4624 /* NB. We check for open_was_deferred in the caller. */
4628 if (vfs_set_filelen(new_fsp, size) == -1) {
4629 status = map_nt_error_from_unix(errno);
4630 close_file(new_fsp,NORMAL_CLOSE);
4634 close_file(new_fsp,NORMAL_CLOSE);
4635 return NT_STATUS_OK;
4638 /****************************************************************************
4639 Deal with SMB_INFO_SET_EA.
4640 ****************************************************************************/
4642 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4648 struct ea_list *ea_list = NULL;
4649 TALLOC_CTX *ctx = NULL;
4650 NTSTATUS status = NT_STATUS_OK;
4652 if (total_data < 10) {
4654 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4655 length. They seem to have no effect. Bug #3212. JRA */
4657 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4658 /* We're done. We only get EA info in this call. */
4659 return NT_STATUS_OK;
4662 return NT_STATUS_INVALID_PARAMETER;
4665 if (IVAL(pdata,0) > total_data) {
4666 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4667 IVAL(pdata,0), (unsigned int)total_data));
4668 return NT_STATUS_INVALID_PARAMETER;
4671 ctx = talloc_init("SMB_INFO_SET_EA");
4673 return NT_STATUS_NO_MEMORY;
4675 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4677 talloc_destroy(ctx);
4678 return NT_STATUS_INVALID_PARAMETER;
4680 status = set_ea(conn, fsp, fname, ea_list);
4681 talloc_destroy(ctx);
4686 /****************************************************************************
4687 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4688 ****************************************************************************/
4690 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4695 SMB_STRUCT_STAT *psbuf)
4697 NTSTATUS status = NT_STATUS_OK;
4698 bool delete_on_close;
4701 if (total_data < 1) {
4702 return NT_STATUS_INVALID_PARAMETER;
4706 return NT_STATUS_INVALID_HANDLE;
4709 delete_on_close = (CVAL(pdata,0) ? True : False);
4710 dosmode = dos_mode(conn, fname, psbuf);
4712 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4713 "delete_on_close = %u\n",
4715 (unsigned int)dosmode,
4716 (unsigned int)delete_on_close ));
4718 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4720 if (!NT_STATUS_IS_OK(status)) {
4724 /* The set is across all open files on this dev/inode pair. */
4725 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4726 return NT_STATUS_ACCESS_DENIED;
4728 return NT_STATUS_OK;
4731 /****************************************************************************
4732 Deal with SMB_FILE_POSITION_INFORMATION.
4733 ****************************************************************************/
4735 static NTSTATUS smb_file_position_information(connection_struct *conn,
4740 SMB_BIG_UINT position_information;
4742 if (total_data < 8) {
4743 return NT_STATUS_INVALID_PARAMETER;
4747 /* Ignore on pathname based set. */
4748 return NT_STATUS_OK;
4751 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4752 #ifdef LARGE_SMB_OFF_T
4753 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4754 #else /* LARGE_SMB_OFF_T */
4755 if (IVAL(pdata,4) != 0) {
4756 /* more than 32 bits? */
4757 return NT_STATUS_INVALID_PARAMETER;
4759 #endif /* LARGE_SMB_OFF_T */
4761 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4762 fsp->fsp_name, (double)position_information ));
4763 fsp->fh->position_information = position_information;
4764 return NT_STATUS_OK;
4767 /****************************************************************************
4768 Deal with SMB_FILE_MODE_INFORMATION.
4769 ****************************************************************************/
4771 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4777 if (total_data < 4) {
4778 return NT_STATUS_INVALID_PARAMETER;
4780 mode = IVAL(pdata,0);
4781 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4782 return NT_STATUS_INVALID_PARAMETER;
4784 return NT_STATUS_OK;
4787 /****************************************************************************
4788 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4789 ****************************************************************************/
4791 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4792 struct smb_request *req,
4797 char *link_target = NULL;
4798 const char *newname = fname;
4799 NTSTATUS status = NT_STATUS_OK;
4800 TALLOC_CTX *ctx = talloc_tos();
4802 /* Set a symbolic link. */
4803 /* Don't allow this if follow links is false. */
4805 if (total_data == 0) {
4806 return NT_STATUS_INVALID_PARAMETER;
4809 if (!lp_symlinks(SNUM(conn))) {
4810 return NT_STATUS_ACCESS_DENIED;
4813 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
4814 total_data, STR_TERMINATE);
4817 return NT_STATUS_INVALID_PARAMETER;
4820 /* !widelinks forces the target path to be within the share. */
4821 /* This means we can interpret the target as a pathname. */
4822 if (!lp_widelinks(SNUM(conn))) {
4823 char *rel_name = NULL;
4824 char *last_dirp = NULL;
4826 if (*link_target == '/') {
4827 /* No absolute paths allowed. */
4828 return NT_STATUS_ACCESS_DENIED;
4830 rel_name = talloc_strdup(ctx,newname);
4832 return NT_STATUS_NO_MEMORY;
4834 last_dirp = strrchr_m(rel_name, '/');
4836 last_dirp[1] = '\0';
4838 rel_name = talloc_strdup(ctx,"./");
4840 return NT_STATUS_NO_MEMORY;
4843 rel_name = talloc_asprintf_append(rel_name,
4847 return NT_STATUS_NO_MEMORY;
4850 status = check_name(conn, rel_name);
4851 if (!NT_STATUS_IS_OK(status)) {
4856 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4857 newname, link_target ));
4859 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4860 return map_nt_error_from_unix(errno);
4863 return NT_STATUS_OK;
4866 /****************************************************************************
4867 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4868 ****************************************************************************/
4870 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4871 struct smb_request *req,
4872 const char *pdata, int total_data,
4875 char *oldname = NULL;
4876 TALLOC_CTX *ctx = talloc_tos();
4877 NTSTATUS status = NT_STATUS_OK;
4879 /* Set a hard link. */
4880 if (total_data == 0) {
4881 return NT_STATUS_INVALID_PARAMETER;
4884 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
4885 total_data, STR_TERMINATE, &status);
4886 if (!NT_STATUS_IS_OK(status)) {
4890 status = resolve_dfspath(ctx, conn,
4891 req->flags2 & FLAGS2_DFS_PATHNAMES,
4894 if (!NT_STATUS_IS_OK(status)) {
4898 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4901 return hardlink_internals(ctx, conn, oldname, fname);
4904 /****************************************************************************
4905 Deal with SMB_FILE_RENAME_INFORMATION.
4906 ****************************************************************************/
4908 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4909 struct smb_request *req,
4918 char *newname = NULL;
4919 char *base_name = NULL;
4920 bool dest_has_wcard = False;
4921 NTSTATUS status = NT_STATUS_OK;
4923 TALLOC_CTX *ctx = talloc_tos();
4925 if (total_data < 13) {
4926 return NT_STATUS_INVALID_PARAMETER;
4929 overwrite = (CVAL(pdata,0) ? True : False);
4930 root_fid = IVAL(pdata,4);
4931 len = IVAL(pdata,8);
4933 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4934 return NT_STATUS_INVALID_PARAMETER;
4937 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
4940 if (!NT_STATUS_IS_OK(status)) {
4944 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4947 status = resolve_dfspath_wcard(ctx, conn,
4948 req->flags2 & FLAGS2_DFS_PATHNAMES,
4952 if (!NT_STATUS_IS_OK(status)) {
4956 /* Check the new name has no '/' characters. */
4957 if (strchr_m(newname, '/')) {
4958 return NT_STATUS_NOT_SUPPORTED;
4961 /* Create the base directory. */
4962 base_name = talloc_strdup(ctx, fname);
4964 return NT_STATUS_NO_MEMORY;
4966 p = strrchr_m(base_name, '/');
4970 base_name = talloc_strdup(ctx, "./");
4972 return NT_STATUS_NO_MEMORY;
4975 /* Append the new name. */
4976 base_name = talloc_asprintf_append(base_name,
4980 return NT_STATUS_NO_MEMORY;
4984 SMB_STRUCT_STAT sbuf;
4985 char *newname_last_component = NULL;
4989 status = unix_convert(ctx, conn, newname, False,
4991 &newname_last_component,
4994 /* If an error we expect this to be
4995 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
4997 if (!NT_STATUS_IS_OK(status)
4998 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5003 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5004 fsp->fnum, fsp->fsp_name, base_name ));
5005 status = rename_internals_fsp(conn, fsp, base_name,
5006 newname_last_component, 0,
5009 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5010 fname, base_name ));
5011 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5012 overwrite, False, dest_has_wcard);
5018 /****************************************************************************
5019 Deal with SMB_SET_POSIX_ACL.
5020 ****************************************************************************/
5022 #if defined(HAVE_POSIX_ACLS)
5023 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5028 SMB_STRUCT_STAT *psbuf)
5030 uint16 posix_acl_version;
5031 uint16 num_file_acls;
5032 uint16 num_def_acls;
5033 bool valid_file_acls = True;
5034 bool valid_def_acls = True;
5036 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5037 return NT_STATUS_INVALID_PARAMETER;
5039 posix_acl_version = SVAL(pdata,0);
5040 num_file_acls = SVAL(pdata,2);
5041 num_def_acls = SVAL(pdata,4);
5043 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5044 valid_file_acls = False;
5048 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5049 valid_def_acls = False;
5053 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5054 return NT_STATUS_INVALID_PARAMETER;
5057 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5058 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5059 return NT_STATUS_INVALID_PARAMETER;
5062 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5063 fname ? fname : fsp->fsp_name,
5064 (unsigned int)num_file_acls,
5065 (unsigned int)num_def_acls));
5067 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5068 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5069 return map_nt_error_from_unix(errno);
5072 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5073 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5074 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5075 return map_nt_error_from_unix(errno);
5077 return NT_STATUS_OK;
5081 /****************************************************************************
5082 Deal with SMB_SET_POSIX_LOCK.
5083 ****************************************************************************/
5085 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5093 SMB_BIG_UINT offset;
5095 bool blocking_lock = False;
5096 enum brl_type lock_type;
5097 NTSTATUS status = NT_STATUS_OK;
5099 if (fsp == NULL || fsp->fh->fd == -1) {
5100 return NT_STATUS_INVALID_HANDLE;
5103 if (total_data != POSIX_LOCK_DATA_SIZE) {
5104 return NT_STATUS_INVALID_PARAMETER;
5107 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5108 case POSIX_LOCK_TYPE_READ:
5109 lock_type = READ_LOCK;
5111 case POSIX_LOCK_TYPE_WRITE:
5112 /* Return the right POSIX-mappable error code for files opened read-only. */
5113 if (!fsp->can_write) {
5114 return NT_STATUS_INVALID_HANDLE;
5116 lock_type = WRITE_LOCK;
5118 case POSIX_LOCK_TYPE_UNLOCK:
5119 lock_type = UNLOCK_LOCK;
5122 return NT_STATUS_INVALID_PARAMETER;
5125 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5126 blocking_lock = False;
5127 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5128 blocking_lock = True;
5130 return NT_STATUS_INVALID_PARAMETER;
5133 if (!lp_blocking_locks(SNUM(conn))) {
5134 blocking_lock = False;
5137 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5138 #if defined(HAVE_LONGLONG)
5139 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5140 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5141 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5142 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5143 #else /* HAVE_LONGLONG */
5144 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5145 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5146 #endif /* HAVE_LONGLONG */
5148 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5149 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5151 (unsigned int)lock_type,
5152 (unsigned int)lock_pid,
5156 if (lock_type == UNLOCK_LOCK) {
5157 status = do_unlock(smbd_messaging_context(),
5164 uint32 block_smbpid;
5166 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5177 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5179 * A blocking lock was requested. Package up
5180 * this smb into a queued request and push it
5181 * onto the blocking lock queue.
5183 if(push_blocking_lock_request(br_lck,
5184 (char *)inbuf, length,
5186 -1, /* infinite timeout. */
5194 TALLOC_FREE(br_lck);
5198 TALLOC_FREE(br_lck);
5204 /****************************************************************************
5205 Deal with SMB_INFO_STANDARD.
5206 ****************************************************************************/
5208 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5213 const SMB_STRUCT_STAT *psbuf)
5215 struct timespec ts[2];
5217 if (total_data < 12) {
5218 return NT_STATUS_INVALID_PARAMETER;
5222 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5224 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5226 DEBUG(10,("smb_set_info_standard: file %s\n",
5227 fname ? fname : fsp->fsp_name ));
5229 return smb_set_file_time(conn,
5237 /****************************************************************************
5238 Deal with SMB_SET_FILE_BASIC_INFO.
5239 ****************************************************************************/
5241 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5246 SMB_STRUCT_STAT *psbuf)
5248 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5249 struct timespec write_time;
5250 struct timespec changed_time;
5252 struct timespec ts[2];
5253 NTSTATUS status = NT_STATUS_OK;
5254 bool setting_write_time = true;
5256 if (total_data < 36) {
5257 return NT_STATUS_INVALID_PARAMETER;
5260 /* Set the attributes */
5261 dosmode = IVAL(pdata,32);
5262 status = smb_set_file_dosmode(conn,
5266 if (!NT_STATUS_IS_OK(status)) {
5270 /* Ignore create time at offset pdata. */
5273 ts[0] = interpret_long_date(pdata+8);
5275 write_time = interpret_long_date(pdata+16);
5276 changed_time = interpret_long_date(pdata+24);
5279 ts[1] = timespec_min(&write_time, &changed_time);
5281 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5285 /* Prefer a defined time to an undefined one. */
5286 if (null_timespec(ts[1])) {
5287 if (null_timespec(write_time)) {
5288 ts[1] = changed_time;
5289 setting_write_time = false;
5295 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5296 fname ? fname : fsp->fsp_name ));
5298 return smb_set_file_time(conn,
5303 setting_write_time);
5306 /****************************************************************************
5307 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5308 ****************************************************************************/
5310 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5311 struct smb_request *req,
5316 SMB_STRUCT_STAT *psbuf)
5318 SMB_BIG_UINT allocation_size = 0;
5319 NTSTATUS status = NT_STATUS_OK;
5320 files_struct *new_fsp = NULL;
5322 if (!VALID_STAT(*psbuf)) {
5323 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5326 if (total_data < 8) {
5327 return NT_STATUS_INVALID_PARAMETER;
5330 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5331 #ifdef LARGE_SMB_OFF_T
5332 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5333 #else /* LARGE_SMB_OFF_T */
5334 if (IVAL(pdata,4) != 0) {
5335 /* more than 32 bits? */
5336 return NT_STATUS_INVALID_PARAMETER;
5338 #endif /* LARGE_SMB_OFF_T */
5340 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5341 fname, (double)allocation_size ));
5343 if (allocation_size) {
5344 allocation_size = smb_roundup(conn, allocation_size);
5347 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5348 fname, (double)allocation_size ));
5350 if (fsp && fsp->fh->fd != -1) {
5351 /* Open file handle. */
5352 /* Only change if needed. */
5353 if (allocation_size != get_file_size(*psbuf)) {
5354 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5355 return map_nt_error_from_unix(errno);
5358 /* But always update the time. */
5359 if (null_timespec(fsp->pending_modtime)) {
5361 * This is equivalent to a write. Ensure it's seen immediately
5362 * if there are no pending writes.
5364 set_filetime(fsp->conn, fsp->fsp_name,
5365 timespec_current());
5367 return NT_STATUS_OK;
5370 /* Pathname or stat or directory file. */
5372 status = open_file_ntcreate(conn, req, fname, psbuf,
5374 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5377 FILE_ATTRIBUTE_NORMAL,
5378 FORCE_OPLOCK_BREAK_TO_NONE,
5381 if (!NT_STATUS_IS_OK(status)) {
5382 /* NB. We check for open_was_deferred in the caller. */
5386 /* Only change if needed. */
5387 if (allocation_size != get_file_size(*psbuf)) {
5388 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5389 status = map_nt_error_from_unix(errno);
5390 close_file(new_fsp,NORMAL_CLOSE);
5395 /* Changing the allocation size should set the last mod time. */
5396 /* Don't need to call set_filetime as this will be flushed on
5399 fsp_set_pending_modtime(new_fsp, timespec_current());
5401 close_file(new_fsp,NORMAL_CLOSE);
5402 return NT_STATUS_OK;
5405 /****************************************************************************
5406 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5407 ****************************************************************************/
5409 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5410 struct smb_request *req,
5415 SMB_STRUCT_STAT *psbuf)
5419 if (total_data < 8) {
5420 return NT_STATUS_INVALID_PARAMETER;
5423 size = IVAL(pdata,0);
5424 #ifdef LARGE_SMB_OFF_T
5425 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5426 #else /* LARGE_SMB_OFF_T */
5427 if (IVAL(pdata,4) != 0) {
5428 /* more than 32 bits? */
5429 return NT_STATUS_INVALID_PARAMETER;
5431 #endif /* LARGE_SMB_OFF_T */
5432 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5433 "file %s to %.0f\n", fname, (double)size ));
5435 return smb_set_file_size(conn, req,
5442 /****************************************************************************
5443 Allow a UNIX info mknod.
5444 ****************************************************************************/
5446 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5450 SMB_STRUCT_STAT *psbuf)
5452 uint32 file_type = IVAL(pdata,56);
5453 #if defined(HAVE_MAKEDEV)
5454 uint32 dev_major = IVAL(pdata,60);
5455 uint32 dev_minor = IVAL(pdata,68);
5457 SMB_DEV_T dev = (SMB_DEV_T)0;
5458 uint32 raw_unixmode = IVAL(pdata,84);
5462 if (total_data < 100) {
5463 return NT_STATUS_INVALID_PARAMETER;
5466 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5467 if (!NT_STATUS_IS_OK(status)) {
5471 #if defined(HAVE_MAKEDEV)
5472 dev = makedev(dev_major, dev_minor);
5475 switch (file_type) {
5476 #if defined(S_IFIFO)
5477 case UNIX_TYPE_FIFO:
5478 unixmode |= S_IFIFO;
5481 #if defined(S_IFSOCK)
5482 case UNIX_TYPE_SOCKET:
5483 unixmode |= S_IFSOCK;
5486 #if defined(S_IFCHR)
5487 case UNIX_TYPE_CHARDEV:
5488 unixmode |= S_IFCHR;
5491 #if defined(S_IFBLK)
5492 case UNIX_TYPE_BLKDEV:
5493 unixmode |= S_IFBLK;
5497 return NT_STATUS_INVALID_PARAMETER;
5500 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5501 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5503 /* Ok - do the mknod. */
5504 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5505 return map_nt_error_from_unix(errno);
5508 /* If any of the other "set" calls fail we
5509 * don't want to end up with a half-constructed mknod.
5512 if (lp_inherit_perms(SNUM(conn))) {
5514 conn, parent_dirname(fname),
5518 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5519 status = map_nt_error_from_unix(errno);
5520 SMB_VFS_UNLINK(conn,fname);
5523 return NT_STATUS_OK;
5526 /****************************************************************************
5527 Deal with SMB_SET_FILE_UNIX_BASIC.
5528 ****************************************************************************/
5530 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5531 struct smb_request *req,
5536 SMB_STRUCT_STAT *psbuf)
5538 struct timespec ts[2];
5539 uint32 raw_unixmode;
5542 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5543 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5544 NTSTATUS status = NT_STATUS_OK;
5545 bool delete_on_fail = False;
5546 enum perm_type ptype;
5548 if (total_data < 100) {
5549 return NT_STATUS_INVALID_PARAMETER;
5552 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5553 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5554 size=IVAL(pdata,0); /* first 8 Bytes are size */
5555 #ifdef LARGE_SMB_OFF_T
5556 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5557 #else /* LARGE_SMB_OFF_T */
5558 if (IVAL(pdata,4) != 0) {
5559 /* more than 32 bits? */
5560 return NT_STATUS_INVALID_PARAMETER;
5562 #endif /* LARGE_SMB_OFF_T */
5565 ts[0] = interpret_long_date(pdata+24); /* access_time */
5566 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5567 set_owner = (uid_t)IVAL(pdata,40);
5568 set_grp = (gid_t)IVAL(pdata,48);
5569 raw_unixmode = IVAL(pdata,84);
5571 if (VALID_STAT(*psbuf)) {
5572 if (S_ISDIR(psbuf->st_mode)) {
5573 ptype = PERM_EXISTING_DIR;
5575 ptype = PERM_EXISTING_FILE;
5578 ptype = PERM_NEW_FILE;
5581 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5582 if (!NT_STATUS_IS_OK(status)) {
5586 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5587 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5588 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5590 if (!VALID_STAT(*psbuf)) {
5592 * The only valid use of this is to create character and block
5593 * devices, and named pipes. This is deprecated (IMHO) and
5594 * a new info level should be used for mknod. JRA.
5597 status = smb_unix_mknod(conn,
5602 if (!NT_STATUS_IS_OK(status)) {
5606 /* Ensure we don't try and change anything else. */
5607 raw_unixmode = SMB_MODE_NO_CHANGE;
5608 size = get_file_size(*psbuf);
5609 ts[0] = get_atimespec(psbuf);
5610 ts[1] = get_mtimespec(psbuf);
5612 * We continue here as we might want to change the
5615 delete_on_fail = True;
5619 /* Horrible backwards compatibility hack as an old server bug
5620 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5624 size = get_file_size(*psbuf);
5629 * Deal with the UNIX specific mode set.
5632 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5633 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5634 (unsigned int)unixmode, fname ));
5635 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5636 return map_nt_error_from_unix(errno);
5641 * Deal with the UNIX specific uid set.
5644 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5647 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5648 (unsigned int)set_owner, fname ));
5650 if (S_ISLNK(psbuf->st_mode)) {
5651 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5653 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5657 status = map_nt_error_from_unix(errno);
5658 if (delete_on_fail) {
5659 SMB_VFS_UNLINK(conn,fname);
5666 * Deal with the UNIX specific gid set.
5669 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5670 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5671 (unsigned int)set_owner, fname ));
5672 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5673 status = map_nt_error_from_unix(errno);
5674 if (delete_on_fail) {
5675 SMB_VFS_UNLINK(conn,fname);
5681 /* Deal with any size changes. */
5683 status = smb_set_file_size(conn, req,
5688 if (!NT_STATUS_IS_OK(status)) {
5692 /* Deal with any time changes. */
5694 return smb_set_file_time(conn,
5702 /****************************************************************************
5703 Deal with SMB_SET_FILE_UNIX_INFO2.
5704 ****************************************************************************/
5706 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5707 struct smb_request *req,
5712 SMB_STRUCT_STAT *psbuf)
5718 if (total_data < 116) {
5719 return NT_STATUS_INVALID_PARAMETER;
5722 /* Start by setting all the fields that are common between UNIX_BASIC
5725 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5727 if (!NT_STATUS_IS_OK(status)) {
5731 smb_fflags = IVAL(pdata, 108);
5732 smb_fmask = IVAL(pdata, 112);
5734 /* NB: We should only attempt to alter the file flags if the client
5735 * sends a non-zero mask.
5737 if (smb_fmask != 0) {
5738 int stat_fflags = 0;
5740 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5742 /* Client asked to alter a flag we don't understand. */
5743 return NT_STATUS_INVALID_PARAMETER;
5746 if (fsp && fsp->fh->fd != -1) {
5747 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5748 return NT_STATUS_NOT_SUPPORTED;
5750 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5751 return map_nt_error_from_unix(errno);
5756 /* XXX: need to add support for changing the create_time here. You
5757 * can do this for paths on Darwin with setattrlist(2). The right way
5758 * to hook this up is probably by extending the VFS utimes interface.
5761 return NT_STATUS_OK;
5764 /****************************************************************************
5765 Create a directory with POSIX semantics.
5766 ****************************************************************************/
5768 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5769 struct smb_request *req,
5773 SMB_STRUCT_STAT *psbuf,
5774 int *pdata_return_size)
5776 NTSTATUS status = NT_STATUS_OK;
5777 uint32 raw_unixmode = 0;
5778 uint32 mod_unixmode = 0;
5779 mode_t unixmode = (mode_t)0;
5780 files_struct *fsp = NULL;
5781 uint16 info_level_return = 0;
5783 char *pdata = *ppdata;
5785 if (total_data < 18) {
5786 return NT_STATUS_INVALID_PARAMETER;
5789 raw_unixmode = IVAL(pdata,8);
5790 /* Next 4 bytes are not yet defined. */
5792 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5793 if (!NT_STATUS_IS_OK(status)) {
5797 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5799 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5800 fname, (unsigned int)unixmode ));
5802 status = open_directory(conn, req,
5805 FILE_READ_ATTRIBUTES, /* Just a stat open */
5806 FILE_SHARE_NONE, /* Ignored for stat opens */
5813 if (NT_STATUS_IS_OK(status)) {
5814 close_file(fsp, NORMAL_CLOSE);
5817 info_level_return = SVAL(pdata,16);
5819 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5820 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5821 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5822 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5824 *pdata_return_size = 12;
5827 /* Realloc the data size */
5828 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5829 if (*ppdata == NULL) {
5830 *pdata_return_size = 0;
5831 return NT_STATUS_NO_MEMORY;
5835 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5836 SSVAL(pdata,2,0); /* No fnum. */
5837 SIVAL(pdata,4,info); /* Was directory created. */
5839 switch (info_level_return) {
5840 case SMB_QUERY_FILE_UNIX_BASIC:
5841 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5842 SSVAL(pdata,10,0); /* Padding. */
5843 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5845 case SMB_QUERY_FILE_UNIX_INFO2:
5846 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5847 SSVAL(pdata,10,0); /* Padding. */
5848 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5851 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5852 SSVAL(pdata,10,0); /* Padding. */
5859 /****************************************************************************
5860 Open/Create a file with POSIX semantics.
5861 ****************************************************************************/
5863 static NTSTATUS smb_posix_open(connection_struct *conn,
5864 struct smb_request *req,
5868 SMB_STRUCT_STAT *psbuf,
5869 int *pdata_return_size)
5871 bool extended_oplock_granted = False;
5872 char *pdata = *ppdata;
5874 uint32 wire_open_mode = 0;
5875 uint32 raw_unixmode = 0;
5876 uint32 mod_unixmode = 0;
5877 uint32 create_disp = 0;
5878 uint32 access_mask = 0;
5879 uint32 create_options = 0;
5880 NTSTATUS status = NT_STATUS_OK;
5881 mode_t unixmode = (mode_t)0;
5882 files_struct *fsp = NULL;
5883 int oplock_request = 0;
5885 uint16 info_level_return = 0;
5887 if (total_data < 18) {
5888 return NT_STATUS_INVALID_PARAMETER;
5891 flags = IVAL(pdata,0);
5892 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5893 if (oplock_request) {
5894 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5897 wire_open_mode = IVAL(pdata,4);
5899 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5900 return smb_posix_mkdir(conn, req,
5908 switch (wire_open_mode & SMB_ACCMODE) {
5910 access_mask = FILE_READ_DATA;
5913 access_mask = FILE_WRITE_DATA;
5916 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5919 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5920 (unsigned int)wire_open_mode ));
5921 return NT_STATUS_INVALID_PARAMETER;
5924 wire_open_mode &= ~SMB_ACCMODE;
5926 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5927 create_disp = FILE_CREATE;
5928 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5929 create_disp = FILE_OVERWRITE_IF;
5930 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5931 create_disp = FILE_OPEN_IF;
5933 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5934 (unsigned int)wire_open_mode ));
5935 return NT_STATUS_INVALID_PARAMETER;
5938 raw_unixmode = IVAL(pdata,8);
5939 /* Next 4 bytes are not yet defined. */
5941 status = unix_perms_from_wire(conn,
5944 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5947 if (!NT_STATUS_IS_OK(status)) {
5951 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5953 if (wire_open_mode & SMB_O_SYNC) {
5954 create_options |= FILE_WRITE_THROUGH;
5956 if (wire_open_mode & SMB_O_APPEND) {
5957 access_mask |= FILE_APPEND_DATA;
5959 if (wire_open_mode & SMB_O_DIRECT) {
5960 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5963 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5965 (unsigned int)wire_open_mode,
5966 (unsigned int)unixmode ));
5968 status = open_file_ntcreate(conn, req,
5972 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5974 0, /* no create options yet. */
5980 if (!NT_STATUS_IS_OK(status)) {
5984 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5985 extended_oplock_granted = True;
5988 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5989 extended_oplock_granted = True;
5992 info_level_return = SVAL(pdata,16);
5994 /* Allocate the correct return size. */
5996 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5997 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5998 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5999 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6001 *pdata_return_size = 12;
6004 /* Realloc the data size */
6005 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6006 if (*ppdata == NULL) {
6007 close_file(fsp,ERROR_CLOSE);
6008 *pdata_return_size = 0;
6009 return NT_STATUS_NO_MEMORY;
6013 if (extended_oplock_granted) {
6014 if (flags & REQUEST_BATCH_OPLOCK) {
6015 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6017 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6019 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6020 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6022 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6025 SSVAL(pdata,2,fsp->fnum);
6026 SIVAL(pdata,4,info); /* Was file created etc. */
6028 switch (info_level_return) {
6029 case SMB_QUERY_FILE_UNIX_BASIC:
6030 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6031 SSVAL(pdata,10,0); /* padding. */
6032 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6034 case SMB_QUERY_FILE_UNIX_INFO2:
6035 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6036 SSVAL(pdata,10,0); /* padding. */
6037 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6040 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6041 SSVAL(pdata,10,0); /* padding. */
6044 return NT_STATUS_OK;
6047 /****************************************************************************
6048 Delete a file with POSIX semantics.
6049 ****************************************************************************/
6051 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6052 struct smb_request *req,
6056 SMB_STRUCT_STAT *psbuf)
6058 NTSTATUS status = NT_STATUS_OK;
6059 files_struct *fsp = NULL;
6064 struct share_mode_lock *lck = NULL;
6066 if (total_data < 2) {
6067 return NT_STATUS_INVALID_PARAMETER;
6070 flags = SVAL(pdata,0);
6072 if (!VALID_STAT(*psbuf)) {
6073 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6076 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6077 !VALID_STAT_OF_DIR(*psbuf)) {
6078 return NT_STATUS_NOT_A_DIRECTORY;
6081 DEBUG(10,("smb_posix_unlink: %s %s\n",
6082 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6085 if (VALID_STAT_OF_DIR(*psbuf)) {
6086 status = open_directory(conn, req,
6090 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6093 FILE_FLAG_POSIX_SEMANTICS|0777,
6098 status = open_file_ntcreate(conn, req,
6102 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6105 FILE_FLAG_POSIX_SEMANTICS|0777,
6106 0, /* No oplock, but break existing ones. */
6111 if (!NT_STATUS_IS_OK(status)) {
6116 * Don't lie to client. If we can't really delete due to
6117 * non-POSIX opens return SHARING_VIOLATION.
6120 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
6122 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6123 "lock for file %s\n", fsp->fsp_name));
6124 close_file(fsp, NORMAL_CLOSE);
6125 return NT_STATUS_INVALID_PARAMETER;
6129 * See if others still have the file open. If this is the case, then
6130 * don't delete. If all opens are POSIX delete we can set the delete
6131 * on close disposition.
6133 for (i=0; i<lck->num_share_modes; i++) {
6134 struct share_mode_entry *e = &lck->share_modes[i];
6135 if (is_valid_share_mode_entry(e)) {
6136 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6139 /* Fail with sharing violation. */
6140 close_file(fsp, NORMAL_CLOSE);
6142 return NT_STATUS_SHARING_VIOLATION;
6147 * Set the delete on close.
6149 status = smb_set_file_disposition_info(conn,
6156 if (!NT_STATUS_IS_OK(status)) {
6157 close_file(fsp, NORMAL_CLOSE);
6162 return close_file(fsp, NORMAL_CLOSE);
6165 /****************************************************************************
6166 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6167 ****************************************************************************/
6169 static void call_trans2setfilepathinfo(connection_struct *conn,
6170 struct smb_request *req,
6171 unsigned int tran_call,
6172 char **pparams, int total_params,
6173 char **ppdata, int total_data,
6174 unsigned int max_data_bytes)
6176 char *params = *pparams;
6177 char *pdata = *ppdata;
6179 SMB_STRUCT_STAT sbuf;
6181 files_struct *fsp = NULL;
6182 NTSTATUS status = NT_STATUS_OK;
6183 int data_return_size = 0;
6184 TALLOC_CTX *ctx = talloc_tos();
6187 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6193 if (tran_call == TRANSACT2_SETFILEINFO) {
6194 if (total_params < 4) {
6195 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6199 fsp = file_fsp(SVAL(params,0));
6200 /* Basic check for non-null fsp. */
6201 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
6204 info_level = SVAL(params,2);
6206 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6208 reply_nterror(req, NT_STATUS_NO_MEMORY);
6212 if(fsp->is_directory || fsp->fh->fd == -1) {
6214 * This is actually a SETFILEINFO on a directory
6215 * handle (returned from an NT SMB). NT5.0 seems
6216 * to do this call. JRA.
6218 if (INFO_LEVEL_IS_UNIX(info_level)) {
6219 /* Always do lstat for UNIX calls. */
6220 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6221 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6222 reply_unixerror(req,ERRDOS,ERRbadpath);
6226 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6227 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6228 reply_unixerror(req,ERRDOS,ERRbadpath);
6232 } else if (fsp->print_file) {
6234 * Doing a DELETE_ON_CLOSE should cancel a print job.
6236 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6237 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6239 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6242 send_trans2_replies(req, params, 2,
6247 reply_unixerror(req, ERRDOS, ERRbadpath);
6252 * Original code - this is an open file.
6254 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6258 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6259 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6260 reply_unixerror(req, ERRDOS, ERRbadfid);
6266 if (total_params < 7) {
6267 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6271 info_level = SVAL(params,0);
6272 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6273 total_params - 6, STR_TERMINATE,
6275 if (!NT_STATUS_IS_OK(status)) {
6276 reply_nterror(req, status);
6280 status = resolve_dfspath(ctx, conn,
6281 req->flags2 & FLAGS2_DFS_PATHNAMES,
6284 if (!NT_STATUS_IS_OK(status)) {
6285 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6286 reply_botherror(req,
6287 NT_STATUS_PATH_NOT_COVERED,
6288 ERRSRV, ERRbadpath);
6291 reply_nterror(req, status);
6295 status = unix_convert(ctx, conn, fname, False,
6296 &fname, NULL, &sbuf);
6297 if (!NT_STATUS_IS_OK(status)) {
6298 reply_nterror(req, status);
6302 status = check_name(conn, fname);
6303 if (!NT_STATUS_IS_OK(status)) {
6304 reply_nterror(req, status);
6308 if (INFO_LEVEL_IS_UNIX(info_level)) {
6310 * For CIFS UNIX extensions the target name may not exist.
6313 /* Always do lstat for UNIX calls. */
6314 SMB_VFS_LSTAT(conn,fname,&sbuf);
6316 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6317 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6318 reply_unixerror(req, ERRDOS, ERRbadpath);
6323 if (!CAN_WRITE(conn)) {
6324 reply_doserror(req, ERRSRV, ERRaccess);
6328 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6329 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6333 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6334 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6336 /* Realloc the parameter size */
6337 *pparams = (char *)SMB_REALLOC(*pparams,2);
6338 if (*pparams == NULL) {
6339 reply_nterror(req, NT_STATUS_NO_MEMORY);
6346 if (fsp && !null_timespec(fsp->pending_modtime)) {
6347 /* the pending modtime overrides the current modtime */
6348 set_mtimespec(&sbuf, fsp->pending_modtime);
6351 switch (info_level) {
6353 case SMB_INFO_STANDARD:
6355 status = smb_set_info_standard(conn,
6364 case SMB_INFO_SET_EA:
6366 status = smb_info_set_ea(conn,
6374 case SMB_SET_FILE_BASIC_INFO:
6375 case SMB_FILE_BASIC_INFORMATION:
6377 status = smb_set_file_basic_info(conn,
6386 case SMB_FILE_ALLOCATION_INFORMATION:
6387 case SMB_SET_FILE_ALLOCATION_INFO:
6389 status = smb_set_file_allocation_info(conn, req,
6398 case SMB_FILE_END_OF_FILE_INFORMATION:
6399 case SMB_SET_FILE_END_OF_FILE_INFO:
6401 status = smb_set_file_end_of_file_info(conn, req,
6410 case SMB_FILE_DISPOSITION_INFORMATION:
6411 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6414 /* JRA - We used to just ignore this on a path ?
6415 * Shouldn't this be invalid level on a pathname
6418 if (tran_call != TRANSACT2_SETFILEINFO) {
6419 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6422 status = smb_set_file_disposition_info(conn,
6431 case SMB_FILE_POSITION_INFORMATION:
6433 status = smb_file_position_information(conn,
6440 /* From tridge Samba4 :
6441 * MODE_INFORMATION in setfileinfo (I have no
6442 * idea what "mode information" on a file is - it takes a value of 0,
6443 * 2, 4 or 6. What could it be?).
6446 case SMB_FILE_MODE_INFORMATION:
6448 status = smb_file_mode_information(conn,
6455 * CIFS UNIX extensions.
6458 case SMB_SET_FILE_UNIX_BASIC:
6460 status = smb_set_file_unix_basic(conn, req,
6469 case SMB_SET_FILE_UNIX_INFO2:
6471 status = smb_set_file_unix_info2(conn, req,
6480 case SMB_SET_FILE_UNIX_LINK:
6482 if (tran_call != TRANSACT2_SETPATHINFO) {
6483 /* We must have a pathname for this. */
6484 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6487 status = smb_set_file_unix_link(conn, req, pdata,
6492 case SMB_SET_FILE_UNIX_HLINK:
6494 if (tran_call != TRANSACT2_SETPATHINFO) {
6495 /* We must have a pathname for this. */
6496 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6499 status = smb_set_file_unix_hlink(conn, req,
6505 case SMB_FILE_RENAME_INFORMATION:
6507 status = smb_file_rename_information(conn, req,
6513 #if defined(HAVE_POSIX_ACLS)
6514 case SMB_SET_POSIX_ACL:
6516 status = smb_set_posix_acl(conn,
6526 case SMB_SET_POSIX_LOCK:
6528 if (tran_call != TRANSACT2_SETFILEINFO) {
6529 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6532 status = smb_set_posix_lock(conn, req->inbuf,
6533 smb_len(req->inbuf) + 4,
6534 pdata, total_data, fsp);
6538 case SMB_POSIX_PATH_OPEN:
6540 if (tran_call != TRANSACT2_SETPATHINFO) {
6541 /* We must have a pathname for this. */
6542 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6546 status = smb_posix_open(conn, req,
6555 case SMB_POSIX_PATH_UNLINK:
6557 if (tran_call != TRANSACT2_SETPATHINFO) {
6558 /* We must have a pathname for this. */
6559 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6563 status = smb_posix_unlink(conn, req,
6572 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6577 if (!NT_STATUS_IS_OK(status)) {
6578 if (open_was_deferred(req->mid)) {
6579 /* We have re-scheduled this call. */
6582 if (blocking_lock_was_deferred(req->mid)) {
6583 /* We have re-scheduled this call. */
6586 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6587 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6588 ERRSRV, ERRbadpath);
6591 if (info_level == SMB_POSIX_PATH_OPEN) {
6592 reply_openerror(req, status);
6596 reply_nterror(req, status);
6601 send_trans2_replies(req, params, 2, *ppdata, data_return_size,
6607 /****************************************************************************
6608 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6609 ****************************************************************************/
6611 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6612 char **pparams, int total_params,
6613 char **ppdata, int total_data,
6614 unsigned int max_data_bytes)
6616 char *params = *pparams;
6617 char *pdata = *ppdata;
6618 char *directory = NULL;
6619 SMB_STRUCT_STAT sbuf;
6620 NTSTATUS status = NT_STATUS_OK;
6621 struct ea_list *ea_list = NULL;
6622 TALLOC_CTX *ctx = talloc_tos();
6624 if (!CAN_WRITE(conn)) {
6625 reply_doserror(req, ERRSRV, ERRaccess);
6629 if (total_params < 5) {
6630 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6634 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
6635 total_params - 4, STR_TERMINATE,
6637 if (!NT_STATUS_IS_OK(status)) {
6638 reply_nterror(req, status);
6642 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6644 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6645 if (!NT_STATUS_IS_OK(status)) {
6646 reply_nterror(req, status);
6650 status = check_name(conn, directory);
6651 if (!NT_STATUS_IS_OK(status)) {
6652 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6653 reply_nterror(req, status);
6657 /* Any data in this call is an EA list. */
6658 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6659 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6664 * OS/2 workplace shell seems to send SET_EA requests of "null"
6665 * length (4 bytes containing IVAL 4).
6666 * They seem to have no effect. Bug #3212. JRA.
6669 if (total_data != 4) {
6670 if (total_data < 10) {
6671 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6675 if (IVAL(pdata,0) > total_data) {
6676 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6677 IVAL(pdata,0), (unsigned int)total_data));
6678 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6682 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6685 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6688 } else if (IVAL(pdata,0) != 4) {
6689 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6693 status = create_directory(conn, directory);
6695 if (!NT_STATUS_IS_OK(status)) {
6696 reply_nterror(req, status);
6700 /* Try and set any given EA. */
6702 status = set_ea(conn, NULL, directory, ea_list);
6703 if (!NT_STATUS_IS_OK(status)) {
6704 reply_nterror(req, status);
6709 /* Realloc the parameter and data sizes */
6710 *pparams = (char *)SMB_REALLOC(*pparams,2);
6711 if(*pparams == NULL) {
6712 reply_nterror(req, NT_STATUS_NO_MEMORY);
6719 send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
6724 /****************************************************************************
6725 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6726 We don't actually do this - we just send a null response.
6727 ****************************************************************************/
6729 static void call_trans2findnotifyfirst(connection_struct *conn,
6730 struct smb_request *req,
6731 char **pparams, int total_params,
6732 char **ppdata, int total_data,
6733 unsigned int max_data_bytes)
6735 static uint16 fnf_handle = 257;
6736 char *params = *pparams;
6739 if (total_params < 6) {
6740 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6744 info_level = SVAL(params,4);
6745 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6747 switch (info_level) {
6752 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6756 /* Realloc the parameter and data sizes */
6757 *pparams = (char *)SMB_REALLOC(*pparams,6);
6758 if (*pparams == NULL) {
6759 reply_nterror(req, NT_STATUS_NO_MEMORY);
6764 SSVAL(params,0,fnf_handle);
6765 SSVAL(params,2,0); /* No changes */
6766 SSVAL(params,4,0); /* No EA errors */
6773 send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
6778 /****************************************************************************
6779 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6780 changes). Currently this does nothing.
6781 ****************************************************************************/
6783 static void call_trans2findnotifynext(connection_struct *conn,
6784 struct smb_request *req,
6785 char **pparams, int total_params,
6786 char **ppdata, int total_data,
6787 unsigned int max_data_bytes)
6789 char *params = *pparams;
6791 DEBUG(3,("call_trans2findnotifynext\n"));
6793 /* Realloc the parameter and data sizes */
6794 *pparams = (char *)SMB_REALLOC(*pparams,4);
6795 if (*pparams == NULL) {
6796 reply_nterror(req, NT_STATUS_NO_MEMORY);
6801 SSVAL(params,0,0); /* No changes */
6802 SSVAL(params,2,0); /* No EA errors */
6804 send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes);
6809 /****************************************************************************
6810 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6811 ****************************************************************************/
6813 static void call_trans2getdfsreferral(connection_struct *conn,
6814 struct smb_request *req,
6815 char **pparams, int total_params,
6816 char **ppdata, int total_data,
6817 unsigned int max_data_bytes)
6819 char *params = *pparams;
6820 char *pathname = NULL;
6822 int max_referral_level;
6823 NTSTATUS status = NT_STATUS_OK;
6824 TALLOC_CTX *ctx = talloc_tos();
6826 DEBUG(10,("call_trans2getdfsreferral\n"));
6828 if (total_params < 3) {
6829 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6833 max_referral_level = SVAL(params,0);
6835 if(!lp_host_msdfs()) {
6836 reply_doserror(req, ERRDOS, ERRbadfunc);
6840 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
6841 total_params - 2, STR_TERMINATE);
6843 reply_nterror(req, NT_STATUS_NOT_FOUND);
6846 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6847 ppdata,&status)) < 0) {
6848 reply_nterror(req, status);
6852 SSVAL(req->inbuf, smb_flg2,
6853 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6854 send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes);
6859 #define LMCAT_SPL 0x53
6860 #define LMFUNC_GETJOBID 0x60
6862 /****************************************************************************
6863 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6864 ****************************************************************************/
6866 static void call_trans2ioctl(connection_struct *conn,
6867 struct smb_request *req,
6868 char **pparams, int total_params,
6869 char **ppdata, int total_data,
6870 unsigned int max_data_bytes)
6872 char *pdata = *ppdata;
6873 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6875 /* check for an invalid fid before proceeding */
6878 reply_doserror(req, ERRDOS, ERRbadfid);
6882 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6883 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6884 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6885 if (*ppdata == NULL) {
6886 reply_nterror(req, NT_STATUS_NO_MEMORY);
6891 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6892 CAN ACCEPT THIS IN UNICODE. JRA. */
6894 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6895 srvstr_push(pdata, req->flags2, pdata + 2,
6896 global_myname(), 15,
6897 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6898 srvstr_push(pdata, req->flags2, pdata+18,
6899 lp_servicename(SNUM(conn)), 13,
6900 STR_ASCII|STR_TERMINATE); /* Service name */
6901 send_trans2_replies(req, *pparams, 0, *ppdata, 32,
6906 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6907 reply_doserror(req, ERRSRV, ERRerror);
6910 /****************************************************************************
6911 Reply to a SMBfindclose (stop trans2 directory search).
6912 ****************************************************************************/
6914 void reply_findclose(connection_struct *conn, struct smb_request *req)
6918 START_PROFILE(SMBfindclose);
6921 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6922 END_PROFILE(SMBfindclose);
6926 dptr_num = SVALS(req->inbuf,smb_vwv0);
6928 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6930 dptr_close(&dptr_num);
6932 reply_outbuf(req, 0, 0);
6934 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6936 END_PROFILE(SMBfindclose);
6940 /****************************************************************************
6941 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6942 ****************************************************************************/
6944 void reply_findnclose(connection_struct *conn, struct smb_request *req)
6948 START_PROFILE(SMBfindnclose);
6951 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6952 END_PROFILE(SMBfindnclose);
6956 dptr_num = SVAL(req->inbuf,smb_vwv0);
6958 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6960 /* We never give out valid handles for a
6961 findnotifyfirst - so any dptr_num is ok here.
6964 reply_outbuf(req, 0, 0);
6966 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6968 END_PROFILE(SMBfindnclose);
6972 static void handle_trans2(connection_struct *conn, struct smb_request *req,
6973 struct trans_state *state)
6975 if (Protocol >= PROTOCOL_NT1) {
6976 req->flags2 |= 0x40; /* IS_LONG_NAME */
6977 SSVAL(req->inbuf,smb_flg2,req->flags2);
6980 /* Now we must call the relevant TRANS2 function */
6981 switch(state->call) {
6982 case TRANSACT2_OPEN:
6984 START_PROFILE(Trans2_open);
6985 call_trans2open(conn, req,
6986 &state->param, state->total_param,
6987 &state->data, state->total_data,
6988 state->max_data_return);
6989 END_PROFILE(Trans2_open);
6993 case TRANSACT2_FINDFIRST:
6995 START_PROFILE(Trans2_findfirst);
6996 call_trans2findfirst(conn, req,
6997 &state->param, state->total_param,
6998 &state->data, state->total_data,
6999 state->max_data_return);
7000 END_PROFILE(Trans2_findfirst);
7004 case TRANSACT2_FINDNEXT:
7006 START_PROFILE(Trans2_findnext);
7007 call_trans2findnext(conn, req,
7008 &state->param, state->total_param,
7009 &state->data, state->total_data,
7010 state->max_data_return);
7011 END_PROFILE(Trans2_findnext);
7015 case TRANSACT2_QFSINFO:
7017 START_PROFILE(Trans2_qfsinfo);
7018 call_trans2qfsinfo(conn, req,
7019 &state->param, state->total_param,
7020 &state->data, state->total_data,
7021 state->max_data_return);
7022 END_PROFILE(Trans2_qfsinfo);
7026 case TRANSACT2_SETFSINFO:
7028 START_PROFILE(Trans2_setfsinfo);
7029 call_trans2setfsinfo(conn, req,
7030 &state->param, state->total_param,
7031 &state->data, state->total_data,
7032 state->max_data_return);
7033 END_PROFILE(Trans2_setfsinfo);
7037 case TRANSACT2_QPATHINFO:
7038 case TRANSACT2_QFILEINFO:
7040 START_PROFILE(Trans2_qpathinfo);
7041 call_trans2qfilepathinfo(conn, req, state->call,
7042 &state->param, state->total_param,
7043 &state->data, state->total_data,
7044 state->max_data_return);
7045 END_PROFILE(Trans2_qpathinfo);
7049 case TRANSACT2_SETPATHINFO:
7050 case TRANSACT2_SETFILEINFO:
7052 START_PROFILE(Trans2_setpathinfo);
7053 call_trans2setfilepathinfo(conn, req, state->call,
7054 &state->param, state->total_param,
7055 &state->data, state->total_data,
7056 state->max_data_return);
7057 END_PROFILE(Trans2_setpathinfo);
7061 case TRANSACT2_FINDNOTIFYFIRST:
7063 START_PROFILE(Trans2_findnotifyfirst);
7064 call_trans2findnotifyfirst(conn, req,
7065 &state->param, state->total_param,
7066 &state->data, state->total_data,
7067 state->max_data_return);
7068 END_PROFILE(Trans2_findnotifyfirst);
7072 case TRANSACT2_FINDNOTIFYNEXT:
7074 START_PROFILE(Trans2_findnotifynext);
7075 call_trans2findnotifynext(conn, req,
7076 &state->param, state->total_param,
7077 &state->data, state->total_data,
7078 state->max_data_return);
7079 END_PROFILE(Trans2_findnotifynext);
7083 case TRANSACT2_MKDIR:
7085 START_PROFILE(Trans2_mkdir);
7086 call_trans2mkdir(conn, req,
7087 &state->param, state->total_param,
7088 &state->data, state->total_data,
7089 state->max_data_return);
7090 END_PROFILE(Trans2_mkdir);
7094 case TRANSACT2_GET_DFS_REFERRAL:
7096 START_PROFILE(Trans2_get_dfs_referral);
7097 call_trans2getdfsreferral(conn, req,
7098 &state->param, state->total_param,
7099 &state->data, state->total_data,
7100 state->max_data_return);
7101 END_PROFILE(Trans2_get_dfs_referral);
7105 case TRANSACT2_IOCTL:
7107 START_PROFILE(Trans2_ioctl);
7108 call_trans2ioctl(conn, req,
7109 &state->param, state->total_param,
7110 &state->data, state->total_data,
7111 state->max_data_return);
7112 END_PROFILE(Trans2_ioctl);
7117 /* Error in request */
7118 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7119 reply_doserror(req, ERRSRV,ERRerror);
7123 /****************************************************************************
7124 Reply to a SMBtrans2.
7125 ****************************************************************************/
7127 void reply_trans2(connection_struct *conn, struct smb_request *req)
7133 unsigned int tran_call;
7135 struct trans_state *state;
7138 START_PROFILE(SMBtrans2);
7140 if (req->wct < 14) {
7141 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7142 END_PROFILE(SMBtrans2);
7146 dsoff = SVAL(req->inbuf, smb_dsoff);
7147 dscnt = SVAL(req->inbuf, smb_dscnt);
7148 psoff = SVAL(req->inbuf, smb_psoff);
7149 pscnt = SVAL(req->inbuf, smb_pscnt);
7150 tran_call = SVAL(req->inbuf, smb_setup0);
7151 size = smb_len(req->inbuf) + 4;
7153 result = allow_new_trans(conn->pending_trans, req->mid);
7154 if (!NT_STATUS_IS_OK(result)) {
7155 DEBUG(2, ("Got invalid trans2 request: %s\n",
7156 nt_errstr(result)));
7157 reply_nterror(req, result);
7158 END_PROFILE(SMBtrans2);
7162 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
7163 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
7164 && (tran_call != TRANSACT2_QFILEINFO)) {
7165 reply_doserror(req, ERRSRV, ERRaccess);
7166 END_PROFILE(SMBtrans2);
7170 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7171 DEBUG(0, ("talloc failed\n"));
7172 reply_nterror(req, NT_STATUS_NO_MEMORY);
7173 END_PROFILE(SMBtrans2);
7177 state->cmd = SMBtrans2;
7179 state->mid = req->mid;
7180 state->vuid = req->vuid;
7181 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7182 state->setup = NULL;
7183 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7184 state->param = NULL;
7185 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7187 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7188 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7189 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7190 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7191 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7193 state->call = tran_call;
7195 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7196 is so as a sanity check */
7197 if (state->setup_count != 1) {
7199 * Need to have rc=0 for ioctl to get job id for OS/2.
7200 * Network printing will fail if function is not successful.
7201 * Similar function in reply.c will be used if protocol
7202 * is LANMAN1.0 instead of LM1.2X002.
7203 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7204 * outbuf doesn't have to be set(only job id is used).
7206 if ( (state->setup_count == 4)
7207 && (tran_call == TRANSACT2_IOCTL)
7208 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7209 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7210 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7212 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7213 DEBUG(2,("Transaction is %d\n",tran_call));
7215 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7216 END_PROFILE(SMBtrans2);
7221 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7224 if (state->total_data) {
7225 /* Can't use talloc here, the core routines do realloc on the
7226 * params and data. */
7227 state->data = (char *)SMB_MALLOC(state->total_data);
7228 if (state->data == NULL) {
7229 DEBUG(0,("reply_trans2: data malloc fail for %u "
7230 "bytes !\n", (unsigned int)state->total_data));
7232 reply_nterror(req, NT_STATUS_NO_MEMORY);
7233 END_PROFILE(SMBtrans2);
7236 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7238 if ((smb_base(req->inbuf)+dsoff+dscnt
7239 > (char *)req->inbuf + size) ||
7240 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7243 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7246 if (state->total_param) {
7247 /* Can't use talloc here, the core routines do realloc on the
7248 * params and data. */
7249 state->param = (char *)SMB_MALLOC(state->total_param);
7250 if (state->param == NULL) {
7251 DEBUG(0,("reply_trans: param malloc fail for %u "
7252 "bytes !\n", (unsigned int)state->total_param));
7253 SAFE_FREE(state->data);
7255 reply_nterror(req, NT_STATUS_NO_MEMORY);
7256 END_PROFILE(SMBtrans2);
7259 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7261 if ((smb_base(req->inbuf)+psoff+pscnt
7262 > (char *)req->inbuf + size) ||
7263 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7266 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7269 state->received_data = dscnt;
7270 state->received_param = pscnt;
7272 if ((state->received_param == state->total_param) &&
7273 (state->received_data == state->total_data)) {
7275 handle_trans2(conn, req, state);
7277 SAFE_FREE(state->data);
7278 SAFE_FREE(state->param);
7280 END_PROFILE(SMBtrans2);
7284 DLIST_ADD(conn->pending_trans, state);
7286 /* We need to send an interim response then receive the rest
7287 of the parameter/data bytes */
7288 reply_outbuf(req, 0, 0);
7289 show_msg((char *)req->outbuf);
7290 END_PROFILE(SMBtrans2);
7295 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7296 SAFE_FREE(state->data);
7297 SAFE_FREE(state->param);
7299 END_PROFILE(SMBtrans2);
7300 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7304 /****************************************************************************
7305 Reply to a SMBtranss2
7306 ****************************************************************************/
7308 void reply_transs2(connection_struct *conn, struct smb_request *req)
7310 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7311 struct trans_state *state;
7314 START_PROFILE(SMBtranss2);
7316 show_msg((char *)req->inbuf);
7319 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7320 END_PROFILE(SMBtranss2);
7324 size = smb_len(req->inbuf)+4;
7326 for (state = conn->pending_trans; state != NULL;
7327 state = state->next) {
7328 if (state->mid == req->mid) {
7333 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7334 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7335 END_PROFILE(SMBtranss2);
7339 /* Revise state->total_param and state->total_data in case they have
7340 changed downwards */
7342 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7343 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7344 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7345 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7347 pcnt = SVAL(req->inbuf, smb_spscnt);
7348 poff = SVAL(req->inbuf, smb_spsoff);
7349 pdisp = SVAL(req->inbuf, smb_spsdisp);
7351 dcnt = SVAL(req->inbuf, smb_sdscnt);
7352 doff = SVAL(req->inbuf, smb_sdsoff);
7353 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7355 state->received_param += pcnt;
7356 state->received_data += dcnt;
7358 if ((state->received_data > state->total_data) ||
7359 (state->received_param > state->total_param))
7363 if (pdisp+pcnt > state->total_param)
7365 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7367 if (pdisp > state->total_param)
7369 if ((smb_base(req->inbuf) + poff + pcnt
7370 > (char *)req->inbuf + size) ||
7371 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7373 if (state->param + pdisp < state->param)
7376 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7381 if (ddisp+dcnt > state->total_data)
7383 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7385 if (ddisp > state->total_data)
7387 if ((smb_base(req->inbuf) + doff + dcnt
7388 > (char *)req->inbuf + size) ||
7389 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7391 if (state->data + ddisp < state->data)
7394 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7398 if ((state->received_param < state->total_param) ||
7399 (state->received_data < state->total_data)) {
7400 END_PROFILE(SMBtranss2);
7405 * construct_reply_common will copy smb_com from inbuf to
7406 * outbuf. SMBtranss2 is wrong here.
7408 SCVAL(req->inbuf,smb_com,SMBtrans2);
7410 handle_trans2(conn, req, state);
7412 DLIST_REMOVE(conn->pending_trans, state);
7413 SAFE_FREE(state->data);
7414 SAFE_FREE(state->param);
7417 END_PROFILE(SMBtranss2);
7422 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7423 DLIST_REMOVE(conn->pending_trans, state);
7424 SAFE_FREE(state->data);
7425 SAFE_FREE(state->param);
7427 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7428 END_PROFILE(SMBtranss2);