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 /* Copy the param bytes into the packet */
704 if(params_sent_thistime) {
705 if (alignment_offset != 0) {
706 memset(smb_buf(req->outbuf), 0,
709 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
710 params_sent_thistime);
713 /* Copy in the data bytes */
714 if(data_sent_thistime) {
715 if (data_alignment_offset != 0) {
716 memset((smb_buf(req->outbuf)+alignment_offset+
717 params_sent_thistime), 0,
718 data_alignment_offset);
720 memcpy(smb_buf(req->outbuf)+alignment_offset
721 +params_sent_thistime+data_alignment_offset,
722 pd,data_sent_thistime);
725 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
726 params_sent_thistime, data_sent_thistime, useable_space));
727 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
728 params_to_send, data_to_send, paramsize, datasize));
731 error_packet_set((char *)req->outbuf,
732 ERRDOS,ERRbufferoverflow,
733 STATUS_BUFFER_OVERFLOW,
737 /* Send the packet */
738 show_msg((char *)req->outbuf);
739 if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
740 exit_server_cleanly("send_trans2_replies: send_smb failed.");
742 TALLOC_FREE(req->outbuf);
744 pp += params_sent_thistime;
745 pd += data_sent_thistime;
747 params_to_send -= params_sent_thistime;
748 data_to_send -= data_sent_thistime;
751 if(params_to_send < 0 || data_to_send < 0) {
752 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
753 params_to_send, data_to_send));
761 /****************************************************************************
762 Reply to a TRANSACT2_OPEN.
763 ****************************************************************************/
765 static void call_trans2open(connection_struct *conn,
766 struct smb_request *req,
767 char **pparams, int total_params,
768 char **ppdata, int total_data,
769 unsigned int max_data_bytes)
771 char *params = *pparams;
772 char *pdata = *ppdata;
777 BOOL return_additional_info;
788 SMB_STRUCT_STAT sbuf;
791 struct ea_list *ea_list = NULL;
796 uint32 create_disposition;
797 uint32 create_options = 0;
800 * Ensure we have enough parameters to perform the operation.
803 if (total_params < 29) {
804 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
808 flags = SVAL(params, 0);
809 deny_mode = SVAL(params, 2);
810 open_attr = SVAL(params,6);
811 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
812 if (oplock_request) {
813 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
817 return_additional_info = BITSETW(params,0);
818 open_sattr = SVAL(params, 4);
819 open_time = make_unix_date3(params+8);
821 open_ofun = SVAL(params,12);
822 open_size = IVAL(params,14);
826 reply_doserror(req, ERRSRV, ERRaccess);
830 srvstr_get_path(params, req->flags2, fname, pname,
831 sizeof(fname), total_params - 28, STR_TERMINATE,
833 if (!NT_STATUS_IS_OK(status)) {
834 reply_nterror(req, status);
838 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
839 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
840 (unsigned int)open_ofun, open_size));
842 /* XXXX we need to handle passed times, sattr and flags */
844 status = unix_convert(conn, fname, False, NULL, &sbuf);
845 if (!NT_STATUS_IS_OK(status)) {
846 reply_nterror(req, status);
850 status = check_name(conn, fname);
851 if (!NT_STATUS_IS_OK(status)) {
852 reply_nterror(req, status);
856 if (open_ofun == 0) {
857 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
861 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
866 reply_doserror(req, ERRDOS, ERRbadaccess);
870 /* Any data in this call is an EA list. */
871 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
872 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
876 if (total_data != 4) {
877 if (total_data < 10) {
878 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
882 if (IVAL(pdata,0) > total_data) {
883 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
884 IVAL(pdata,0), (unsigned int)total_data));
885 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
889 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
892 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
895 } else if (IVAL(pdata,0) != 4) {
896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
900 status = open_file_ntcreate(conn, req, fname, &sbuf,
909 if (!NT_STATUS_IS_OK(status)) {
910 if (open_was_deferred(req->mid)) {
911 /* We have re-scheduled this call. */
914 reply_nterror(req, status);
918 size = get_file_size(sbuf);
919 fattr = dos_mode(conn,fname,&sbuf);
920 mtime = sbuf.st_mtime;
923 close_file(fsp,ERROR_CLOSE);
924 reply_doserror(req, ERRDOS,ERRnoaccess);
928 /* Save the requested allocation size. */
929 /* Allocate space for the file if a size hint is supplied */
930 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
931 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
932 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
933 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
934 if (fsp->is_directory) {
935 close_file(fsp,ERROR_CLOSE);
936 /* Can't set allocation size on a directory. */
937 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
940 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
941 close_file(fsp,ERROR_CLOSE);
942 reply_nterror(req, NT_STATUS_DISK_FULL);
946 /* Adjust size here to return the right size in the reply.
947 Windows does it this way. */
948 size = fsp->initial_allocation_size;
950 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
954 if (ea_list && smb_action == FILE_WAS_CREATED) {
955 status = set_ea(conn, fsp, fname, ea_list);
956 if (!NT_STATUS_IS_OK(status)) {
957 close_file(fsp,ERROR_CLOSE);
958 reply_nterror(req, status);
963 /* Realloc the size of parameters and data we will return */
964 *pparams = (char *)SMB_REALLOC(*pparams, 30);
965 if(*pparams == NULL ) {
966 reply_nterror(req, NT_STATUS_NO_MEMORY);
971 SSVAL(params,0,fsp->fnum);
972 SSVAL(params,2,fattr);
973 srv_put_dos_date2(params,4, mtime);
974 SIVAL(params,8, (uint32)size);
975 SSVAL(params,12,deny_mode);
976 SSVAL(params,14,0); /* open_type - file or directory. */
977 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
979 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
980 smb_action |= EXTENDED_OPLOCK_GRANTED;
983 SSVAL(params,18,smb_action);
986 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
988 SIVAL(params,20,inode);
989 SSVAL(params,24,0); /* Padding. */
991 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
992 SIVAL(params, 26, ea_size);
994 SIVAL(params, 26, 0);
997 /* Send the required number of replies */
998 send_trans2_replies(req, params, 30, *ppdata, 0, max_data_bytes);
1001 /*********************************************************
1002 Routine to check if a given string matches exactly.
1003 as a special case a mask of "." does NOT match. That
1004 is required for correct wildcard semantics
1005 Case can be significant or not.
1006 **********************************************************/
1008 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
1010 if (mask[0] == '.' && mask[1] == 0)
1012 if (conn->case_sensitive)
1013 return strcmp(str,mask)==0;
1014 if (StrCaseCmp(str,mask) != 0) {
1017 if (dptr_has_wild(conn->dirptr)) {
1023 /****************************************************************************
1024 Return the filetype for UNIX extensions.
1025 ****************************************************************************/
1027 static uint32 unix_filetype(mode_t mode)
1030 return UNIX_TYPE_FILE;
1031 else if(S_ISDIR(mode))
1032 return UNIX_TYPE_DIR;
1034 else if(S_ISLNK(mode))
1035 return UNIX_TYPE_SYMLINK;
1038 else if(S_ISCHR(mode))
1039 return UNIX_TYPE_CHARDEV;
1042 else if(S_ISBLK(mode))
1043 return UNIX_TYPE_BLKDEV;
1046 else if(S_ISFIFO(mode))
1047 return UNIX_TYPE_FIFO;
1050 else if(S_ISSOCK(mode))
1051 return UNIX_TYPE_SOCKET;
1054 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1055 return UNIX_TYPE_UNKNOWN;
1058 /****************************************************************************
1059 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1060 ****************************************************************************/
1062 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1064 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1065 SMB_STRUCT_STAT *psbuf,
1067 enum perm_type ptype,
1072 if (perms == SMB_MODE_NO_CHANGE) {
1073 if (!VALID_STAT(*psbuf)) {
1074 return NT_STATUS_INVALID_PARAMETER;
1076 *ret_perms = psbuf->st_mode;
1077 return NT_STATUS_OK;
1081 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1082 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1083 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1084 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1085 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1086 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1087 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1088 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1089 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1091 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1094 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1097 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1102 /* Apply mode mask */
1103 ret &= lp_create_mask(SNUM(conn));
1104 /* Add in force bits */
1105 ret |= lp_force_create_mode(SNUM(conn));
1108 ret &= lp_dir_mask(SNUM(conn));
1109 /* Add in force bits */
1110 ret |= lp_force_dir_mode(SNUM(conn));
1112 case PERM_EXISTING_FILE:
1113 /* Apply mode mask */
1114 ret &= lp_security_mask(SNUM(conn));
1115 /* Add in force bits */
1116 ret |= lp_force_security_mode(SNUM(conn));
1118 case PERM_EXISTING_DIR:
1119 /* Apply mode mask */
1120 ret &= lp_dir_security_mask(SNUM(conn));
1121 /* Add in force bits */
1122 ret |= lp_force_dir_security_mode(SNUM(conn));
1127 return NT_STATUS_OK;
1130 /****************************************************************************
1131 Get a level dependent lanman2 dir entry.
1132 ****************************************************************************/
1134 static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
1135 char *path_mask,uint32 dirtype,int info_level,
1136 int requires_resume_key,
1137 BOOL dont_descend,char **ppdata,
1138 char *base_data, char *end_data,
1139 int space_remaining,
1140 BOOL *out_of_space, BOOL *got_exact_match,
1141 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1145 SMB_STRUCT_STAT sbuf;
1149 char *p, *q, *pdata = *ppdata;
1153 SMB_OFF_T file_size = 0;
1154 SMB_BIG_UINT allocation_size = 0;
1156 struct timespec mdate_ts, adate_ts, create_date_ts;
1157 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1159 char *last_entry_ptr;
1161 uint32 nt_extmode; /* Used for NT connections instead of mode */
1162 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1163 BOOL check_mangled_names = lp_manglednames(conn->params);
1166 *out_of_space = False;
1167 *got_exact_match = False;
1169 ZERO_STRUCT(mdate_ts);
1170 ZERO_STRUCT(adate_ts);
1171 ZERO_STRUCT(create_date_ts);
1176 p = strrchr_m(path_mask,'/');
1179 pstrcpy(mask,"*.*");
1183 pstrcpy(mask, path_mask);
1188 BOOL ms_dfs_link = False;
1190 /* Needed if we run out of space */
1191 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1192 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1195 * Due to bugs in NT client redirectors we are not using
1196 * resume keys any more - set them to zero.
1197 * Check out the related comments in findfirst/findnext.
1203 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1204 (long)conn->dirptr,curr_dirpos));
1211 * fname may get mangled, dname is never mangled.
1212 * Whenever we're accessing the filesystem we use
1213 * pathreal which is composed from dname.
1216 pstrcpy(fname,dname);
1218 /* This will mangle fname if it's an illegal name. */
1219 mangle_map(fname,False,True,conn->params);
1221 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1222 got_match = mask_match(fname, mask, conn->case_sensitive);
1225 if(!got_match && check_mangled_names &&
1226 !mangle_is_8_3(fname, False, conn->params)) {
1227 pstring mangled_name;
1230 * It turns out that NT matches wildcards against
1231 * both long *and* short names. This may explain some
1232 * of the wildcard wierdness from old DOS clients
1233 * that some people have been seeing.... JRA.
1236 pstrcpy(mangled_name, fname);
1238 /* Force the mangling into 8.3. */
1239 mangle_map( mangled_name, True, False, conn->params);
1240 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1241 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1246 BOOL isdots = (strequal(dname,"..") || strequal(dname,"."));
1247 if (dont_descend && !isdots) {
1251 pstrcpy(pathreal,conn->dirpath);
1253 pstrcat(pathreal,"/");
1255 pstrcat(pathreal,dname);
1257 if (INFO_LEVEL_IS_UNIX(info_level)) {
1258 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1259 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1260 pathreal,strerror(errno)));
1263 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1264 pstring link_target;
1266 /* Needed to show the msdfs symlinks as
1269 if(lp_host_msdfs() &&
1270 lp_msdfs_root(SNUM(conn)) &&
1271 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1272 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1275 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1279 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1280 pathreal,strerror(errno)));
1286 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1288 mode = dos_mode(conn,pathreal,&sbuf);
1291 if (!dir_check_ftype(conn,mode,dirtype)) {
1292 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1296 if (!(mode & aDIR)) {
1297 file_size = get_file_size(sbuf);
1299 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1301 mdate_ts = get_mtimespec(&sbuf);
1302 adate_ts = get_atimespec(&sbuf);
1303 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1305 if (lp_dos_filetime_resolution(SNUM(conn))) {
1306 dos_filetime_timespec(&create_date_ts);
1307 dos_filetime_timespec(&mdate_ts);
1308 dos_filetime_timespec(&adate_ts);
1311 create_date = convert_timespec_to_time_t(create_date_ts);
1312 mdate = convert_timespec_to_time_t(mdate_ts);
1313 adate = convert_timespec_to_time_t(adate_ts);
1315 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1319 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1326 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1328 switch (info_level) {
1329 case SMB_FIND_INFO_STANDARD:
1330 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1331 if(requires_resume_key) {
1335 srv_put_dos_date2(p,0,create_date);
1336 srv_put_dos_date2(p,4,adate);
1337 srv_put_dos_date2(p,8,mdate);
1338 SIVAL(p,12,(uint32)file_size);
1339 SIVAL(p,16,(uint32)allocation_size);
1343 p += align_string(pdata, p, 0);
1344 len = srvstr_push(base_data, flags2, p,
1345 fname, PTR_DIFF(end_data, p),
1347 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1349 SCVAL(nameptr, -1, len - 2);
1351 SCVAL(nameptr, -1, 0);
1355 SCVAL(nameptr, -1, len - 1);
1357 SCVAL(nameptr, -1, 0);
1363 case SMB_FIND_EA_SIZE:
1364 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1365 if(requires_resume_key) {
1369 srv_put_dos_date2(p,0,create_date);
1370 srv_put_dos_date2(p,4,adate);
1371 srv_put_dos_date2(p,8,mdate);
1372 SIVAL(p,12,(uint32)file_size);
1373 SIVAL(p,16,(uint32)allocation_size);
1376 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1377 SIVAL(p,22,ea_size); /* Extended attributes */
1381 len = srvstr_push(base_data, flags2,
1382 p, fname, PTR_DIFF(end_data, p),
1383 STR_TERMINATE | STR_NOALIGN);
1384 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1397 SCVAL(nameptr,0,len);
1399 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1402 case SMB_FIND_EA_LIST:
1404 struct ea_list *file_list = NULL;
1407 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1411 if(requires_resume_key) {
1415 srv_put_dos_date2(p,0,create_date);
1416 srv_put_dos_date2(p,4,adate);
1417 srv_put_dos_date2(p,8,mdate);
1418 SIVAL(p,12,(uint32)file_size);
1419 SIVAL(p,16,(uint32)allocation_size);
1421 p += 22; /* p now points to the EA area. */
1423 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1424 name_list = ea_list_union(name_list, file_list, &ea_len);
1426 /* We need to determine if this entry will fit in the space available. */
1427 /* Max string size is 255 bytes. */
1428 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1429 /* Move the dirptr back to prev_dirpos */
1430 dptr_SeekDir(conn->dirptr, prev_dirpos);
1431 *out_of_space = True;
1432 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1433 return False; /* Not finished - just out of space */
1436 /* Push the ea_data followed by the name. */
1437 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1439 len = srvstr_push(base_data, flags2,
1440 p + 1, fname, PTR_DIFF(end_data, p),
1441 STR_TERMINATE | STR_NOALIGN);
1442 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1455 SCVAL(nameptr,0,len);
1457 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1461 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1462 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1463 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1465 SIVAL(p,0,reskey); p += 4;
1466 put_long_date_timespec(p,create_date_ts); p += 8;
1467 put_long_date_timespec(p,adate_ts); p += 8;
1468 put_long_date_timespec(p,mdate_ts); p += 8;
1469 put_long_date_timespec(p,mdate_ts); p += 8;
1470 SOFF_T(p,0,file_size); p += 8;
1471 SOFF_T(p,0,allocation_size); p += 8;
1472 SIVAL(p,0,nt_extmode); p += 4;
1473 q = p; p += 4; /* q is placeholder for name length. */
1475 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1476 SIVAL(p,0,ea_size); /* Extended attributes */
1479 /* Clear the short name buffer. This is
1480 * IMPORTANT as not doing so will trigger
1481 * a Win2k client bug. JRA.
1483 if (!was_8_3 && check_mangled_names) {
1484 pstring mangled_name;
1485 pstrcpy(mangled_name, fname);
1486 mangle_map(mangled_name,True,True,
1488 mangled_name[12] = 0;
1489 len = srvstr_push(base_data, flags2,
1490 p+2, mangled_name, 24,
1491 STR_UPPER|STR_UNICODE);
1493 memset(p + 2 + len,'\0',24 - len);
1500 len = srvstr_push(base_data, flags2, p,
1501 fname, PTR_DIFF(end_data, p),
1502 STR_TERMINATE_ASCII);
1505 SIVAL(p,0,0); /* Ensure any padding is null. */
1506 len = PTR_DIFF(p, pdata);
1507 len = (len + 3) & ~3;
1512 case SMB_FIND_FILE_DIRECTORY_INFO:
1513 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1515 SIVAL(p,0,reskey); p += 4;
1516 put_long_date_timespec(p,create_date_ts); p += 8;
1517 put_long_date_timespec(p,adate_ts); p += 8;
1518 put_long_date_timespec(p,mdate_ts); p += 8;
1519 put_long_date_timespec(p,mdate_ts); p += 8;
1520 SOFF_T(p,0,file_size); p += 8;
1521 SOFF_T(p,0,allocation_size); p += 8;
1522 SIVAL(p,0,nt_extmode); p += 4;
1523 len = srvstr_push(base_data, flags2,
1524 p + 4, fname, PTR_DIFF(end_data, p),
1525 STR_TERMINATE_ASCII);
1528 SIVAL(p,0,0); /* Ensure any padding is null. */
1529 len = PTR_DIFF(p, pdata);
1530 len = (len + 3) & ~3;
1535 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1536 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1538 SIVAL(p,0,reskey); p += 4;
1539 put_long_date_timespec(p,create_date_ts); p += 8;
1540 put_long_date_timespec(p,adate_ts); p += 8;
1541 put_long_date_timespec(p,mdate_ts); p += 8;
1542 put_long_date_timespec(p,mdate_ts); p += 8;
1543 SOFF_T(p,0,file_size); p += 8;
1544 SOFF_T(p,0,allocation_size); p += 8;
1545 SIVAL(p,0,nt_extmode); p += 4;
1546 q = p; p += 4; /* q is placeholder for name length. */
1548 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1549 SIVAL(p,0,ea_size); /* Extended attributes */
1552 len = srvstr_push(base_data, flags2, p,
1553 fname, PTR_DIFF(end_data, p),
1554 STR_TERMINATE_ASCII);
1558 SIVAL(p,0,0); /* Ensure any padding is null. */
1559 len = PTR_DIFF(p, pdata);
1560 len = (len + 3) & ~3;
1565 case SMB_FIND_FILE_NAMES_INFO:
1566 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1568 SIVAL(p,0,reskey); p += 4;
1570 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1571 acl on a dir (tridge) */
1572 len = srvstr_push(base_data, flags2, p,
1573 fname, PTR_DIFF(end_data, p),
1574 STR_TERMINATE_ASCII);
1577 SIVAL(p,0,0); /* Ensure any padding is null. */
1578 len = PTR_DIFF(p, pdata);
1579 len = (len + 3) & ~3;
1584 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1585 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1587 SIVAL(p,0,reskey); p += 4;
1588 put_long_date_timespec(p,create_date_ts); p += 8;
1589 put_long_date_timespec(p,adate_ts); p += 8;
1590 put_long_date_timespec(p,mdate_ts); p += 8;
1591 put_long_date_timespec(p,mdate_ts); p += 8;
1592 SOFF_T(p,0,file_size); p += 8;
1593 SOFF_T(p,0,allocation_size); p += 8;
1594 SIVAL(p,0,nt_extmode); p += 4;
1595 q = p; p += 4; /* q is placeholder for name length. */
1597 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1598 SIVAL(p,0,ea_size); /* Extended attributes */
1601 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1602 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1603 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1604 len = srvstr_push(base_data, flags2, p,
1605 fname, PTR_DIFF(end_data, p),
1606 STR_TERMINATE_ASCII);
1609 SIVAL(p,0,0); /* Ensure any padding is null. */
1610 len = PTR_DIFF(p, pdata);
1611 len = (len + 3) & ~3;
1616 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1617 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1618 was_8_3 = mangle_is_8_3(fname, True, conn->params);
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 /* Clear the short name buffer. This is
1635 * IMPORTANT as not doing so will trigger
1636 * a Win2k client bug. JRA.
1638 if (!was_8_3 && check_mangled_names) {
1639 pstring mangled_name;
1640 pstrcpy(mangled_name, fname);
1641 mangle_map(mangled_name,True,True,
1643 mangled_name[12] = 0;
1644 len = srvstr_push(base_data, flags2,
1645 p+2, mangled_name, 24,
1646 STR_UPPER|STR_UNICODE);
1649 memset(p + 2 + len,'\0',24 - len);
1656 SSVAL(p,0,0); p += 2; /* Reserved ? */
1657 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1658 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1659 len = srvstr_push(base_data, flags2, p,
1660 fname, PTR_DIFF(end_data, p),
1661 STR_TERMINATE_ASCII);
1664 SIVAL(p,0,0); /* Ensure any padding is null. */
1665 len = PTR_DIFF(p, pdata);
1666 len = (len + 3) & ~3;
1671 /* CIFS UNIX Extension. */
1673 case SMB_FIND_FILE_UNIX:
1674 case SMB_FIND_FILE_UNIX_INFO2:
1676 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1678 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1680 if (info_level == SMB_FIND_FILE_UNIX) {
1681 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1682 p = store_file_unix_basic(conn, p,
1684 len = srvstr_push(base_data, flags2, p,
1685 fname, PTR_DIFF(end_data, p),
1688 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1689 p = store_file_unix_basic_info2(conn, p,
1693 len = srvstr_push(base_data, flags2, p, fname,
1694 PTR_DIFF(end_data, p), 0);
1695 SIVAL(nameptr, 0, len);
1699 SIVAL(p,0,0); /* Ensure any padding is null. */
1701 len = PTR_DIFF(p, pdata);
1702 len = (len + 3) & ~3;
1703 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1705 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1714 if (PTR_DIFF(p,pdata) > space_remaining) {
1715 /* Move the dirptr back to prev_dirpos */
1716 dptr_SeekDir(conn->dirptr, prev_dirpos);
1717 *out_of_space = True;
1718 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1719 return False; /* Not finished - just out of space */
1722 /* Setup the last entry pointer, as an offset from base_data */
1723 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1724 /* Advance the data pointer to the next slot */
1730 /****************************************************************************
1731 Reply to a TRANS2_FINDFIRST.
1732 ****************************************************************************/
1734 static void call_trans2findfirst(connection_struct *conn,
1735 struct smb_request *req,
1736 char **pparams, int total_params,
1737 char **ppdata, int total_data,
1738 unsigned int max_data_bytes)
1740 /* We must be careful here that we don't return more than the
1741 allowed number of data bytes. If this means returning fewer than
1742 maxentries then so be it. We assume that the redirector has
1743 enough room for the fixed number of parameter bytes it has
1745 char *params = *pparams;
1746 char *pdata = *ppdata;
1750 uint16 findfirst_flags;
1751 BOOL close_after_first;
1753 BOOL requires_resume_key;
1758 int last_entry_off=0;
1762 BOOL finished = False;
1763 BOOL dont_descend = False;
1764 BOOL out_of_space = False;
1765 int space_remaining;
1766 BOOL mask_contains_wcard = False;
1767 SMB_STRUCT_STAT sbuf;
1768 TALLOC_CTX *ea_ctx = NULL;
1769 struct ea_list *ea_list = NULL;
1770 NTSTATUS ntstatus = NT_STATUS_OK;
1772 if (total_params < 13) {
1773 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1777 dirtype = SVAL(params,0);
1778 maxentries = SVAL(params,2);
1779 findfirst_flags = SVAL(params,4);
1780 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1781 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1782 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1783 info_level = SVAL(params,6);
1785 *directory = *mask = 0;
1787 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1788 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1789 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1790 info_level, max_data_bytes));
1793 /* W2K3 seems to treat zero as 1. */
1797 switch (info_level) {
1798 case SMB_FIND_INFO_STANDARD:
1799 case SMB_FIND_EA_SIZE:
1800 case SMB_FIND_EA_LIST:
1801 case SMB_FIND_FILE_DIRECTORY_INFO:
1802 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1803 case SMB_FIND_FILE_NAMES_INFO:
1804 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1805 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1806 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1808 case SMB_FIND_FILE_UNIX:
1809 case SMB_FIND_FILE_UNIX_INFO2:
1810 if (!lp_unix_extensions()) {
1811 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1816 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1820 srvstr_get_path_wcard(params, req->flags2, directory,
1821 params+12, sizeof(directory), total_params - 12,
1822 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1823 if (!NT_STATUS_IS_OK(ntstatus)) {
1824 reply_nterror(req, ntstatus);
1828 ntstatus = resolve_dfspath_wcard(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1829 if (!NT_STATUS_IS_OK(ntstatus)) {
1830 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1831 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1832 ERRSRV, ERRbadpath);
1835 reply_nterror(req, ntstatus);
1839 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1840 if (!NT_STATUS_IS_OK(ntstatus)) {
1841 reply_nterror(req, ntstatus);
1844 ntstatus = check_name(conn, directory);
1845 if (!NT_STATUS_IS_OK(ntstatus)) {
1846 reply_nterror(req, ntstatus);
1850 p = strrchr_m(directory,'/');
1852 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1853 if((directory[0] == '.') && (directory[1] == '\0')) {
1855 mask_contains_wcard = True;
1857 pstrcpy(mask,directory);
1859 pstrcpy(directory,"./");
1865 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1867 if (info_level == SMB_FIND_EA_LIST) {
1870 if (total_data < 4) {
1871 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1875 ea_size = IVAL(pdata,0);
1876 if (ea_size != total_data) {
1877 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1878 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1879 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1883 if (!lp_ea_support(SNUM(conn))) {
1884 reply_doserror(req, ERRDOS, ERReasnotsupported);
1888 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1889 reply_nterror(req, NT_STATUS_NO_MEMORY);
1893 /* Pull out the list of names. */
1894 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1896 talloc_destroy(ea_ctx);
1897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1902 *ppdata = (char *)SMB_REALLOC(
1903 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1904 if(*ppdata == NULL ) {
1905 talloc_destroy(ea_ctx);
1906 reply_nterror(req, NT_STATUS_NO_MEMORY);
1910 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1912 /* Realloc the params space */
1913 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1914 if (*pparams == NULL) {
1915 talloc_destroy(ea_ctx);
1916 reply_nterror(req, NT_STATUS_NO_MEMORY);
1921 /* Save the wildcard match and attribs we are using on this directory -
1922 needed as lanman2 assumes these are being saved between calls */
1924 ntstatus = dptr_create(conn,
1930 mask_contains_wcard,
1934 if (!NT_STATUS_IS_OK(ntstatus)) {
1935 talloc_destroy(ea_ctx);
1936 reply_nterror(req, ntstatus);
1940 dptr_num = dptr_dnum(conn->dirptr);
1941 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1943 /* We don't need to check for VOL here as this is returned by
1944 a different TRANS2 call. */
1946 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1947 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1948 dont_descend = True;
1951 space_remaining = max_data_bytes;
1952 out_of_space = False;
1954 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1955 BOOL got_exact_match = False;
1957 /* this is a heuristic to avoid seeking the dirptr except when
1958 absolutely necessary. It allows for a filename of about 40 chars */
1959 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1960 out_of_space = True;
1963 finished = !get_lanman2_dir_entry(conn,
1965 mask,dirtype,info_level,
1966 requires_resume_key,dont_descend,
1968 space_remaining, &out_of_space,
1970 &last_entry_off, ea_list, ea_ctx);
1973 if (finished && out_of_space)
1976 if (!finished && !out_of_space)
1980 * As an optimisation if we know we aren't looking
1981 * for a wildcard name (ie. the name matches the wildcard exactly)
1982 * then we can finish on any (first) match.
1983 * This speeds up large directory searches. JRA.
1989 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1992 talloc_destroy(ea_ctx);
1994 /* Check if we can close the dirptr */
1995 if(close_after_first || (finished && close_if_end)) {
1996 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1997 dptr_close(&dptr_num);
2001 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2002 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2003 * the protocol level is less than NT1. Tested with smbclient. JRA.
2004 * This should fix the OS/2 client bug #2335.
2007 if(numentries == 0) {
2008 dptr_close(&dptr_num);
2009 if (Protocol < PROTOCOL_NT1) {
2010 reply_doserror(req, ERRDOS, ERRnofiles);
2013 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2014 ERRDOS, ERRbadfile);
2019 /* At this point pdata points to numentries directory entries. */
2021 /* Set up the return parameter block */
2022 SSVAL(params,0,dptr_num);
2023 SSVAL(params,2,numentries);
2024 SSVAL(params,4,finished);
2025 SSVAL(params,6,0); /* Never an EA error */
2026 SSVAL(params,8,last_entry_off);
2028 send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
2031 if ((! *directory) && dptr_path(dptr_num))
2032 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2034 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2035 smb_fn_name(CVAL(req->inbuf,smb_com)),
2036 mask, directory, dirtype, numentries ) );
2039 * Force a name mangle here to ensure that the
2040 * mask as an 8.3 name is top of the mangled cache.
2041 * The reasons for this are subtle. Don't remove
2042 * this code unless you know what you are doing
2043 * (see PR#13758). JRA.
2046 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
2047 mangle_map(mask, True, True, conn->params);
2052 /****************************************************************************
2053 Reply to a TRANS2_FINDNEXT.
2054 ****************************************************************************/
2056 static void call_trans2findnext(connection_struct *conn,
2057 struct smb_request *req,
2058 char **pparams, int total_params,
2059 char **ppdata, int total_data,
2060 unsigned int max_data_bytes)
2062 /* We must be careful here that we don't return more than the
2063 allowed number of data bytes. If this means returning fewer than
2064 maxentries then so be it. We assume that the redirector has
2065 enough room for the fixed number of parameter bytes it has
2067 char *params = *pparams;
2068 char *pdata = *ppdata;
2074 uint16 findnext_flags;
2075 BOOL close_after_request;
2077 BOOL requires_resume_key;
2079 BOOL mask_contains_wcard = False;
2080 pstring resume_name;
2086 int i, last_entry_off=0;
2087 BOOL finished = False;
2088 BOOL dont_descend = False;
2089 BOOL out_of_space = False;
2090 int space_remaining;
2091 TALLOC_CTX *ea_ctx = NULL;
2092 struct ea_list *ea_list = NULL;
2093 NTSTATUS ntstatus = NT_STATUS_OK;
2095 if (total_params < 13) {
2096 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2100 dptr_num = SVAL(params,0);
2101 maxentries = SVAL(params,2);
2102 info_level = SVAL(params,4);
2103 resume_key = IVAL(params,6);
2104 findnext_flags = SVAL(params,10);
2105 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2106 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2107 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2108 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2110 *mask = *directory = *resume_name = 0;
2112 srvstr_get_path_wcard(params, req->flags2, resume_name,
2113 params+12, sizeof(resume_name),
2114 total_params - 12, STR_TERMINATE, &ntstatus,
2115 &mask_contains_wcard);
2116 if (!NT_STATUS_IS_OK(ntstatus)) {
2117 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2118 complain (it thinks we're asking for the directory above the shared
2119 path or an invalid name). Catch this as the resume name is only compared, never used in
2120 a file access. JRA. */
2121 srvstr_pull(params, req->flags2,
2122 resume_name, params+12,
2123 sizeof(resume_name), total_params - 12,
2126 if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2127 reply_nterror(req, ntstatus);
2132 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2133 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2134 resume_key = %d resume name = %s continue=%d level = %d\n",
2135 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2136 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2139 /* W2K3 seems to treat zero as 1. */
2143 switch (info_level) {
2144 case SMB_FIND_INFO_STANDARD:
2145 case SMB_FIND_EA_SIZE:
2146 case SMB_FIND_EA_LIST:
2147 case SMB_FIND_FILE_DIRECTORY_INFO:
2148 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2149 case SMB_FIND_FILE_NAMES_INFO:
2150 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2151 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2152 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2154 case SMB_FIND_FILE_UNIX:
2155 case SMB_FIND_FILE_UNIX_INFO2:
2156 if (!lp_unix_extensions()) {
2157 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2162 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2166 if (info_level == SMB_FIND_EA_LIST) {
2169 if (total_data < 4) {
2170 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2174 ea_size = IVAL(pdata,0);
2175 if (ea_size != total_data) {
2176 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2177 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2178 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2182 if (!lp_ea_support(SNUM(conn))) {
2183 reply_doserror(req, ERRDOS, ERReasnotsupported);
2187 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2188 reply_nterror(req, NT_STATUS_NO_MEMORY);
2192 /* Pull out the list of names. */
2193 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2195 talloc_destroy(ea_ctx);
2196 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2201 *ppdata = (char *)SMB_REALLOC(
2202 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2203 if(*ppdata == NULL) {
2204 talloc_destroy(ea_ctx);
2205 reply_nterror(req, NT_STATUS_NO_MEMORY);
2210 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2212 /* Realloc the params space */
2213 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2214 if(*pparams == NULL ) {
2215 talloc_destroy(ea_ctx);
2216 reply_nterror(req, NT_STATUS_NO_MEMORY);
2222 /* Check that the dptr is valid */
2223 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2224 talloc_destroy(ea_ctx);
2225 reply_doserror(req, ERRDOS, ERRnofiles);
2229 string_set(&conn->dirpath,dptr_path(dptr_num));
2231 /* Get the wildcard mask from the dptr */
2232 if((p = dptr_wcard(dptr_num))== NULL) {
2233 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2234 talloc_destroy(ea_ctx);
2235 reply_doserror(req, ERRDOS, ERRnofiles);
2240 pstrcpy(directory,conn->dirpath);
2242 /* Get the attr mask from the dptr */
2243 dirtype = dptr_attr(dptr_num);
2245 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2246 dptr_num, mask, dirtype,
2248 dptr_TellDir(conn->dirptr)));
2250 /* We don't need to check for VOL here as this is returned by
2251 a different TRANS2 call. */
2253 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2254 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2255 dont_descend = True;
2258 space_remaining = max_data_bytes;
2259 out_of_space = False;
2262 * Seek to the correct position. We no longer use the resume key but
2263 * depend on the last file name instead.
2266 if(*resume_name && !continue_bit) {
2269 long current_pos = 0;
2271 * Remember, mangle_map is called by
2272 * get_lanman2_dir_entry(), so the resume name
2273 * could be mangled. Ensure we check the unmangled name.
2276 if (mangle_is_mangled(resume_name, conn->params)) {
2277 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2282 * Fix for NT redirector problem triggered by resume key indexes
2283 * changing between directory scans. We now return a resume key of 0
2284 * and instead look for the filename to continue from (also given
2285 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2286 * findfirst/findnext (as is usual) then the directory pointer
2287 * should already be at the correct place.
2290 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2291 } /* end if resume_name && !continue_bit */
2293 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2294 BOOL got_exact_match = False;
2296 /* this is a heuristic to avoid seeking the dirptr except when
2297 absolutely necessary. It allows for a filename of about 40 chars */
2298 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2299 out_of_space = True;
2302 finished = !get_lanman2_dir_entry(conn,
2304 mask,dirtype,info_level,
2305 requires_resume_key,dont_descend,
2307 space_remaining, &out_of_space,
2309 &last_entry_off, ea_list, ea_ctx);
2312 if (finished && out_of_space)
2315 if (!finished && !out_of_space)
2319 * As an optimisation if we know we aren't looking
2320 * for a wildcard name (ie. the name matches the wildcard exactly)
2321 * then we can finish on any (first) match.
2322 * This speeds up large directory searches. JRA.
2328 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2331 talloc_destroy(ea_ctx);
2333 /* Check if we can close the dirptr */
2334 if(close_after_request || (finished && close_if_end)) {
2335 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2336 dptr_close(&dptr_num); /* This frees up the saved mask */
2339 /* Set up the return parameter block */
2340 SSVAL(params,0,numentries);
2341 SSVAL(params,2,finished);
2342 SSVAL(params,4,0); /* Never an EA error */
2343 SSVAL(params,6,last_entry_off);
2345 send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata),
2348 if ((! *directory) && dptr_path(dptr_num))
2349 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2351 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2352 smb_fn_name(CVAL(req->inbuf,smb_com)),
2353 mask, directory, dirtype, numentries ) );
2358 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2360 E_md4hash(lp_servicename(SNUM(conn)),objid);
2364 /****************************************************************************
2365 Reply to a TRANS2_QFSINFO (query filesystem info).
2366 ****************************************************************************/
2368 static void call_trans2qfsinfo(connection_struct *conn,
2369 struct smb_request *req,
2370 char **pparams, int total_params,
2371 char **ppdata, int total_data,
2372 unsigned int max_data_bytes)
2374 char *pdata, *end_data;
2375 char *params = *pparams;
2379 const char *vname = volume_label(SNUM(conn));
2380 int snum = SNUM(conn);
2381 char *fstype = lp_fstype(SNUM(conn));
2384 if (total_params < 2) {
2385 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2389 info_level = SVAL(params,0);
2391 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2393 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2394 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2395 reply_doserror(req, ERRSRV, ERRinvdevice);
2399 *ppdata = (char *)SMB_REALLOC(
2400 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2401 if (*ppdata == NULL ) {
2402 reply_nterror(req, NT_STATUS_NO_MEMORY);
2407 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2408 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2410 switch (info_level) {
2411 case SMB_INFO_ALLOCATION:
2413 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2415 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2416 reply_unixerror(req, ERRHRD, ERRgeneral);
2420 block_size = lp_block_size(snum);
2421 if (bsize < block_size) {
2422 SMB_BIG_UINT factor = block_size/bsize;
2427 if (bsize > block_size) {
2428 SMB_BIG_UINT factor = bsize/block_size;
2433 bytes_per_sector = 512;
2434 sectors_per_unit = bsize/bytes_per_sector;
2436 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2437 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2438 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2440 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2441 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2442 SIVAL(pdata,l1_cUnit,dsize);
2443 SIVAL(pdata,l1_cUnitAvail,dfree);
2444 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2448 case SMB_INFO_VOLUME:
2449 /* Return volume name */
2451 * Add volume serial number - hash of a combination of
2452 * the called hostname and the service name.
2454 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2456 * Win2k3 and previous mess this up by sending a name length
2457 * one byte short. I believe only older clients (OS/2 Win9x) use
2458 * this call so try fixing this by adding a terminating null to
2459 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2463 pdata+l2_vol_szVolLabel, vname,
2464 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2465 STR_NOALIGN|STR_TERMINATE);
2466 SCVAL(pdata,l2_vol_cch,len);
2467 data_len = l2_vol_szVolLabel + len;
2468 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2469 (unsigned)st.st_ctime, len, vname));
2472 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2473 case SMB_FS_ATTRIBUTE_INFORMATION:
2476 #if defined(HAVE_SYS_QUOTAS)
2477 quota_flag = FILE_VOLUME_QUOTAS;
2480 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2481 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2482 FILE_SUPPORTS_OBJECT_IDS|
2483 FILE_UNICODE_ON_DISK|
2484 quota_flag); /* FS ATTRIBUTES */
2486 SIVAL(pdata,4,255); /* Max filename component length */
2487 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2488 and will think we can't do long filenames */
2489 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2490 PTR_DIFF(end_data, pdata+12),
2493 data_len = 12 + len;
2496 case SMB_QUERY_FS_LABEL_INFO:
2497 case SMB_FS_LABEL_INFORMATION:
2498 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2499 PTR_DIFF(end_data, pdata+4), 0);
2504 case SMB_QUERY_FS_VOLUME_INFO:
2505 case SMB_FS_VOLUME_INFORMATION:
2508 * Add volume serial number - hash of a combination of
2509 * the called hostname and the service name.
2511 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2512 (str_checksum(get_local_machine_name())<<16));
2514 /* Max label len is 32 characters. */
2515 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2516 PTR_DIFF(end_data, pdata+18),
2518 SIVAL(pdata,12,len);
2521 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2522 (int)strlen(vname),vname, lp_servicename(snum)));
2525 case SMB_QUERY_FS_SIZE_INFO:
2526 case SMB_FS_SIZE_INFORMATION:
2528 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2530 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2531 reply_unixerror(req, ERRHRD, ERRgeneral);
2534 block_size = lp_block_size(snum);
2535 if (bsize < block_size) {
2536 SMB_BIG_UINT factor = block_size/bsize;
2541 if (bsize > block_size) {
2542 SMB_BIG_UINT factor = bsize/block_size;
2547 bytes_per_sector = 512;
2548 sectors_per_unit = bsize/bytes_per_sector;
2549 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2550 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2551 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2552 SBIG_UINT(pdata,0,dsize);
2553 SBIG_UINT(pdata,8,dfree);
2554 SIVAL(pdata,16,sectors_per_unit);
2555 SIVAL(pdata,20,bytes_per_sector);
2559 case SMB_FS_FULL_SIZE_INFORMATION:
2561 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2563 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2564 reply_unixerror(req, ERRHRD, ERRgeneral);
2567 block_size = lp_block_size(snum);
2568 if (bsize < block_size) {
2569 SMB_BIG_UINT factor = block_size/bsize;
2574 if (bsize > block_size) {
2575 SMB_BIG_UINT factor = bsize/block_size;
2580 bytes_per_sector = 512;
2581 sectors_per_unit = bsize/bytes_per_sector;
2582 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2583 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2584 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2585 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2586 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2587 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2588 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2589 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2593 case SMB_QUERY_FS_DEVICE_INFO:
2594 case SMB_FS_DEVICE_INFORMATION:
2596 SIVAL(pdata,0,0); /* dev type */
2597 SIVAL(pdata,4,0); /* characteristics */
2600 #ifdef HAVE_SYS_QUOTAS
2601 case SMB_FS_QUOTA_INFORMATION:
2603 * what we have to send --metze:
2605 * Unknown1: 24 NULL bytes
2606 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2607 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2608 * Quota Flags: 2 byte :
2609 * Unknown3: 6 NULL bytes
2613 * details for Quota Flags:
2615 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2616 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2617 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2618 * 0x0001 Enable Quotas: enable quota for this fs
2622 /* we need to fake up a fsp here,
2623 * because its not send in this call
2626 SMB_NTQUOTA_STRUCT quotas;
2629 ZERO_STRUCT(quotas);
2635 if (current_user.ut.uid != 0) {
2636 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2637 lp_servicename(SNUM(conn)),conn->user));
2638 reply_doserror(req, ERRDOS, ERRnoaccess);
2642 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2643 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2644 reply_doserror(req, ERRSRV, ERRerror);
2650 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2652 /* Unknown1 24 NULL bytes*/
2653 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2654 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2655 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2657 /* Default Soft Quota 8 bytes */
2658 SBIG_UINT(pdata,24,quotas.softlim);
2660 /* Default Hard Quota 8 bytes */
2661 SBIG_UINT(pdata,32,quotas.hardlim);
2663 /* Quota flag 2 bytes */
2664 SSVAL(pdata,40,quotas.qflags);
2666 /* Unknown3 6 NULL bytes */
2672 #endif /* HAVE_SYS_QUOTAS */
2673 case SMB_FS_OBJECTID_INFORMATION:
2675 unsigned char objid[16];
2676 memcpy(pdata,create_volume_objectid(conn, objid),16);
2682 * Query the version and capabilities of the CIFS UNIX extensions
2686 case SMB_QUERY_CIFS_UNIX_INFO:
2687 if (!lp_unix_extensions()) {
2688 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2692 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2693 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2694 /* We have POSIX ACLs, pathname and locking capability. */
2695 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2696 CIFS_UNIX_POSIX_ACLS_CAP|
2697 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2698 CIFS_UNIX_FCNTL_LOCKS_CAP|
2699 CIFS_UNIX_EXTATTR_CAP|
2700 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2701 /* Ensure we don't do this on signed or sealed data. */
2702 (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2706 case SMB_QUERY_POSIX_FS_INFO:
2709 vfs_statvfs_struct svfs;
2711 if (!lp_unix_extensions()) {
2712 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2716 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2720 SIVAL(pdata,0,svfs.OptimalTransferSize);
2721 SIVAL(pdata,4,svfs.BlockSize);
2722 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2723 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2724 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2725 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2726 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2727 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2728 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2730 } else if (rc == EOPNOTSUPP) {
2731 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2733 #endif /* EOPNOTSUPP */
2735 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2736 reply_doserror(req, ERRSRV, ERRerror);
2742 case SMB_QUERY_POSIX_WHOAMI:
2748 if (!lp_unix_extensions()) {
2749 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2753 if (max_data_bytes < 40) {
2754 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2758 /* We ARE guest if global_sid_Builtin_Guests is
2759 * in our list of SIDs.
2761 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2762 current_user.nt_user_token)) {
2763 flags |= SMB_WHOAMI_GUEST;
2766 /* We are NOT guest if global_sid_Authenticated_Users
2767 * is in our list of SIDs.
2769 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2770 current_user.nt_user_token)) {
2771 flags &= ~SMB_WHOAMI_GUEST;
2774 /* NOTE: 8 bytes for UID/GID, irrespective of native
2775 * platform size. This matches
2776 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2778 data_len = 4 /* flags */
2785 + 4 /* pad/reserved */
2786 + (current_user.ut.ngroups * 8)
2788 + (current_user.nt_user_token->num_sids *
2792 SIVAL(pdata, 0, flags);
2793 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2794 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2795 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2798 if (data_len >= max_data_bytes) {
2799 /* Potential overflow, skip the GIDs and SIDs. */
2801 SIVAL(pdata, 24, 0); /* num_groups */
2802 SIVAL(pdata, 28, 0); /* num_sids */
2803 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2804 SIVAL(pdata, 36, 0); /* reserved */
2810 SIVAL(pdata, 24, current_user.ut.ngroups);
2812 current_user.nt_user_token->num_sids);
2814 /* We walk the SID list twice, but this call is fairly
2815 * infrequent, and I don't expect that it's performance
2816 * sensitive -- jpeach
2818 for (i = 0, sid_bytes = 0;
2819 i < current_user.nt_user_token->num_sids; ++i) {
2821 sid_size(¤t_user.nt_user_token->user_sids[i]);
2824 /* SID list byte count */
2825 SIVAL(pdata, 32, sid_bytes);
2827 /* 4 bytes pad/reserved - must be zero */
2828 SIVAL(pdata, 36, 0);
2832 for (i = 0; i < current_user.ut.ngroups; ++i) {
2833 SBIG_UINT(pdata, data_len,
2834 (SMB_BIG_UINT)current_user.ut.groups[i]);
2840 i < current_user.nt_user_token->num_sids; ++i) {
2842 sid_size(¤t_user.nt_user_token->user_sids[i]);
2844 sid_linearize(pdata + data_len, sid_len,
2845 ¤t_user.nt_user_token->user_sids[i]);
2846 data_len += sid_len;
2852 case SMB_MAC_QUERY_FS_INFO:
2854 * Thursby MAC extension... ONLY on NTFS filesystems
2855 * once we do streams then we don't need this
2857 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2859 SIVAL(pdata,84,0x100); /* Don't support mac... */
2864 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2869 send_trans2_replies(req, params, 0, pdata, data_len,
2872 DEBUG( 4, ( "%s info_level = %d\n",
2873 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2878 /****************************************************************************
2879 Reply to a TRANS2_SETFSINFO (set filesystem info).
2880 ****************************************************************************/
2882 static void call_trans2setfsinfo(connection_struct *conn,
2883 struct smb_request *req,
2884 char **pparams, int total_params,
2885 char **ppdata, int total_data,
2886 unsigned int max_data_bytes)
2888 char *pdata = *ppdata;
2889 char *params = *pparams;
2892 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2895 if (total_params < 4) {
2896 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2902 info_level = SVAL(params,2);
2904 switch(info_level) {
2905 case SMB_SET_CIFS_UNIX_INFO:
2907 uint16 client_unix_major;
2908 uint16 client_unix_minor;
2909 uint32 client_unix_cap_low;
2910 uint32 client_unix_cap_high;
2912 if (!lp_unix_extensions()) {
2914 NT_STATUS_INVALID_LEVEL);
2918 /* There should be 12 bytes of capabilities set. */
2919 if (total_data < 8) {
2922 NT_STATUS_INVALID_PARAMETER);
2925 client_unix_major = SVAL(pdata,0);
2926 client_unix_minor = SVAL(pdata,2);
2927 client_unix_cap_low = IVAL(pdata,4);
2928 client_unix_cap_high = IVAL(pdata,8);
2929 /* Just print these values for now. */
2930 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2931 cap_low = 0x%x, cap_high = 0x%x\n",
2932 (unsigned int)client_unix_major,
2933 (unsigned int)client_unix_minor,
2934 (unsigned int)client_unix_cap_low,
2935 (unsigned int)client_unix_cap_high ));
2937 /* Here is where we must switch to posix pathname processing... */
2938 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2939 lp_set_posix_pathnames();
2940 mangle_change_to_posix();
2943 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2944 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2945 /* Client that knows how to do posix locks,
2946 * but not posix open/mkdir operations. Set a
2947 * default type for read/write checks. */
2949 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2954 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2957 size_t param_len = 0;
2958 size_t data_len = total_data;
2960 if (!lp_unix_extensions()) {
2962 req, NT_STATUS_INVALID_LEVEL);
2966 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2968 status = srv_request_encryption_setup(conn,
2969 (unsigned char **)ppdata,
2971 (unsigned char **)pparams,
2975 if (!NT_STATUS_IS_OK(status)) {
2978 * MORE_PROCESSING_REQUIRED, this used
2979 * to have special handling here.
2981 reply_nterror(req, status);
2985 send_trans2_replies(req,
2986 *pparams, param_len,
2990 if (NT_STATUS_IS_OK(status)) {
2991 /* Server-side transport encryption is now *on*. */
2992 status = srv_encryption_start(conn);
2993 if (!NT_STATUS_IS_OK(status)) {
2994 exit_server_cleanly("Failure in setting up encrypted transport");
2999 case SMB_FS_QUOTA_INFORMATION:
3001 files_struct *fsp = NULL;
3002 SMB_NTQUOTA_STRUCT quotas;
3004 ZERO_STRUCT(quotas);
3007 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3008 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3009 lp_servicename(SNUM(conn)),conn->user));
3010 reply_doserror(req, ERRSRV, ERRaccess);
3014 /* note: normaly there're 48 bytes,
3015 * but we didn't use the last 6 bytes for now
3018 fsp = file_fsp(SVAL(params,0));
3019 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3020 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3022 req, NT_STATUS_INVALID_HANDLE);
3026 if (total_data < 42) {
3027 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3031 NT_STATUS_INVALID_PARAMETER);
3035 /* unknown_1 24 NULL bytes in pdata*/
3037 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3038 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3039 #ifdef LARGE_SMB_OFF_T
3040 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3041 #else /* LARGE_SMB_OFF_T */
3042 if ((IVAL(pdata,28) != 0)&&
3043 ((quotas.softlim != 0xFFFFFFFF)||
3044 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3045 /* more than 32 bits? */
3048 NT_STATUS_INVALID_PARAMETER);
3051 #endif /* LARGE_SMB_OFF_T */
3053 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3054 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3055 #ifdef LARGE_SMB_OFF_T
3056 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3057 #else /* LARGE_SMB_OFF_T */
3058 if ((IVAL(pdata,36) != 0)&&
3059 ((quotas.hardlim != 0xFFFFFFFF)||
3060 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3061 /* more than 32 bits? */
3064 NT_STATUS_INVALID_PARAMETER);
3067 #endif /* LARGE_SMB_OFF_T */
3069 /* quota_flags 2 bytes **/
3070 quotas.qflags = SVAL(pdata,40);
3072 /* unknown_2 6 NULL bytes follow*/
3074 /* now set the quotas */
3075 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3076 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3077 reply_doserror(req, ERRSRV, ERRerror);
3084 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3086 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3092 * sending this reply works fine,
3093 * but I'm not sure it's the same
3094 * like windows do...
3097 reply_outbuf(req, 10, 0);
3100 #if defined(HAVE_POSIX_ACLS)
3101 /****************************************************************************
3102 Utility function to count the number of entries in a POSIX acl.
3103 ****************************************************************************/
3105 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3107 unsigned int ace_count = 0;
3108 int entry_id = SMB_ACL_FIRST_ENTRY;
3109 SMB_ACL_ENTRY_T entry;
3111 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3113 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3114 entry_id = SMB_ACL_NEXT_ENTRY;
3121 /****************************************************************************
3122 Utility function to marshall a POSIX acl into wire format.
3123 ****************************************************************************/
3125 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3127 int entry_id = SMB_ACL_FIRST_ENTRY;
3128 SMB_ACL_ENTRY_T entry;
3130 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3131 SMB_ACL_TAG_T tagtype;
3132 SMB_ACL_PERMSET_T permset;
3133 unsigned char perms = 0;
3134 unsigned int own_grp;
3137 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3138 entry_id = SMB_ACL_NEXT_ENTRY;
3141 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3142 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3146 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3147 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3151 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3152 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3153 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3155 SCVAL(pdata,1,perms);
3158 case SMB_ACL_USER_OBJ:
3159 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3160 own_grp = (unsigned int)pst->st_uid;
3161 SIVAL(pdata,2,own_grp);
3166 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3168 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3171 own_grp = (unsigned int)*puid;
3172 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3173 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3174 SIVAL(pdata,2,own_grp);
3178 case SMB_ACL_GROUP_OBJ:
3179 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3180 own_grp = (unsigned int)pst->st_gid;
3181 SIVAL(pdata,2,own_grp);
3186 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3188 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3191 own_grp = (unsigned int)*pgid;
3192 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3193 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3194 SIVAL(pdata,2,own_grp);
3199 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3200 SIVAL(pdata,2,0xFFFFFFFF);
3201 SIVAL(pdata,6,0xFFFFFFFF);
3204 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3205 SIVAL(pdata,2,0xFFFFFFFF);
3206 SIVAL(pdata,6,0xFFFFFFFF);
3209 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3212 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3219 /****************************************************************************
3220 Store the FILE_UNIX_BASIC info.
3221 ****************************************************************************/
3223 static char *store_file_unix_basic(connection_struct *conn,
3226 const SMB_STRUCT_STAT *psbuf)
3228 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3229 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3231 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3234 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3237 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3238 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3239 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3242 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3246 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3250 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3253 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3257 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3261 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3264 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3268 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3275 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3276 * the chflags(2) (or equivalent) flags.
3278 * XXX: this really should be behind the VFS interface. To do this, we would
3279 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3280 * Each VFS module could then implement it's own mapping as appropriate for the
3281 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3283 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3287 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3291 { UF_IMMUTABLE, EXT_IMMUTABLE },
3295 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3299 { UF_HIDDEN, EXT_HIDDEN },
3302 /* Do not remove. We need to guarantee that this array has at least one
3303 * entry to build on HP-UX.
3309 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3310 uint32 *smb_fflags, uint32 *smb_fmask)
3312 #ifdef HAVE_STAT_ST_FLAGS
3315 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3316 *smb_fmask |= info2_flags_map[i].smb_fflag;
3317 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3318 *smb_fflags |= info2_flags_map[i].smb_fflag;
3321 #endif /* HAVE_STAT_ST_FLAGS */
3324 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3325 const uint32 smb_fflags,
3326 const uint32 smb_fmask,
3329 #ifdef HAVE_STAT_ST_FLAGS
3330 uint32 max_fmask = 0;
3333 *stat_fflags = psbuf->st_flags;
3335 /* For each flags requested in smb_fmask, check the state of the
3336 * corresponding flag in smb_fflags and set or clear the matching
3340 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3341 max_fmask |= info2_flags_map[i].smb_fflag;
3342 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3343 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3344 *stat_fflags |= info2_flags_map[i].stat_fflag;
3346 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3351 /* If smb_fmask is asking to set any bits that are not supported by
3352 * our flag mappings, we should fail.
3354 if ((smb_fmask & max_fmask) != smb_fmask) {
3361 #endif /* HAVE_STAT_ST_FLAGS */
3365 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3366 * of file flags and birth (create) time.
3368 static char *store_file_unix_basic_info2(connection_struct *conn,
3371 const SMB_STRUCT_STAT *psbuf)
3373 uint32 file_flags = 0;
3374 uint32 flags_mask = 0;
3376 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3378 /* Create (birth) time 64 bit */
3379 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3382 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3383 SIVAL(pdata, 0, file_flags); /* flags */
3384 SIVAL(pdata, 4, flags_mask); /* mask */
3390 /****************************************************************************
3391 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3392 ****************************************************************************/
3394 static void call_trans2qpipeinfo(connection_struct *conn,
3395 struct smb_request *req,
3396 unsigned int tran_call,
3397 char **pparams, int total_params,
3398 char **ppdata, int total_data,
3399 unsigned int max_data_bytes)
3401 char *params = *pparams;
3402 char *pdata = *ppdata;
3403 unsigned int data_size = 0;
3404 unsigned int param_size = 2;
3406 smb_np_struct *p_pipe = NULL;
3409 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3413 if (total_params < 4) {
3414 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3418 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3419 if (p_pipe == NULL) {
3420 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3424 info_level = SVAL(params,2);
3426 *pparams = (char *)SMB_REALLOC(*pparams,2);
3427 if (*pparams == NULL) {
3428 reply_nterror(req, NT_STATUS_NO_MEMORY);
3433 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3434 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3435 if (*ppdata == NULL ) {
3436 reply_nterror(req, NT_STATUS_NO_MEMORY);
3441 switch (info_level) {
3442 case SMB_FILE_STANDARD_INFORMATION:
3444 SOFF_T(pdata,0,4096LL);
3451 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3455 send_trans2_replies(req, params, param_size, *ppdata, data_size,
3461 /****************************************************************************
3462 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3463 file name or file id).
3464 ****************************************************************************/
3466 static void call_trans2qfilepathinfo(connection_struct *conn,
3467 struct smb_request *req,
3468 unsigned int tran_call,
3469 char **pparams, int total_params,
3470 char **ppdata, int total_data,
3471 unsigned int max_data_bytes)
3473 char *params = *pparams;
3474 char *pdata = *ppdata;
3475 char *dstart, *dend;
3479 SMB_OFF_T file_size=0;
3480 SMB_BIG_UINT allocation_size=0;
3481 unsigned int data_size = 0;
3482 unsigned int param_size = 2;
3483 SMB_STRUCT_STAT sbuf;
3484 pstring fname, dos_fname;
3489 BOOL delete_pending = False;
3491 time_t create_time, mtime, atime;
3492 struct timespec create_time_ts, mtime_ts, atime_ts;
3493 files_struct *fsp = NULL;
3494 struct file_id fileid;
3495 TALLOC_CTX *data_ctx = NULL;
3496 struct ea_list *ea_list = NULL;
3497 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3498 char *lock_data = NULL;
3501 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3507 if (tran_call == TRANSACT2_QFILEINFO) {
3508 if (total_params < 4) {
3509 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3514 call_trans2qpipeinfo(conn, req, tran_call,
3515 pparams, total_params,
3521 fsp = file_fsp(SVAL(params,0));
3522 info_level = SVAL(params,2);
3524 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3526 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3527 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3531 if(fsp && (fsp->fake_file_handle)) {
3533 * This is actually for the QUOTA_FAKE_FILE --metze
3536 pstrcpy(fname, fsp->fsp_name);
3537 /* We know this name is ok, it's already passed the checks. */
3539 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3541 * This is actually a QFILEINFO on a directory
3542 * handle (returned from an NT SMB). NT5.0 seems
3543 * to do this call. JRA.
3545 /* We know this name is ok, it's already passed the checks. */
3546 pstrcpy(fname, fsp->fsp_name);
3548 if (INFO_LEVEL_IS_UNIX(info_level)) {
3549 /* Always do lstat for UNIX calls. */
3550 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3551 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3552 reply_unixerror(req,ERRDOS,ERRbadpath);
3555 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3556 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3557 reply_unixerror(req, ERRDOS, ERRbadpath);
3561 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3562 delete_pending = get_delete_on_close_flag(fileid);
3565 * Original code - this is an open file.
3567 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3571 pstrcpy(fname, fsp->fsp_name);
3572 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3573 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3574 reply_unixerror(req, ERRDOS, ERRbadfid);
3577 pos = fsp->fh->position_information;
3578 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3579 delete_pending = get_delete_on_close_flag(fileid);
3580 access_mask = fsp->access_mask;
3583 NTSTATUS status = NT_STATUS_OK;
3586 if (total_params < 7) {
3587 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3591 info_level = SVAL(params,0);
3593 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3595 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3596 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3600 srvstr_get_path(params, req->flags2, fname, ¶ms[6],
3601 sizeof(fname), total_params - 6,
3602 STR_TERMINATE, &status);
3603 if (!NT_STATUS_IS_OK(status)) {
3604 reply_nterror(req, status);
3608 status = resolve_dfspath(conn,
3609 req->flags2 & FLAGS2_DFS_PATHNAMES,
3611 if (!NT_STATUS_IS_OK(status)) {
3612 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3613 reply_botherror(req,
3614 NT_STATUS_PATH_NOT_COVERED,
3615 ERRSRV, ERRbadpath);
3617 reply_nterror(req, status);
3621 status = unix_convert(conn, fname, False, NULL, &sbuf);
3622 if (!NT_STATUS_IS_OK(status)) {
3623 reply_nterror(req, status);
3626 status = check_name(conn, fname);
3627 if (!NT_STATUS_IS_OK(status)) {
3628 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3629 reply_nterror(req, status);
3633 if (INFO_LEVEL_IS_UNIX(info_level)) {
3634 /* Always do lstat for UNIX calls. */
3635 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3636 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3637 reply_unixerror(req, ERRDOS, ERRbadpath);
3640 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3641 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3642 reply_unixerror(req, ERRDOS, ERRbadpath);
3646 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3647 delete_pending = get_delete_on_close_flag(fileid);
3648 if (delete_pending) {
3649 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3654 nlink = sbuf.st_nlink;
3656 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3657 /* NTFS does not seem to count ".." */
3661 if ((nlink > 0) && delete_pending) {
3665 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3666 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3670 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3671 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3673 p = strrchr_m(fname,'/');
3679 mode = dos_mode(conn,fname,&sbuf);
3681 mode = FILE_ATTRIBUTE_NORMAL;
3683 fullpathname = fname;
3685 file_size = get_file_size(sbuf);
3687 /* Pull out any data sent here before we realloc. */
3688 switch (info_level) {
3689 case SMB_INFO_QUERY_EAS_FROM_LIST:
3691 /* Pull any EA list from the data portion. */
3694 if (total_data < 4) {
3696 req, NT_STATUS_INVALID_PARAMETER);
3699 ea_size = IVAL(pdata,0);
3701 if (total_data > 0 && ea_size != total_data) {
3702 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3703 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3705 req, NT_STATUS_INVALID_PARAMETER);
3709 if (!lp_ea_support(SNUM(conn))) {
3710 reply_doserror(req, ERRDOS,
3711 ERReasnotsupported);
3715 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3716 reply_nterror(req, NT_STATUS_NO_MEMORY);
3720 /* Pull out the list of names. */
3721 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3723 talloc_destroy(data_ctx);
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 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3745 reply_nterror(req, NT_STATUS_NO_MEMORY);
3749 /* Copy the lock range data. */
3750 lock_data = (char *)TALLOC_MEMDUP(
3751 data_ctx, pdata, total_data);
3753 talloc_destroy(data_ctx);
3754 reply_nterror(req, NT_STATUS_NO_MEMORY);
3762 *pparams = (char *)SMB_REALLOC(*pparams,2);
3763 if (*pparams == NULL) {
3764 talloc_destroy(data_ctx);
3765 reply_nterror(req, NT_STATUS_NO_MEMORY);
3770 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3771 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3772 if (*ppdata == NULL ) {
3773 talloc_destroy(data_ctx);
3774 reply_nterror(req, NT_STATUS_NO_MEMORY);
3779 dend = dstart + data_size - 1;
3781 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3782 mtime_ts = get_mtimespec(&sbuf);
3783 atime_ts = get_atimespec(&sbuf);
3785 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3788 if (!null_timespec(fsp->pending_modtime)) {
3789 /* the pending modtime overrides the current modtime */
3790 mtime_ts = fsp->pending_modtime;
3794 /* Do we have this path open ? */
3795 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3796 fsp1 = file_find_di_first(fileid);
3797 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3798 /* the pending modtime overrides the current modtime */
3799 mtime_ts = fsp1->pending_modtime;
3801 if (fsp1 && fsp1->initial_allocation_size) {
3802 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3806 if (lp_dos_filetime_resolution(SNUM(conn))) {
3807 dos_filetime_timespec(&create_time_ts);
3808 dos_filetime_timespec(&mtime_ts);
3809 dos_filetime_timespec(&atime_ts);
3812 create_time = convert_timespec_to_time_t(create_time_ts);
3813 mtime = convert_timespec_to_time_t(mtime_ts);
3814 atime = convert_timespec_to_time_t(atime_ts);
3816 /* NT expects the name to be in an exact form of the *full*
3817 filename. See the trans2 torture test */
3818 if (strequal(base_name,".")) {
3819 pstrcpy(dos_fname, "\\");
3821 pstr_sprintf(dos_fname, "\\%s", fname);
3822 string_replace(dos_fname, '/', '\\');
3825 switch (info_level) {
3826 case SMB_INFO_STANDARD:
3827 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3829 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3830 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3831 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3832 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3833 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3834 SSVAL(pdata,l1_attrFile,mode);
3837 case SMB_INFO_QUERY_EA_SIZE:
3839 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3840 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3842 srv_put_dos_date2(pdata,0,create_time);
3843 srv_put_dos_date2(pdata,4,atime);
3844 srv_put_dos_date2(pdata,8,mtime); /* write time */
3845 SIVAL(pdata,12,(uint32)file_size);
3846 SIVAL(pdata,16,(uint32)allocation_size);
3847 SSVAL(pdata,20,mode);
3848 SIVAL(pdata,22,ea_size);
3852 case SMB_INFO_IS_NAME_VALID:
3853 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3854 if (tran_call == TRANSACT2_QFILEINFO) {
3855 /* os/2 needs this ? really ?*/
3856 reply_doserror(req, ERRDOS, ERRbadfunc);
3863 case SMB_INFO_QUERY_EAS_FROM_LIST:
3865 size_t total_ea_len = 0;
3866 struct ea_list *ea_file_list = NULL;
3868 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3870 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3871 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3873 if (!ea_list || (total_ea_len > data_size)) {
3874 talloc_destroy(data_ctx);
3876 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3880 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3881 talloc_destroy(data_ctx);
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 data_ctx = talloc_init("ea_ctx");
3894 reply_nterror(req, NT_STATUS_NO_MEMORY);
3898 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3899 if (!ea_list || (total_ea_len > data_size)) {
3900 talloc_destroy(data_ctx);
3902 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3906 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3907 talloc_destroy(data_ctx);
3911 case SMB_FILE_BASIC_INFORMATION:
3912 case SMB_QUERY_FILE_BASIC_INFO:
3914 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3915 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3916 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3918 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3922 put_long_date_timespec(pdata,create_time_ts);
3923 put_long_date_timespec(pdata+8,atime_ts);
3924 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3925 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3926 SIVAL(pdata,32,mode);
3928 DEBUG(5,("SMB_QFBI - "));
3929 DEBUG(5,("create: %s ", ctime(&create_time)));
3930 DEBUG(5,("access: %s ", ctime(&atime)));
3931 DEBUG(5,("write: %s ", ctime(&mtime)));
3932 DEBUG(5,("change: %s ", ctime(&mtime)));
3933 DEBUG(5,("mode: %x\n", mode));
3936 case SMB_FILE_STANDARD_INFORMATION:
3937 case SMB_QUERY_FILE_STANDARD_INFO:
3939 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3941 SOFF_T(pdata,0,allocation_size);
3942 SOFF_T(pdata,8,file_size);
3943 SIVAL(pdata,16,nlink);
3944 SCVAL(pdata,20,delete_pending?1:0);
3945 SCVAL(pdata,21,(mode&aDIR)?1:0);
3946 SSVAL(pdata,22,0); /* Padding. */
3949 case SMB_FILE_EA_INFORMATION:
3950 case SMB_QUERY_FILE_EA_INFO:
3952 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3953 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3955 SIVAL(pdata,0,ea_size);
3959 /* Get the 8.3 name - used if NT SMB was negotiated. */
3960 case SMB_QUERY_FILE_ALT_NAME_INFO:
3961 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3965 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3966 pstrcpy(short_name,base_name);
3967 /* Mangle if not already 8.3 */
3968 if(!mangle_is_8_3(short_name, True, conn->params)) {
3969 mangle_map(short_name,True,True,conn->params);
3971 len = srvstr_push(dstart, req->flags2,
3972 pdata+4, short_name,
3973 PTR_DIFF(dend, pdata+4),
3975 data_size = 4 + len;
3980 case SMB_QUERY_FILE_NAME_INFO:
3982 this must be *exactly* right for ACLs on mapped drives to work
3984 len = srvstr_push(dstart, req->flags2,
3986 PTR_DIFF(dend, pdata+4),
3988 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3989 data_size = 4 + len;
3993 case SMB_FILE_ALLOCATION_INFORMATION:
3994 case SMB_QUERY_FILE_ALLOCATION_INFO:
3995 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3997 SOFF_T(pdata,0,allocation_size);
4000 case SMB_FILE_END_OF_FILE_INFORMATION:
4001 case SMB_QUERY_FILE_END_OF_FILEINFO:
4002 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4004 SOFF_T(pdata,0,file_size);
4007 case SMB_QUERY_FILE_ALL_INFO:
4008 case SMB_FILE_ALL_INFORMATION:
4010 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4011 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4012 put_long_date_timespec(pdata,create_time_ts);
4013 put_long_date_timespec(pdata+8,atime_ts);
4014 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4015 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4016 SIVAL(pdata,32,mode);
4017 SIVAL(pdata,36,0); /* padding. */
4019 SOFF_T(pdata,0,allocation_size);
4020 SOFF_T(pdata,8,file_size);
4021 SIVAL(pdata,16,nlink);
4022 SCVAL(pdata,20,delete_pending);
4023 SCVAL(pdata,21,(mode&aDIR)?1:0);
4026 SIVAL(pdata,0,ea_size);
4027 pdata += 4; /* EA info */
4028 len = srvstr_push(dstart, req->flags2,
4030 PTR_DIFF(dend, pdata+4),
4034 data_size = PTR_DIFF(pdata,(*ppdata));
4037 case SMB_FILE_INTERNAL_INFORMATION:
4038 /* This should be an index number - looks like
4041 I think this causes us to fail the IFSKIT
4042 BasicFileInformationTest. -tpot */
4044 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4045 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4046 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4050 case SMB_FILE_ACCESS_INFORMATION:
4051 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4052 SIVAL(pdata,0,access_mask);
4056 case SMB_FILE_NAME_INFORMATION:
4057 /* Pathname with leading '\'. */
4060 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4061 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4062 SIVAL(pdata,0,byte_len);
4063 data_size = 4 + byte_len;
4067 case SMB_FILE_DISPOSITION_INFORMATION:
4068 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4070 SCVAL(pdata,0,delete_pending);
4073 case SMB_FILE_POSITION_INFORMATION:
4074 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4076 SOFF_T(pdata,0,pos);
4079 case SMB_FILE_MODE_INFORMATION:
4080 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4081 SIVAL(pdata,0,mode);
4085 case SMB_FILE_ALIGNMENT_INFORMATION:
4086 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4087 SIVAL(pdata,0,0); /* No alignment needed. */
4093 * NT4 server just returns "invalid query" to this - if we try to answer
4094 * it then NTws gets a BSOD! (tridge).
4095 * W2K seems to want this. JRA.
4097 case SMB_QUERY_FILE_STREAM_INFO:
4099 case SMB_FILE_STREAM_INFORMATION:
4100 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4104 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4105 SIVAL(pdata,0,0); /* ??? */
4106 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4107 SOFF_T(pdata,8,file_size);
4108 SOFF_T(pdata,16,allocation_size);
4109 data_size = 24 + byte_len;
4113 case SMB_QUERY_COMPRESSION_INFO:
4114 case SMB_FILE_COMPRESSION_INFORMATION:
4115 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4116 SOFF_T(pdata,0,file_size);
4117 SIVAL(pdata,8,0); /* ??? */
4118 SIVAL(pdata,12,0); /* ??? */
4122 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4123 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4124 put_long_date_timespec(pdata,create_time_ts);
4125 put_long_date_timespec(pdata+8,atime_ts);
4126 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4127 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4128 SOFF_T(pdata,32,allocation_size);
4129 SOFF_T(pdata,40,file_size);
4130 SIVAL(pdata,48,mode);
4131 SIVAL(pdata,52,0); /* ??? */
4135 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4136 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4137 SIVAL(pdata,0,mode);
4143 * CIFS UNIX Extensions.
4146 case SMB_QUERY_FILE_UNIX_BASIC:
4148 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4149 data_size = PTR_DIFF(pdata,(*ppdata));
4153 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4155 for (i=0; i<100; i++)
4156 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4162 case SMB_QUERY_FILE_UNIX_INFO2:
4164 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4165 data_size = PTR_DIFF(pdata,(*ppdata));
4169 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4171 for (i=0; i<100; i++)
4172 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4178 case SMB_QUERY_FILE_UNIX_LINK:
4182 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4184 if(!S_ISLNK(sbuf.st_mode)) {
4185 reply_unixerror(req, ERRSRV,
4190 reply_unixerror(req, ERRDOS, ERRbadlink);
4193 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
4195 reply_unixerror(req, ERRDOS,
4200 len = srvstr_push(dstart, req->flags2,
4202 PTR_DIFF(dend, pdata),
4205 data_size = PTR_DIFF(pdata,(*ppdata));
4210 #if defined(HAVE_POSIX_ACLS)
4211 case SMB_QUERY_POSIX_ACL:
4213 SMB_ACL_T file_acl = NULL;
4214 SMB_ACL_T def_acl = NULL;
4215 uint16 num_file_acls = 0;
4216 uint16 num_def_acls = 0;
4218 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4219 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4221 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4224 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4225 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4229 NT_STATUS_NOT_IMPLEMENTED);
4233 if (S_ISDIR(sbuf.st_mode)) {
4234 if (fsp && fsp->is_directory) {
4235 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4237 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4239 def_acl = free_empty_sys_acl(conn, def_acl);
4242 num_file_acls = count_acl_entries(conn, file_acl);
4243 num_def_acls = count_acl_entries(conn, def_acl);
4245 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4246 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4248 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4249 SMB_POSIX_ACL_HEADER_SIZE) ));
4251 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4254 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4258 NT_STATUS_BUFFER_TOO_SMALL);
4262 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4263 SSVAL(pdata,2,num_file_acls);
4264 SSVAL(pdata,4,num_def_acls);
4265 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4267 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4270 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4273 req, NT_STATUS_INTERNAL_ERROR);
4276 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4278 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4281 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4285 NT_STATUS_INTERNAL_ERROR);
4290 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4293 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4295 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4301 case SMB_QUERY_POSIX_LOCK:
4303 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4305 SMB_BIG_UINT offset;
4307 enum brl_type lock_type;
4309 if (total_data != POSIX_LOCK_DATA_SIZE) {
4311 req, NT_STATUS_INVALID_PARAMETER);
4315 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4316 case POSIX_LOCK_TYPE_READ:
4317 lock_type = READ_LOCK;
4319 case POSIX_LOCK_TYPE_WRITE:
4320 lock_type = WRITE_LOCK;
4322 case POSIX_LOCK_TYPE_UNLOCK:
4324 /* There's no point in asking for an unlock... */
4325 talloc_destroy(data_ctx);
4328 NT_STATUS_INVALID_PARAMETER);
4332 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4333 #if defined(HAVE_LONGLONG)
4334 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4335 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4336 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4337 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4338 #else /* HAVE_LONGLONG */
4339 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4340 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4341 #endif /* HAVE_LONGLONG */
4343 status = query_lock(fsp,
4350 if (ERROR_WAS_LOCK_DENIED(status)) {
4351 /* Here we need to report who has it locked... */
4352 data_size = POSIX_LOCK_DATA_SIZE;
4354 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4355 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4356 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4357 #if defined(HAVE_LONGLONG)
4358 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4359 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4360 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4361 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4362 #else /* HAVE_LONGLONG */
4363 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4364 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4365 #endif /* HAVE_LONGLONG */
4367 } else if (NT_STATUS_IS_OK(status)) {
4368 /* For success we just return a copy of what we sent
4369 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4370 data_size = POSIX_LOCK_DATA_SIZE;
4371 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4372 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4374 reply_nterror(req, status);
4381 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4385 send_trans2_replies(req, params, param_size, *ppdata, data_size,
4391 /****************************************************************************
4392 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4394 ****************************************************************************/
4396 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4398 SMB_STRUCT_STAT sbuf1, sbuf2;
4399 pstring last_component_oldname;
4400 pstring last_component_newname;
4401 NTSTATUS status = NT_STATUS_OK;
4406 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4407 if (!NT_STATUS_IS_OK(status)) {
4411 status = check_name(conn, oldname);
4412 if (!NT_STATUS_IS_OK(status)) {
4416 /* source must already exist. */
4417 if (!VALID_STAT(sbuf1)) {
4418 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4421 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4422 if (!NT_STATUS_IS_OK(status)) {
4426 status = check_name(conn, newname);
4427 if (!NT_STATUS_IS_OK(status)) {
4431 /* Disallow if newname already exists. */
4432 if (VALID_STAT(sbuf2)) {
4433 return NT_STATUS_OBJECT_NAME_COLLISION;
4436 /* No links from a directory. */
4437 if (S_ISDIR(sbuf1.st_mode)) {
4438 return NT_STATUS_FILE_IS_A_DIRECTORY;
4441 /* Ensure this is within the share. */
4442 status = check_reduced_name(conn, oldname);
4443 if (!NT_STATUS_IS_OK(status)) {
4447 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4449 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4450 status = map_nt_error_from_unix(errno);
4451 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4452 nt_errstr(status), newname, oldname));
4458 /****************************************************************************
4459 Deal with setting the time from any of the setfilepathinfo functions.
4460 ****************************************************************************/
4462 static NTSTATUS smb_set_file_time(connection_struct *conn,
4465 const SMB_STRUCT_STAT *psbuf,
4466 struct timespec ts[2])
4469 FILE_NOTIFY_CHANGE_LAST_ACCESS
4470 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4473 if (!VALID_STAT(*psbuf)) {
4474 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4477 /* get some defaults (no modifications) if any info is zero or -1. */
4478 if (null_timespec(ts[0])) {
4479 ts[0] = get_atimespec(psbuf);
4480 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4483 if (null_timespec(ts[1])) {
4484 ts[1] = get_mtimespec(psbuf);
4485 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4488 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4489 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4492 * Try and set the times of this file if
4493 * they are different from the current values.
4497 struct timespec mts = get_mtimespec(psbuf);
4498 struct timespec ats = get_atimespec(psbuf);
4499 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4500 return NT_STATUS_OK;
4506 * This was a setfileinfo on an open file.
4507 * NT does this a lot. We also need to
4508 * set the time here, as it can be read by
4509 * FindFirst/FindNext and with the patch for bug #2045
4510 * in smbd/fileio.c it ensures that this timestamp is
4511 * kept sticky even after a write. We save the request
4512 * away and will set it on file close and after a write. JRA.
4515 if (!null_timespec(ts[1])) {
4516 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4517 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4518 fsp_set_pending_modtime(fsp, ts[1]);
4522 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4524 if(file_ntimes(conn, fname, ts)!=0) {
4525 return map_nt_error_from_unix(errno);
4528 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4530 return NT_STATUS_OK;
4533 /****************************************************************************
4534 Deal with setting the dosmode from any of the setfilepathinfo functions.
4535 ****************************************************************************/
4537 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4539 SMB_STRUCT_STAT *psbuf,
4542 if (!VALID_STAT(*psbuf)) {
4543 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4547 if (S_ISDIR(psbuf->st_mode)) {
4554 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4556 /* check the mode isn't different, before changing it */
4557 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4559 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4560 fname, (unsigned int)dosmode ));
4562 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4563 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4564 fname, strerror(errno)));
4565 return map_nt_error_from_unix(errno);
4568 return NT_STATUS_OK;
4571 /****************************************************************************
4572 Deal with setting the size from any of the setfilepathinfo functions.
4573 ****************************************************************************/
4575 static NTSTATUS smb_set_file_size(connection_struct *conn,
4576 struct smb_request *req,
4579 SMB_STRUCT_STAT *psbuf,
4582 NTSTATUS status = NT_STATUS_OK;
4583 files_struct *new_fsp = NULL;
4585 if (!VALID_STAT(*psbuf)) {
4586 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4589 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4591 if (size == get_file_size(*psbuf)) {
4592 return NT_STATUS_OK;
4595 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4596 fname, (double)size ));
4598 if (fsp && fsp->fh->fd != -1) {
4599 /* Handle based call. */
4600 if (vfs_set_filelen(fsp, size) == -1) {
4601 return map_nt_error_from_unix(errno);
4603 return NT_STATUS_OK;
4606 status = open_file_ntcreate(conn, req, fname, psbuf,
4608 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4611 FILE_ATTRIBUTE_NORMAL,
4612 FORCE_OPLOCK_BREAK_TO_NONE,
4615 if (!NT_STATUS_IS_OK(status)) {
4616 /* NB. We check for open_was_deferred in the caller. */
4620 if (vfs_set_filelen(new_fsp, size) == -1) {
4621 status = map_nt_error_from_unix(errno);
4622 close_file(new_fsp,NORMAL_CLOSE);
4626 close_file(new_fsp,NORMAL_CLOSE);
4627 return NT_STATUS_OK;
4630 /****************************************************************************
4631 Deal with SMB_INFO_SET_EA.
4632 ****************************************************************************/
4634 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4640 struct ea_list *ea_list = NULL;
4641 TALLOC_CTX *ctx = NULL;
4642 NTSTATUS status = NT_STATUS_OK;
4644 if (total_data < 10) {
4646 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4647 length. They seem to have no effect. Bug #3212. JRA */
4649 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4650 /* We're done. We only get EA info in this call. */
4651 return NT_STATUS_OK;
4654 return NT_STATUS_INVALID_PARAMETER;
4657 if (IVAL(pdata,0) > total_data) {
4658 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4659 IVAL(pdata,0), (unsigned int)total_data));
4660 return NT_STATUS_INVALID_PARAMETER;
4663 ctx = talloc_init("SMB_INFO_SET_EA");
4665 return NT_STATUS_NO_MEMORY;
4667 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4669 talloc_destroy(ctx);
4670 return NT_STATUS_INVALID_PARAMETER;
4672 status = set_ea(conn, fsp, fname, ea_list);
4673 talloc_destroy(ctx);
4678 /****************************************************************************
4679 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4680 ****************************************************************************/
4682 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4687 SMB_STRUCT_STAT *psbuf)
4689 NTSTATUS status = NT_STATUS_OK;
4690 BOOL delete_on_close;
4693 if (total_data < 1) {
4694 return NT_STATUS_INVALID_PARAMETER;
4698 return NT_STATUS_INVALID_HANDLE;
4701 delete_on_close = (CVAL(pdata,0) ? True : False);
4702 dosmode = dos_mode(conn, fname, psbuf);
4704 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4705 "delete_on_close = %u\n",
4707 (unsigned int)dosmode,
4708 (unsigned int)delete_on_close ));
4710 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4712 if (!NT_STATUS_IS_OK(status)) {
4716 /* The set is across all open files on this dev/inode pair. */
4717 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4718 return NT_STATUS_ACCESS_DENIED;
4720 return NT_STATUS_OK;
4723 /****************************************************************************
4724 Deal with SMB_FILE_POSITION_INFORMATION.
4725 ****************************************************************************/
4727 static NTSTATUS smb_file_position_information(connection_struct *conn,
4732 SMB_BIG_UINT position_information;
4734 if (total_data < 8) {
4735 return NT_STATUS_INVALID_PARAMETER;
4739 /* Ignore on pathname based set. */
4740 return NT_STATUS_OK;
4743 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4744 #ifdef LARGE_SMB_OFF_T
4745 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4746 #else /* LARGE_SMB_OFF_T */
4747 if (IVAL(pdata,4) != 0) {
4748 /* more than 32 bits? */
4749 return NT_STATUS_INVALID_PARAMETER;
4751 #endif /* LARGE_SMB_OFF_T */
4753 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4754 fsp->fsp_name, (double)position_information ));
4755 fsp->fh->position_information = position_information;
4756 return NT_STATUS_OK;
4759 /****************************************************************************
4760 Deal with SMB_FILE_MODE_INFORMATION.
4761 ****************************************************************************/
4763 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4769 if (total_data < 4) {
4770 return NT_STATUS_INVALID_PARAMETER;
4772 mode = IVAL(pdata,0);
4773 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4774 return NT_STATUS_INVALID_PARAMETER;
4776 return NT_STATUS_OK;
4779 /****************************************************************************
4780 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4781 ****************************************************************************/
4783 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4784 struct smb_request *req,
4789 pstring link_target;
4790 const char *newname = fname;
4791 NTSTATUS status = NT_STATUS_OK;
4793 /* Set a symbolic link. */
4794 /* Don't allow this if follow links is false. */
4796 if (total_data == 0) {
4797 return NT_STATUS_INVALID_PARAMETER;
4800 if (!lp_symlinks(SNUM(conn))) {
4801 return NT_STATUS_ACCESS_DENIED;
4804 srvstr_pull(pdata, req->flags2, link_target, pdata,
4805 sizeof(link_target), total_data, STR_TERMINATE);
4807 /* !widelinks forces the target path to be within the share. */
4808 /* This means we can interpret the target as a pathname. */
4809 if (!lp_widelinks(SNUM(conn))) {
4811 char *last_dirp = NULL;
4813 if (*link_target == '/') {
4814 /* No absolute paths allowed. */
4815 return NT_STATUS_ACCESS_DENIED;
4817 pstrcpy(rel_name, newname);
4818 last_dirp = strrchr_m(rel_name, '/');
4820 last_dirp[1] = '\0';
4822 pstrcpy(rel_name, "./");
4824 pstrcat(rel_name, link_target);
4826 status = check_name(conn, rel_name);
4827 if (!NT_STATUS_IS_OK(status)) {
4832 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4833 newname, link_target ));
4835 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4836 return map_nt_error_from_unix(errno);
4839 return NT_STATUS_OK;
4842 /****************************************************************************
4843 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4844 ****************************************************************************/
4846 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4847 struct smb_request *req,
4848 const char *pdata, int total_data,
4852 NTSTATUS status = NT_STATUS_OK;
4854 /* Set a hard link. */
4855 if (total_data == 0) {
4856 return NT_STATUS_INVALID_PARAMETER;
4859 srvstr_get_path(pdata, req->flags2, oldname, pdata,
4860 sizeof(oldname), total_data, STR_TERMINATE, &status);
4861 if (!NT_STATUS_IS_OK(status)) {
4865 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
4867 if (!NT_STATUS_IS_OK(status)) {
4871 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4874 return hardlink_internals(conn, oldname, fname);
4877 /****************************************************************************
4878 Deal with SMB_FILE_RENAME_INFORMATION.
4879 ****************************************************************************/
4881 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4882 struct smb_request *req,
4883 const char *pdata, int total_data,
4884 files_struct *fsp, pstring fname)
4891 BOOL dest_has_wcard = False;
4892 NTSTATUS status = NT_STATUS_OK;
4895 if (total_data < 13) {
4896 return NT_STATUS_INVALID_PARAMETER;
4899 overwrite = (CVAL(pdata,0) ? True : False);
4900 root_fid = IVAL(pdata,4);
4901 len = IVAL(pdata,8);
4903 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4904 return NT_STATUS_INVALID_PARAMETER;
4907 srvstr_get_path_wcard(pdata, req->flags2, newname, &pdata[12],
4908 sizeof(newname), len, 0, &status,
4910 if (!NT_STATUS_IS_OK(status)) {
4914 status = resolve_dfspath_wcard(conn,
4915 req->flags2 & FLAGS2_DFS_PATHNAMES,
4916 newname, &dest_has_wcard);
4917 if (!NT_STATUS_IS_OK(status)) {
4921 /* Check the new name has no '/' characters. */
4922 if (strchr_m(newname, '/')) {
4923 return NT_STATUS_NOT_SUPPORTED;
4926 /* Create the base directory. */
4927 pstrcpy(base_name, fname);
4928 p = strrchr_m(base_name, '/');
4932 pstrcpy(base_name, "./");
4934 /* Append the new name. */
4935 pstrcat(base_name, newname);
4938 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4939 fsp->fnum, fsp->fsp_name, base_name ));
4940 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4942 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4944 status = rename_internals(conn, req, fname, base_name, 0,
4945 overwrite, False, dest_has_wcard);
4951 /****************************************************************************
4952 Deal with SMB_SET_POSIX_ACL.
4953 ****************************************************************************/
4955 #if defined(HAVE_POSIX_ACLS)
4956 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4961 SMB_STRUCT_STAT *psbuf)
4963 uint16 posix_acl_version;
4964 uint16 num_file_acls;
4965 uint16 num_def_acls;
4966 BOOL valid_file_acls = True;
4967 BOOL valid_def_acls = True;
4969 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4970 return NT_STATUS_INVALID_PARAMETER;
4972 posix_acl_version = SVAL(pdata,0);
4973 num_file_acls = SVAL(pdata,2);
4974 num_def_acls = SVAL(pdata,4);
4976 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4977 valid_file_acls = False;
4981 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4982 valid_def_acls = False;
4986 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4987 return NT_STATUS_INVALID_PARAMETER;
4990 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4991 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4992 return NT_STATUS_INVALID_PARAMETER;
4995 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4996 fname ? fname : fsp->fsp_name,
4997 (unsigned int)num_file_acls,
4998 (unsigned int)num_def_acls));
5000 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5001 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5002 return map_nt_error_from_unix(errno);
5005 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5006 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5007 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5008 return map_nt_error_from_unix(errno);
5010 return NT_STATUS_OK;
5014 /****************************************************************************
5015 Deal with SMB_SET_POSIX_LOCK.
5016 ****************************************************************************/
5018 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5026 SMB_BIG_UINT offset;
5028 BOOL blocking_lock = False;
5029 enum brl_type lock_type;
5030 NTSTATUS status = NT_STATUS_OK;
5032 if (fsp == NULL || fsp->fh->fd == -1) {
5033 return NT_STATUS_INVALID_HANDLE;
5036 if (total_data != POSIX_LOCK_DATA_SIZE) {
5037 return NT_STATUS_INVALID_PARAMETER;
5040 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5041 case POSIX_LOCK_TYPE_READ:
5042 lock_type = READ_LOCK;
5044 case POSIX_LOCK_TYPE_WRITE:
5045 /* Return the right POSIX-mappable error code for files opened read-only. */
5046 if (!fsp->can_write) {
5047 return NT_STATUS_INVALID_HANDLE;
5049 lock_type = WRITE_LOCK;
5051 case POSIX_LOCK_TYPE_UNLOCK:
5052 lock_type = UNLOCK_LOCK;
5055 return NT_STATUS_INVALID_PARAMETER;
5058 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5059 blocking_lock = False;
5060 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5061 blocking_lock = True;
5063 return NT_STATUS_INVALID_PARAMETER;
5066 if (!lp_blocking_locks(SNUM(conn))) {
5067 blocking_lock = False;
5070 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5071 #if defined(HAVE_LONGLONG)
5072 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5073 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5074 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5075 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5076 #else /* HAVE_LONGLONG */
5077 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5078 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5079 #endif /* HAVE_LONGLONG */
5081 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5082 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5084 (unsigned int)lock_type,
5085 (unsigned int)lock_pid,
5089 if (lock_type == UNLOCK_LOCK) {
5090 status = do_unlock(smbd_messaging_context(),
5097 uint32 block_smbpid;
5099 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5110 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5112 * A blocking lock was requested. Package up
5113 * this smb into a queued request and push it
5114 * onto the blocking lock queue.
5116 if(push_blocking_lock_request(br_lck,
5117 (char *)inbuf, length,
5119 -1, /* infinite timeout. */
5127 TALLOC_FREE(br_lck);
5131 TALLOC_FREE(br_lck);
5137 /****************************************************************************
5138 Deal with SMB_INFO_STANDARD.
5139 ****************************************************************************/
5141 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5146 const SMB_STRUCT_STAT *psbuf)
5148 struct timespec ts[2];
5150 if (total_data < 12) {
5151 return NT_STATUS_INVALID_PARAMETER;
5155 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5157 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5159 DEBUG(10,("smb_set_info_standard: file %s\n",
5160 fname ? fname : fsp->fsp_name ));
5162 return smb_set_file_time(conn,
5169 /****************************************************************************
5170 Deal with SMB_SET_FILE_BASIC_INFO.
5171 ****************************************************************************/
5173 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5178 SMB_STRUCT_STAT *psbuf)
5180 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5181 struct timespec write_time;
5182 struct timespec changed_time;
5184 struct timespec ts[2];
5185 NTSTATUS status = NT_STATUS_OK;
5187 if (total_data < 36) {
5188 return NT_STATUS_INVALID_PARAMETER;
5191 /* Set the attributes */
5192 dosmode = IVAL(pdata,32);
5193 status = smb_set_file_dosmode(conn,
5197 if (!NT_STATUS_IS_OK(status)) {
5201 /* Ignore create time at offset pdata. */
5204 ts[0] = interpret_long_date(pdata+8);
5206 write_time = interpret_long_date(pdata+16);
5207 changed_time = interpret_long_date(pdata+24);
5210 ts[1] = timespec_min(&write_time, &changed_time);
5212 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5216 /* Prefer a defined time to an undefined one. */
5217 if (null_timespec(ts[1])) {
5218 ts[1] = null_timespec(write_time) ? changed_time : write_time;
5221 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5222 fname ? fname : fsp->fsp_name ));
5224 return smb_set_file_time(conn,
5231 /****************************************************************************
5232 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5233 ****************************************************************************/
5235 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5236 struct smb_request *req,
5241 SMB_STRUCT_STAT *psbuf)
5243 SMB_BIG_UINT allocation_size = 0;
5244 NTSTATUS status = NT_STATUS_OK;
5245 files_struct *new_fsp = NULL;
5247 if (!VALID_STAT(*psbuf)) {
5248 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5251 if (total_data < 8) {
5252 return NT_STATUS_INVALID_PARAMETER;
5255 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5256 #ifdef LARGE_SMB_OFF_T
5257 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5258 #else /* LARGE_SMB_OFF_T */
5259 if (IVAL(pdata,4) != 0) {
5260 /* more than 32 bits? */
5261 return NT_STATUS_INVALID_PARAMETER;
5263 #endif /* LARGE_SMB_OFF_T */
5265 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5266 fname, (double)allocation_size ));
5268 if (allocation_size) {
5269 allocation_size = smb_roundup(conn, allocation_size);
5272 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5273 fname, (double)allocation_size ));
5275 if (fsp && fsp->fh->fd != -1) {
5276 /* Open file handle. */
5277 /* Only change if needed. */
5278 if (allocation_size != get_file_size(*psbuf)) {
5279 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5280 return map_nt_error_from_unix(errno);
5283 /* But always update the time. */
5284 if (null_timespec(fsp->pending_modtime)) {
5286 * This is equivalent to a write. Ensure it's seen immediately
5287 * if there are no pending writes.
5289 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
5291 return NT_STATUS_OK;
5294 /* Pathname or stat or directory file. */
5296 status = open_file_ntcreate(conn, req, fname, psbuf,
5298 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5301 FILE_ATTRIBUTE_NORMAL,
5302 FORCE_OPLOCK_BREAK_TO_NONE,
5305 if (!NT_STATUS_IS_OK(status)) {
5306 /* NB. We check for open_was_deferred in the caller. */
5310 /* Only change if needed. */
5311 if (allocation_size != get_file_size(*psbuf)) {
5312 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5313 status = map_nt_error_from_unix(errno);
5314 close_file(new_fsp,NORMAL_CLOSE);
5319 /* Changing the allocation size should set the last mod time. */
5320 /* Don't need to call set_filetime as this will be flushed on
5323 fsp_set_pending_modtime(new_fsp, timespec_current());
5325 close_file(new_fsp,NORMAL_CLOSE);
5326 return NT_STATUS_OK;
5329 /****************************************************************************
5330 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5331 ****************************************************************************/
5333 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5334 struct smb_request *req,
5339 SMB_STRUCT_STAT *psbuf)
5343 if (total_data < 8) {
5344 return NT_STATUS_INVALID_PARAMETER;
5347 size = IVAL(pdata,0);
5348 #ifdef LARGE_SMB_OFF_T
5349 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5350 #else /* LARGE_SMB_OFF_T */
5351 if (IVAL(pdata,4) != 0) {
5352 /* more than 32 bits? */
5353 return NT_STATUS_INVALID_PARAMETER;
5355 #endif /* LARGE_SMB_OFF_T */
5356 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5357 "file %s to %.0f\n", fname, (double)size ));
5359 return smb_set_file_size(conn, req,
5366 /****************************************************************************
5367 Allow a UNIX info mknod.
5368 ****************************************************************************/
5370 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5374 SMB_STRUCT_STAT *psbuf)
5376 uint32 file_type = IVAL(pdata,56);
5377 #if defined(HAVE_MAKEDEV)
5378 uint32 dev_major = IVAL(pdata,60);
5379 uint32 dev_minor = IVAL(pdata,68);
5381 SMB_DEV_T dev = (SMB_DEV_T)0;
5382 uint32 raw_unixmode = IVAL(pdata,84);
5386 if (total_data < 100) {
5387 return NT_STATUS_INVALID_PARAMETER;
5390 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5391 if (!NT_STATUS_IS_OK(status)) {
5395 #if defined(HAVE_MAKEDEV)
5396 dev = makedev(dev_major, dev_minor);
5399 switch (file_type) {
5400 #if defined(S_IFIFO)
5401 case UNIX_TYPE_FIFO:
5402 unixmode |= S_IFIFO;
5405 #if defined(S_IFSOCK)
5406 case UNIX_TYPE_SOCKET:
5407 unixmode |= S_IFSOCK;
5410 #if defined(S_IFCHR)
5411 case UNIX_TYPE_CHARDEV:
5412 unixmode |= S_IFCHR;
5415 #if defined(S_IFBLK)
5416 case UNIX_TYPE_BLKDEV:
5417 unixmode |= S_IFBLK;
5421 return NT_STATUS_INVALID_PARAMETER;
5424 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5425 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5427 /* Ok - do the mknod. */
5428 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5429 return map_nt_error_from_unix(errno);
5432 /* If any of the other "set" calls fail we
5433 * don't want to end up with a half-constructed mknod.
5436 if (lp_inherit_perms(SNUM(conn))) {
5438 conn, parent_dirname(fname),
5442 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5443 status = map_nt_error_from_unix(errno);
5444 SMB_VFS_UNLINK(conn,fname);
5447 return NT_STATUS_OK;
5450 /****************************************************************************
5451 Deal with SMB_SET_FILE_UNIX_BASIC.
5452 ****************************************************************************/
5454 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5455 struct smb_request *req,
5460 SMB_STRUCT_STAT *psbuf)
5462 struct timespec ts[2];
5463 uint32 raw_unixmode;
5466 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5467 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5468 NTSTATUS status = NT_STATUS_OK;
5469 BOOL delete_on_fail = False;
5470 enum perm_type ptype;
5472 if (total_data < 100) {
5473 return NT_STATUS_INVALID_PARAMETER;
5476 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5477 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5478 size=IVAL(pdata,0); /* first 8 Bytes are size */
5479 #ifdef LARGE_SMB_OFF_T
5480 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5481 #else /* LARGE_SMB_OFF_T */
5482 if (IVAL(pdata,4) != 0) {
5483 /* more than 32 bits? */
5484 return NT_STATUS_INVALID_PARAMETER;
5486 #endif /* LARGE_SMB_OFF_T */
5489 ts[0] = interpret_long_date(pdata+24); /* access_time */
5490 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5491 set_owner = (uid_t)IVAL(pdata,40);
5492 set_grp = (gid_t)IVAL(pdata,48);
5493 raw_unixmode = IVAL(pdata,84);
5495 if (VALID_STAT(*psbuf)) {
5496 if (S_ISDIR(psbuf->st_mode)) {
5497 ptype = PERM_EXISTING_DIR;
5499 ptype = PERM_EXISTING_FILE;
5502 ptype = PERM_NEW_FILE;
5505 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5506 if (!NT_STATUS_IS_OK(status)) {
5510 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5511 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5512 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5514 if (!VALID_STAT(*psbuf)) {
5516 * The only valid use of this is to create character and block
5517 * devices, and named pipes. This is deprecated (IMHO) and
5518 * a new info level should be used for mknod. JRA.
5521 status = smb_unix_mknod(conn,
5526 if (!NT_STATUS_IS_OK(status)) {
5530 /* Ensure we don't try and change anything else. */
5531 raw_unixmode = SMB_MODE_NO_CHANGE;
5532 size = get_file_size(*psbuf);
5533 ts[0] = get_atimespec(psbuf);
5534 ts[1] = get_mtimespec(psbuf);
5536 * We continue here as we might want to change the
5539 delete_on_fail = True;
5543 /* Horrible backwards compatibility hack as an old server bug
5544 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5548 size = get_file_size(*psbuf);
5553 * Deal with the UNIX specific mode set.
5556 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5557 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5558 (unsigned int)unixmode, fname ));
5559 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5560 return map_nt_error_from_unix(errno);
5565 * Deal with the UNIX specific uid set.
5568 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5571 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5572 (unsigned int)set_owner, fname ));
5574 if (S_ISLNK(psbuf->st_mode)) {
5575 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5577 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5581 status = map_nt_error_from_unix(errno);
5582 if (delete_on_fail) {
5583 SMB_VFS_UNLINK(conn,fname);
5590 * Deal with the UNIX specific gid set.
5593 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5594 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5595 (unsigned int)set_owner, fname ));
5596 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5597 status = map_nt_error_from_unix(errno);
5598 if (delete_on_fail) {
5599 SMB_VFS_UNLINK(conn,fname);
5605 /* Deal with any size changes. */
5607 status = smb_set_file_size(conn, req,
5612 if (!NT_STATUS_IS_OK(status)) {
5616 /* Deal with any time changes. */
5618 return smb_set_file_time(conn,
5625 /****************************************************************************
5626 Deal with SMB_SET_FILE_UNIX_INFO2.
5627 ****************************************************************************/
5629 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5630 struct smb_request *req,
5635 SMB_STRUCT_STAT *psbuf)
5641 if (total_data < 116) {
5642 return NT_STATUS_INVALID_PARAMETER;
5645 /* Start by setting all the fields that are common between UNIX_BASIC
5648 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5650 if (!NT_STATUS_IS_OK(status)) {
5654 smb_fflags = IVAL(pdata, 108);
5655 smb_fmask = IVAL(pdata, 112);
5657 /* NB: We should only attempt to alter the file flags if the client
5658 * sends a non-zero mask.
5660 if (smb_fmask != 0) {
5661 int stat_fflags = 0;
5663 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5665 /* Client asked to alter a flag we don't understand. */
5666 return NT_STATUS_INVALID_PARAMETER;
5669 if (fsp && fsp->fh->fd != -1) {
5670 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5671 return NT_STATUS_NOT_SUPPORTED;
5673 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5674 return map_nt_error_from_unix(errno);
5679 /* XXX: need to add support for changing the create_time here. You
5680 * can do this for paths on Darwin with setattrlist(2). The right way
5681 * to hook this up is probably by extending the VFS utimes interface.
5684 return NT_STATUS_OK;
5687 /****************************************************************************
5688 Create a directory with POSIX semantics.
5689 ****************************************************************************/
5691 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5692 struct smb_request *req,
5696 SMB_STRUCT_STAT *psbuf,
5697 int *pdata_return_size)
5699 NTSTATUS status = NT_STATUS_OK;
5700 uint32 raw_unixmode = 0;
5701 uint32 mod_unixmode = 0;
5702 mode_t unixmode = (mode_t)0;
5703 files_struct *fsp = NULL;
5704 uint16 info_level_return = 0;
5706 char *pdata = *ppdata;
5708 if (total_data < 18) {
5709 return NT_STATUS_INVALID_PARAMETER;
5712 raw_unixmode = IVAL(pdata,8);
5713 /* Next 4 bytes are not yet defined. */
5715 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5716 if (!NT_STATUS_IS_OK(status)) {
5720 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5722 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5723 fname, (unsigned int)unixmode ));
5725 status = open_directory(conn, req,
5728 FILE_READ_ATTRIBUTES, /* Just a stat open */
5729 FILE_SHARE_NONE, /* Ignored for stat opens */
5736 if (NT_STATUS_IS_OK(status)) {
5737 close_file(fsp, NORMAL_CLOSE);
5740 info_level_return = SVAL(pdata,16);
5742 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5743 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5744 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5745 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5747 *pdata_return_size = 12;
5750 /* Realloc the data size */
5751 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5752 if (*ppdata == NULL) {
5753 *pdata_return_size = 0;
5754 return NT_STATUS_NO_MEMORY;
5758 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5759 SSVAL(pdata,2,0); /* No fnum. */
5760 SIVAL(pdata,4,info); /* Was directory created. */
5762 switch (info_level_return) {
5763 case SMB_QUERY_FILE_UNIX_BASIC:
5764 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5765 SSVAL(pdata,10,0); /* Padding. */
5766 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5768 case SMB_QUERY_FILE_UNIX_INFO2:
5769 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5770 SSVAL(pdata,10,0); /* Padding. */
5771 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5774 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5775 SSVAL(pdata,10,0); /* Padding. */
5782 /****************************************************************************
5783 Open/Create a file with POSIX semantics.
5784 ****************************************************************************/
5786 static NTSTATUS smb_posix_open(connection_struct *conn,
5787 struct smb_request *req,
5791 SMB_STRUCT_STAT *psbuf,
5792 int *pdata_return_size)
5794 BOOL extended_oplock_granted = False;
5795 char *pdata = *ppdata;
5797 uint32 wire_open_mode = 0;
5798 uint32 raw_unixmode = 0;
5799 uint32 mod_unixmode = 0;
5800 uint32 create_disp = 0;
5801 uint32 access_mask = 0;
5802 uint32 create_options = 0;
5803 NTSTATUS status = NT_STATUS_OK;
5804 mode_t unixmode = (mode_t)0;
5805 files_struct *fsp = NULL;
5806 int oplock_request = 0;
5808 uint16 info_level_return = 0;
5810 if (total_data < 18) {
5811 return NT_STATUS_INVALID_PARAMETER;
5814 flags = IVAL(pdata,0);
5815 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5816 if (oplock_request) {
5817 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5820 wire_open_mode = IVAL(pdata,4);
5822 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5823 return smb_posix_mkdir(conn, req,
5831 switch (wire_open_mode & SMB_ACCMODE) {
5833 access_mask = FILE_READ_DATA;
5836 access_mask = FILE_WRITE_DATA;
5839 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5842 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5843 (unsigned int)wire_open_mode ));
5844 return NT_STATUS_INVALID_PARAMETER;
5847 wire_open_mode &= ~SMB_ACCMODE;
5849 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5850 create_disp = FILE_CREATE;
5851 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5852 create_disp = FILE_OVERWRITE_IF;
5853 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5854 create_disp = FILE_OPEN_IF;
5856 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5857 (unsigned int)wire_open_mode ));
5858 return NT_STATUS_INVALID_PARAMETER;
5861 raw_unixmode = IVAL(pdata,8);
5862 /* Next 4 bytes are not yet defined. */
5864 status = unix_perms_from_wire(conn,
5867 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5870 if (!NT_STATUS_IS_OK(status)) {
5874 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5876 if (wire_open_mode & SMB_O_SYNC) {
5877 create_options |= FILE_WRITE_THROUGH;
5879 if (wire_open_mode & SMB_O_APPEND) {
5880 access_mask |= FILE_APPEND_DATA;
5882 if (wire_open_mode & SMB_O_DIRECT) {
5883 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5886 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5888 (unsigned int)wire_open_mode,
5889 (unsigned int)unixmode ));
5891 status = open_file_ntcreate(conn, req,
5895 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5897 0, /* no create options yet. */
5903 if (!NT_STATUS_IS_OK(status)) {
5907 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5908 extended_oplock_granted = True;
5911 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5912 extended_oplock_granted = True;
5915 info_level_return = SVAL(pdata,16);
5917 /* Allocate the correct return size. */
5919 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5920 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5921 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5922 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5924 *pdata_return_size = 12;
5927 /* Realloc the data size */
5928 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5929 if (*ppdata == NULL) {
5930 close_file(fsp,ERROR_CLOSE);
5931 *pdata_return_size = 0;
5932 return NT_STATUS_NO_MEMORY;
5936 if (extended_oplock_granted) {
5937 if (flags & REQUEST_BATCH_OPLOCK) {
5938 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5940 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5942 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5943 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5945 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5948 SSVAL(pdata,2,fsp->fnum);
5949 SIVAL(pdata,4,info); /* Was file created etc. */
5951 switch (info_level_return) {
5952 case SMB_QUERY_FILE_UNIX_BASIC:
5953 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5954 SSVAL(pdata,10,0); /* padding. */
5955 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5957 case SMB_QUERY_FILE_UNIX_INFO2:
5958 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5959 SSVAL(pdata,10,0); /* padding. */
5960 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5963 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5964 SSVAL(pdata,10,0); /* padding. */
5967 return NT_STATUS_OK;
5970 /****************************************************************************
5971 Delete a file with POSIX semantics.
5972 ****************************************************************************/
5974 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5975 struct smb_request *req,
5979 SMB_STRUCT_STAT *psbuf)
5981 NTSTATUS status = NT_STATUS_OK;
5982 files_struct *fsp = NULL;
5987 struct share_mode_lock *lck = NULL;
5989 if (total_data < 2) {
5990 return NT_STATUS_INVALID_PARAMETER;
5993 flags = SVAL(pdata,0);
5995 if (!VALID_STAT(*psbuf)) {
5996 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5999 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6000 !VALID_STAT_OF_DIR(*psbuf)) {
6001 return NT_STATUS_NOT_A_DIRECTORY;
6004 DEBUG(10,("smb_posix_unlink: %s %s\n",
6005 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6008 if (VALID_STAT_OF_DIR(*psbuf)) {
6009 status = open_directory(conn, req,
6013 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6016 FILE_FLAG_POSIX_SEMANTICS|0777,
6021 status = open_file_ntcreate(conn, req,
6025 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6028 FILE_FLAG_POSIX_SEMANTICS|0777,
6029 0, /* No oplock, but break existing ones. */
6034 if (!NT_STATUS_IS_OK(status)) {
6039 * Don't lie to client. If we can't really delete due to
6040 * non-POSIX opens return SHARING_VIOLATION.
6043 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
6045 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6046 "lock for file %s\n", fsp->fsp_name));
6047 close_file(fsp, NORMAL_CLOSE);
6048 return NT_STATUS_INVALID_PARAMETER;
6052 * See if others still have the file open. If this is the case, then
6053 * don't delete. If all opens are POSIX delete we can set the delete
6054 * on close disposition.
6056 for (i=0; i<lck->num_share_modes; i++) {
6057 struct share_mode_entry *e = &lck->share_modes[i];
6058 if (is_valid_share_mode_entry(e)) {
6059 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6062 /* Fail with sharing violation. */
6063 close_file(fsp, NORMAL_CLOSE);
6065 return NT_STATUS_SHARING_VIOLATION;
6070 * Set the delete on close.
6072 status = smb_set_file_disposition_info(conn,
6079 if (!NT_STATUS_IS_OK(status)) {
6080 close_file(fsp, NORMAL_CLOSE);
6085 return close_file(fsp, NORMAL_CLOSE);
6088 /****************************************************************************
6089 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6090 ****************************************************************************/
6092 static void call_trans2setfilepathinfo(connection_struct *conn,
6093 struct smb_request *req,
6094 unsigned int tran_call,
6095 char **pparams, int total_params,
6096 char **ppdata, int total_data,
6097 unsigned int max_data_bytes)
6099 char *params = *pparams;
6100 char *pdata = *ppdata;
6102 SMB_STRUCT_STAT sbuf;
6104 files_struct *fsp = NULL;
6105 NTSTATUS status = NT_STATUS_OK;
6106 int data_return_size = 0;
6109 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6115 if (tran_call == TRANSACT2_SETFILEINFO) {
6116 if (total_params < 4) {
6117 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6121 fsp = file_fsp(SVAL(params,0));
6122 info_level = SVAL(params,2);
6124 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
6126 * This is actually a SETFILEINFO on a directory
6127 * handle (returned from an NT SMB). NT5.0 seems
6128 * to do this call. JRA.
6130 pstrcpy(fname, fsp->fsp_name);
6131 if (INFO_LEVEL_IS_UNIX(info_level)) {
6132 /* Always do lstat for UNIX calls. */
6133 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6134 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6135 reply_unixerror(req,ERRDOS,ERRbadpath);
6139 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6140 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6141 reply_unixerror(req,ERRDOS,ERRbadpath);
6145 } else if (fsp && fsp->print_file) {
6147 * Doing a DELETE_ON_CLOSE should cancel a print job.
6149 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6150 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6152 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6155 send_trans2_replies(req, params, 2,
6161 reply_unixerror(req, ERRDOS, ERRbadpath);
6166 * Original code - this is an open file.
6168 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6172 pstrcpy(fname, fsp->fsp_name);
6174 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6175 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6176 reply_unixerror(req, ERRDOS, ERRbadfid);
6182 if (total_params < 7) {
6183 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6187 info_level = SVAL(params,0);
6188 srvstr_get_path(params, req->flags2, fname, ¶ms[6],
6189 sizeof(fname), total_params - 6, STR_TERMINATE,
6191 if (!NT_STATUS_IS_OK(status)) {
6192 reply_nterror(req, status);
6196 status = resolve_dfspath(conn,
6197 req->flags2 & FLAGS2_DFS_PATHNAMES,
6199 if (!NT_STATUS_IS_OK(status)) {
6200 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6201 reply_botherror(req,
6202 NT_STATUS_PATH_NOT_COVERED,
6203 ERRSRV, ERRbadpath);
6206 reply_nterror(req, status);
6210 status = unix_convert(conn, fname, False, NULL, &sbuf);
6211 if (!NT_STATUS_IS_OK(status)) {
6212 reply_nterror(req, status);
6216 status = check_name(conn, fname);
6217 if (!NT_STATUS_IS_OK(status)) {
6218 reply_nterror(req, status);
6222 if (INFO_LEVEL_IS_UNIX(info_level)) {
6224 * For CIFS UNIX extensions the target name may not exist.
6227 /* Always do lstat for UNIX calls. */
6228 SMB_VFS_LSTAT(conn,fname,&sbuf);
6230 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6231 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6232 reply_unixerror(req, ERRDOS, ERRbadpath);
6237 if (!CAN_WRITE(conn)) {
6238 reply_doserror(req, ERRSRV, ERRaccess);
6242 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6243 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6247 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6248 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6250 /* Realloc the parameter size */
6251 *pparams = (char *)SMB_REALLOC(*pparams,2);
6252 if (*pparams == NULL) {
6253 reply_nterror(req, NT_STATUS_NO_MEMORY);
6260 if (fsp && !null_timespec(fsp->pending_modtime)) {
6261 /* the pending modtime overrides the current modtime */
6262 set_mtimespec(&sbuf, fsp->pending_modtime);
6265 switch (info_level) {
6267 case SMB_INFO_STANDARD:
6269 status = smb_set_info_standard(conn,
6278 case SMB_INFO_SET_EA:
6280 status = smb_info_set_ea(conn,
6288 case SMB_SET_FILE_BASIC_INFO:
6289 case SMB_FILE_BASIC_INFORMATION:
6291 status = smb_set_file_basic_info(conn,
6300 case SMB_FILE_ALLOCATION_INFORMATION:
6301 case SMB_SET_FILE_ALLOCATION_INFO:
6303 status = smb_set_file_allocation_info(conn, req,
6312 case SMB_FILE_END_OF_FILE_INFORMATION:
6313 case SMB_SET_FILE_END_OF_FILE_INFO:
6315 status = smb_set_file_end_of_file_info(conn, req,
6324 case SMB_FILE_DISPOSITION_INFORMATION:
6325 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6328 /* JRA - We used to just ignore this on a path ?
6329 * Shouldn't this be invalid level on a pathname
6332 if (tran_call != TRANSACT2_SETFILEINFO) {
6333 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6336 status = smb_set_file_disposition_info(conn,
6345 case SMB_FILE_POSITION_INFORMATION:
6347 status = smb_file_position_information(conn,
6354 /* From tridge Samba4 :
6355 * MODE_INFORMATION in setfileinfo (I have no
6356 * idea what "mode information" on a file is - it takes a value of 0,
6357 * 2, 4 or 6. What could it be?).
6360 case SMB_FILE_MODE_INFORMATION:
6362 status = smb_file_mode_information(conn,
6369 * CIFS UNIX extensions.
6372 case SMB_SET_FILE_UNIX_BASIC:
6374 status = smb_set_file_unix_basic(conn, req,
6383 case SMB_SET_FILE_UNIX_INFO2:
6385 status = smb_set_file_unix_info2(conn, req,
6394 case SMB_SET_FILE_UNIX_LINK:
6396 if (tran_call != TRANSACT2_SETPATHINFO) {
6397 /* We must have a pathname for this. */
6398 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6401 status = smb_set_file_unix_link(conn, req, pdata,
6406 case SMB_SET_FILE_UNIX_HLINK:
6408 if (tran_call != TRANSACT2_SETPATHINFO) {
6409 /* We must have a pathname for this. */
6410 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6413 status = smb_set_file_unix_hlink(conn, req,
6419 case SMB_FILE_RENAME_INFORMATION:
6421 status = smb_file_rename_information(conn, req,
6427 #if defined(HAVE_POSIX_ACLS)
6428 case SMB_SET_POSIX_ACL:
6430 status = smb_set_posix_acl(conn,
6440 case SMB_SET_POSIX_LOCK:
6442 if (tran_call != TRANSACT2_SETFILEINFO) {
6443 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6446 status = smb_set_posix_lock(conn, req->inbuf,
6447 smb_len(req->inbuf) + 4,
6448 pdata, total_data, fsp);
6452 case SMB_POSIX_PATH_OPEN:
6454 if (tran_call != TRANSACT2_SETPATHINFO) {
6455 /* We must have a pathname for this. */
6456 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6460 status = smb_posix_open(conn, req,
6469 case SMB_POSIX_PATH_UNLINK:
6471 if (tran_call != TRANSACT2_SETPATHINFO) {
6472 /* We must have a pathname for this. */
6473 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6477 status = smb_posix_unlink(conn, req,
6486 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6491 if (!NT_STATUS_IS_OK(status)) {
6492 if (open_was_deferred(req->mid)) {
6493 /* We have re-scheduled this call. */
6496 if (blocking_lock_was_deferred(req->mid)) {
6497 /* We have re-scheduled this call. */
6500 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6501 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6502 ERRSRV, ERRbadpath);
6505 reply_nterror(req, status);
6510 send_trans2_replies(req, params, 2, *ppdata, data_return_size,
6516 /****************************************************************************
6517 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6518 ****************************************************************************/
6520 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6521 char **pparams, int total_params,
6522 char **ppdata, int total_data,
6523 unsigned int max_data_bytes)
6525 char *params = *pparams;
6526 char *pdata = *ppdata;
6528 SMB_STRUCT_STAT sbuf;
6529 NTSTATUS status = NT_STATUS_OK;
6530 struct ea_list *ea_list = NULL;
6532 if (!CAN_WRITE(conn)) {
6533 reply_doserror(req, ERRSRV, ERRaccess);
6537 if (total_params < 5) {
6538 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6542 srvstr_get_path(params, req->flags2, directory, ¶ms[4],
6543 sizeof(directory), total_params - 4, STR_TERMINATE,
6545 if (!NT_STATUS_IS_OK(status)) {
6546 reply_nterror(req, status);
6550 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6552 status = unix_convert(conn, directory, False, NULL, &sbuf);
6553 if (!NT_STATUS_IS_OK(status)) {
6554 reply_nterror(req, status);
6558 status = check_name(conn, directory);
6559 if (!NT_STATUS_IS_OK(status)) {
6560 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6561 reply_nterror(req, status);
6565 /* Any data in this call is an EA list. */
6566 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6567 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6572 * OS/2 workplace shell seems to send SET_EA requests of "null"
6573 * length (4 bytes containing IVAL 4).
6574 * They seem to have no effect. Bug #3212. JRA.
6577 if (total_data != 4) {
6578 if (total_data < 10) {
6579 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6583 if (IVAL(pdata,0) > total_data) {
6584 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6585 IVAL(pdata,0), (unsigned int)total_data));
6586 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6590 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6593 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6596 } else if (IVAL(pdata,0) != 4) {
6597 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6601 status = create_directory(conn, directory);
6603 if (!NT_STATUS_IS_OK(status)) {
6604 reply_nterror(req, status);
6608 /* Try and set any given EA. */
6610 status = set_ea(conn, NULL, directory, ea_list);
6611 if (!NT_STATUS_IS_OK(status)) {
6612 reply_nterror(req, status);
6617 /* Realloc the parameter and data sizes */
6618 *pparams = (char *)SMB_REALLOC(*pparams,2);
6619 if(*pparams == NULL) {
6620 reply_nterror(req, NT_STATUS_NO_MEMORY);
6627 send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
6632 /****************************************************************************
6633 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6634 We don't actually do this - we just send a null response.
6635 ****************************************************************************/
6637 static void call_trans2findnotifyfirst(connection_struct *conn,
6638 struct smb_request *req,
6639 char **pparams, int total_params,
6640 char **ppdata, int total_data,
6641 unsigned int max_data_bytes)
6643 static uint16 fnf_handle = 257;
6644 char *params = *pparams;
6647 if (total_params < 6) {
6648 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6652 info_level = SVAL(params,4);
6653 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6655 switch (info_level) {
6660 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6664 /* Realloc the parameter and data sizes */
6665 *pparams = (char *)SMB_REALLOC(*pparams,6);
6666 if (*pparams == NULL) {
6667 reply_nterror(req, NT_STATUS_NO_MEMORY);
6672 SSVAL(params,0,fnf_handle);
6673 SSVAL(params,2,0); /* No changes */
6674 SSVAL(params,4,0); /* No EA errors */
6681 send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
6686 /****************************************************************************
6687 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6688 changes). Currently this does nothing.
6689 ****************************************************************************/
6691 static void call_trans2findnotifynext(connection_struct *conn,
6692 struct smb_request *req,
6693 char **pparams, int total_params,
6694 char **ppdata, int total_data,
6695 unsigned int max_data_bytes)
6697 char *params = *pparams;
6699 DEBUG(3,("call_trans2findnotifynext\n"));
6701 /* Realloc the parameter and data sizes */
6702 *pparams = (char *)SMB_REALLOC(*pparams,4);
6703 if (*pparams == NULL) {
6704 reply_nterror(req, NT_STATUS_NO_MEMORY);
6709 SSVAL(params,0,0); /* No changes */
6710 SSVAL(params,2,0); /* No EA errors */
6712 send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes);
6717 /****************************************************************************
6718 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6719 ****************************************************************************/
6721 static void call_trans2getdfsreferral(connection_struct *conn,
6722 struct smb_request *req,
6723 char **pparams, int total_params,
6724 char **ppdata, int total_data,
6725 unsigned int max_data_bytes)
6727 char *params = *pparams;
6730 int max_referral_level;
6731 NTSTATUS status = NT_STATUS_OK;
6733 DEBUG(10,("call_trans2getdfsreferral\n"));
6735 if (total_params < 3) {
6736 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6740 max_referral_level = SVAL(params,0);
6742 if(!lp_host_msdfs()) {
6743 reply_doserror(req, ERRDOS, ERRbadfunc);
6747 srvstr_pull(params, req->flags2, pathname, ¶ms[2],
6748 sizeof(pathname), total_params - 2, STR_TERMINATE);
6749 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6750 ppdata,&status)) < 0) {
6751 reply_nterror(req, status);
6755 SSVAL(req->inbuf, smb_flg2,
6756 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6757 send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes);
6762 #define LMCAT_SPL 0x53
6763 #define LMFUNC_GETJOBID 0x60
6765 /****************************************************************************
6766 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6767 ****************************************************************************/
6769 static void call_trans2ioctl(connection_struct *conn,
6770 struct smb_request *req,
6771 char **pparams, int total_params,
6772 char **ppdata, int total_data,
6773 unsigned int max_data_bytes)
6775 char *pdata = *ppdata;
6776 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6778 /* check for an invalid fid before proceeding */
6781 reply_doserror(req, ERRDOS, ERRbadfid);
6785 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6786 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6787 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6788 if (*ppdata == NULL) {
6789 reply_nterror(req, NT_STATUS_NO_MEMORY);
6794 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6795 CAN ACCEPT THIS IN UNICODE. JRA. */
6797 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6798 srvstr_push(pdata, req->flags2, pdata + 2,
6799 global_myname(), 15,
6800 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6801 srvstr_push(pdata, req->flags2, pdata+18,
6802 lp_servicename(SNUM(conn)), 13,
6803 STR_ASCII|STR_TERMINATE); /* Service name */
6804 send_trans2_replies(req, *pparams, 0, *ppdata, 32,
6809 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6810 reply_doserror(req, ERRSRV, ERRerror);
6813 /****************************************************************************
6814 Reply to a SMBfindclose (stop trans2 directory search).
6815 ****************************************************************************/
6817 int reply_findclose(connection_struct *conn,
6818 char *inbuf,char *outbuf,int length,int bufsize)
6821 int dptr_num=SVALS(inbuf,smb_vwv0);
6822 START_PROFILE(SMBfindclose);
6824 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6826 dptr_close(&dptr_num);
6828 outsize = set_message(inbuf, outbuf,0,0,False);
6830 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6832 END_PROFILE(SMBfindclose);
6836 /****************************************************************************
6837 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6838 ****************************************************************************/
6840 int reply_findnclose(connection_struct *conn,
6841 char *inbuf,char *outbuf,int length,int bufsize)
6845 START_PROFILE(SMBfindnclose);
6847 dptr_num = SVAL(inbuf,smb_vwv0);
6849 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6851 /* We never give out valid handles for a
6852 findnotifyfirst - so any dptr_num is ok here.
6855 outsize = set_message(inbuf, outbuf,0,0,False);
6857 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6859 END_PROFILE(SMBfindnclose);
6863 static void handle_trans2(connection_struct *conn, struct smb_request *req,
6864 struct trans_state *state)
6866 if (Protocol >= PROTOCOL_NT1) {
6867 req->flags2 |= 0x40; /* IS_LONG_NAME */
6868 SSVAL(req->inbuf,smb_flg2,req->flags2);
6871 /* Now we must call the relevant TRANS2 function */
6872 switch(state->call) {
6873 case TRANSACT2_OPEN:
6875 START_PROFILE(Trans2_open);
6876 call_trans2open(conn, req,
6877 &state->param, state->total_param,
6878 &state->data, state->total_data,
6879 state->max_data_return);
6880 END_PROFILE(Trans2_open);
6884 case TRANSACT2_FINDFIRST:
6886 START_PROFILE(Trans2_findfirst);
6887 call_trans2findfirst(conn, req,
6888 &state->param, state->total_param,
6889 &state->data, state->total_data,
6890 state->max_data_return);
6891 END_PROFILE(Trans2_findfirst);
6895 case TRANSACT2_FINDNEXT:
6897 START_PROFILE(Trans2_findnext);
6898 call_trans2findnext(conn, req,
6899 &state->param, state->total_param,
6900 &state->data, state->total_data,
6901 state->max_data_return);
6902 END_PROFILE(Trans2_findnext);
6906 case TRANSACT2_QFSINFO:
6908 START_PROFILE(Trans2_qfsinfo);
6909 call_trans2qfsinfo(conn, req,
6910 &state->param, state->total_param,
6911 &state->data, state->total_data,
6912 state->max_data_return);
6913 END_PROFILE(Trans2_qfsinfo);
6917 case TRANSACT2_SETFSINFO:
6919 START_PROFILE(Trans2_setfsinfo);
6920 call_trans2setfsinfo(conn, req,
6921 &state->param, state->total_param,
6922 &state->data, state->total_data,
6923 state->max_data_return);
6924 END_PROFILE(Trans2_setfsinfo);
6928 case TRANSACT2_QPATHINFO:
6929 case TRANSACT2_QFILEINFO:
6931 START_PROFILE(Trans2_qpathinfo);
6932 call_trans2qfilepathinfo(conn, req, state->call,
6933 &state->param, state->total_param,
6934 &state->data, state->total_data,
6935 state->max_data_return);
6936 END_PROFILE(Trans2_qpathinfo);
6940 case TRANSACT2_SETPATHINFO:
6941 case TRANSACT2_SETFILEINFO:
6943 START_PROFILE(Trans2_setpathinfo);
6944 call_trans2setfilepathinfo(conn, req, state->call,
6945 &state->param, state->total_param,
6946 &state->data, state->total_data,
6947 state->max_data_return);
6948 END_PROFILE(Trans2_setpathinfo);
6952 case TRANSACT2_FINDNOTIFYFIRST:
6954 START_PROFILE(Trans2_findnotifyfirst);
6955 call_trans2findnotifyfirst(conn, req,
6956 &state->param, state->total_param,
6957 &state->data, state->total_data,
6958 state->max_data_return);
6959 END_PROFILE(Trans2_findnotifyfirst);
6963 case TRANSACT2_FINDNOTIFYNEXT:
6965 START_PROFILE(Trans2_findnotifynext);
6966 call_trans2findnotifynext(conn, req,
6967 &state->param, state->total_param,
6968 &state->data, state->total_data,
6969 state->max_data_return);
6970 END_PROFILE(Trans2_findnotifynext);
6974 case TRANSACT2_MKDIR:
6976 START_PROFILE(Trans2_mkdir);
6977 call_trans2mkdir(conn, req,
6978 &state->param, state->total_param,
6979 &state->data, state->total_data,
6980 state->max_data_return);
6981 END_PROFILE(Trans2_mkdir);
6985 case TRANSACT2_GET_DFS_REFERRAL:
6987 START_PROFILE(Trans2_get_dfs_referral);
6988 call_trans2getdfsreferral(conn, req,
6989 &state->param, state->total_param,
6990 &state->data, state->total_data,
6991 state->max_data_return);
6992 END_PROFILE(Trans2_get_dfs_referral);
6996 case TRANSACT2_IOCTL:
6998 START_PROFILE(Trans2_ioctl);
6999 call_trans2ioctl(conn, req,
7000 &state->param, state->total_param,
7001 &state->data, state->total_data,
7002 state->max_data_return);
7003 END_PROFILE(Trans2_ioctl);
7008 /* Error in request */
7009 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7010 reply_doserror(req, ERRSRV,ERRerror);
7014 /****************************************************************************
7015 Reply to a SMBtrans2.
7016 ****************************************************************************/
7018 void reply_trans2(connection_struct *conn, struct smb_request *req)
7024 unsigned int tran_call;
7026 struct trans_state *state;
7029 START_PROFILE(SMBtrans2);
7031 if (req->wct < 14) {
7032 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7033 END_PROFILE(SMBtrans2);
7037 dsoff = SVAL(req->inbuf, smb_dsoff);
7038 dscnt = SVAL(req->inbuf, smb_dscnt);
7039 psoff = SVAL(req->inbuf, smb_psoff);
7040 pscnt = SVAL(req->inbuf, smb_pscnt);
7041 tran_call = SVAL(req->inbuf, smb_setup0);
7042 size = smb_len(req->inbuf) + 4;
7044 result = allow_new_trans(conn->pending_trans, req->mid);
7045 if (!NT_STATUS_IS_OK(result)) {
7046 DEBUG(2, ("Got invalid trans2 request: %s\n",
7047 nt_errstr(result)));
7048 reply_nterror(req, result);
7049 END_PROFILE(SMBtrans2);
7053 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
7054 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
7055 && (tran_call != TRANSACT2_QFILEINFO)) {
7056 reply_doserror(req, ERRSRV, ERRaccess);
7057 END_PROFILE(SMBtrans2);
7061 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7062 DEBUG(0, ("talloc failed\n"));
7063 reply_nterror(req, NT_STATUS_NO_MEMORY);
7064 END_PROFILE(SMBtrans2);
7068 state->cmd = SMBtrans2;
7070 state->mid = req->mid;
7071 state->vuid = req->vuid;
7072 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7073 state->setup = NULL;
7074 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7075 state->param = NULL;
7076 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7078 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7079 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7080 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7081 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7082 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7084 state->call = tran_call;
7086 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7087 is so as a sanity check */
7088 if (state->setup_count != 1) {
7090 * Need to have rc=0 for ioctl to get job id for OS/2.
7091 * Network printing will fail if function is not successful.
7092 * Similar function in reply.c will be used if protocol
7093 * is LANMAN1.0 instead of LM1.2X002.
7094 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7095 * outbuf doesn't have to be set(only job id is used).
7097 if ( (state->setup_count == 4)
7098 && (tran_call == TRANSACT2_IOCTL)
7099 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7100 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7101 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7103 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7104 DEBUG(2,("Transaction is %d\n",tran_call));
7106 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7107 END_PROFILE(SMBtrans2);
7112 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7115 if (state->total_data) {
7116 /* Can't use talloc here, the core routines do realloc on the
7117 * params and data. */
7118 state->data = (char *)SMB_MALLOC(state->total_data);
7119 if (state->data == NULL) {
7120 DEBUG(0,("reply_trans2: data malloc fail for %u "
7121 "bytes !\n", (unsigned int)state->total_data));
7123 reply_nterror(req, NT_STATUS_NO_MEMORY);
7124 END_PROFILE(SMBtrans2);
7127 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7129 if ((smb_base(req->inbuf)+dsoff+dscnt
7130 > (char *)req->inbuf + size) ||
7131 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7134 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7137 if (state->total_param) {
7138 /* Can't use talloc here, the core routines do realloc on the
7139 * params and data. */
7140 state->param = (char *)SMB_MALLOC(state->total_param);
7141 if (state->param == NULL) {
7142 DEBUG(0,("reply_trans: param malloc fail for %u "
7143 "bytes !\n", (unsigned int)state->total_param));
7144 SAFE_FREE(state->data);
7146 reply_nterror(req, NT_STATUS_NO_MEMORY);
7147 END_PROFILE(SMBtrans2);
7150 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7152 if ((smb_base(req->inbuf)+psoff+pscnt
7153 > (char *)req->inbuf + size) ||
7154 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7157 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7160 state->received_data = dscnt;
7161 state->received_param = pscnt;
7163 if ((state->received_param == state->total_param) &&
7164 (state->received_data == state->total_data)) {
7166 handle_trans2(conn, req, state);
7168 SAFE_FREE(state->data);
7169 SAFE_FREE(state->param);
7171 END_PROFILE(SMBtrans2);
7175 DLIST_ADD(conn->pending_trans, state);
7177 /* We need to send an interim response then receive the rest
7178 of the parameter/data bytes */
7179 reply_outbuf(req, 0, 0);
7180 show_msg((char *)req->outbuf);
7181 END_PROFILE(SMBtrans2);
7186 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7187 SAFE_FREE(state->data);
7188 SAFE_FREE(state->param);
7190 END_PROFILE(SMBtrans2);
7191 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7195 /****************************************************************************
7196 Reply to a SMBtranss2
7197 ****************************************************************************/
7199 void reply_transs2(connection_struct *conn, struct smb_request *req)
7201 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7202 struct trans_state *state;
7205 START_PROFILE(SMBtranss2);
7207 show_msg((char *)req->inbuf);
7210 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7211 END_PROFILE(SMBtranss2);
7215 size = smb_len(req->inbuf)+4;
7217 for (state = conn->pending_trans; state != NULL;
7218 state = state->next) {
7219 if (state->mid == req->mid) {
7224 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7225 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7226 END_PROFILE(SMBtranss2);
7230 /* Revise state->total_param and state->total_data in case they have
7231 changed downwards */
7233 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7234 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7235 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7236 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7238 pcnt = SVAL(req->inbuf, smb_spscnt);
7239 poff = SVAL(req->inbuf, smb_spsoff);
7240 pdisp = SVAL(req->inbuf, smb_spsdisp);
7242 dcnt = SVAL(req->inbuf, smb_sdscnt);
7243 doff = SVAL(req->inbuf, smb_sdsoff);
7244 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7246 state->received_param += pcnt;
7247 state->received_data += dcnt;
7249 if ((state->received_data > state->total_data) ||
7250 (state->received_param > state->total_param))
7254 if (pdisp+pcnt > state->total_param)
7256 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7258 if (pdisp > state->total_param)
7260 if ((smb_base(req->inbuf) + poff + pcnt
7261 > (char *)req->inbuf + size) ||
7262 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7264 if (state->param + pdisp < state->param)
7267 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7272 if (ddisp+dcnt > state->total_data)
7274 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7276 if (ddisp > state->total_data)
7278 if ((smb_base(req->inbuf) + doff + dcnt
7279 > (char *)req->inbuf + size) ||
7280 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7282 if (state->data + ddisp < state->data)
7285 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7289 if ((state->received_param < state->total_param) ||
7290 (state->received_data < state->total_data)) {
7291 END_PROFILE(SMBtranss2);
7296 * construct_reply_common will copy smb_com from inbuf to
7297 * outbuf. SMBtranss2 is wrong here.
7299 SCVAL(req->inbuf,smb_com,SMBtrans2);
7301 handle_trans2(conn, req, state);
7303 DLIST_REMOVE(conn->pending_trans, state);
7304 SAFE_FREE(state->data);
7305 SAFE_FREE(state->param);
7308 END_PROFILE(SMBtranss2);
7313 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7314 DLIST_REMOVE(conn->pending_trans, state);
7315 SAFE_FREE(state->data);
7316 SAFE_FREE(state->param);
7318 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7319 END_PROFILE(SMBtranss2);