2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 extern enum protocol_types Protocol;
30 extern int smb_read_error;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
37 static char *store_file_unix_basic(connection_struct *conn,
40 const SMB_STRUCT_STAT *psbuf);
42 static char *store_file_unix_basic_info2(connection_struct *conn,
45 const SMB_STRUCT_STAT *psbuf);
47 /********************************************************************
48 Roundup a value to the nearest allocation roundup size boundary.
49 Only do this for Windows clients.
50 ********************************************************************/
52 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
54 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
56 /* Only roundup for Windows clients. */
57 enum remote_arch_types ra_type = get_remote_arch();
58 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
59 val = SMB_ROUNDUP(val,rval);
64 /********************************************************************
65 Given a stat buffer return the allocated size on disk, taking into
67 ********************************************************************/
69 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
73 if(S_ISDIR(sbuf->st_mode)) {
77 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
78 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
80 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
83 if (fsp && fsp->initial_allocation_size)
84 ret = MAX(ret,fsp->initial_allocation_size);
86 return smb_roundup(conn, ret);
89 /****************************************************************************
90 Utility functions for dealing with extended attributes.
91 ****************************************************************************/
93 /****************************************************************************
94 Refuse to allow clients to overwrite our private xattrs.
95 ****************************************************************************/
97 static BOOL samba_private_attr_name(const char *unix_ea_name)
99 static const char *prohibited_ea_names[] = {
100 SAMBA_POSIX_INHERITANCE_EA_NAME,
101 SAMBA_XATTR_DOS_ATTRIB,
107 for (i = 0; prohibited_ea_names[i]; i++) {
108 if (strequal( prohibited_ea_names[i], unix_ea_name))
114 /****************************************************************************
115 Get one EA value. Fill in a struct ea_struct.
116 ****************************************************************************/
118 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
119 const char *fname, char *ea_name, struct ea_struct *pea)
121 /* Get the value of this xattr. Max size is 64k. */
122 size_t attr_size = 256;
128 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
133 if (fsp && fsp->fh->fd != -1) {
134 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
136 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
139 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
148 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
149 dump_data(10, (uint8 *)val, sizeret);
152 if (strnequal(ea_name, "user.", 5)) {
153 pea->name = &ea_name[5];
157 pea->value.data = (unsigned char *)val;
158 pea->value.length = (size_t)sizeret;
162 /****************************************************************************
163 Return a linked list of the total EA's. Plus the total size
164 ****************************************************************************/
166 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
167 const char *fname, size_t *pea_total_len)
169 /* Get a list of all xattrs. Max namesize is 64k. */
170 size_t ea_namelist_size = 1024;
175 struct ea_list *ea_list_head = NULL;
179 if (!lp_ea_support(SNUM(conn))) {
183 for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
184 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
190 if (fsp && fsp->fh->fd != -1) {
191 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
193 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
196 if (sizeret == -1 && errno == ERANGE) {
197 ea_namelist_size *= 2;
206 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
209 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
210 struct ea_list *listp;
212 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
215 listp = TALLOC_P(mem_ctx, struct ea_list);
219 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
225 push_ascii_fstring(dos_ea_name, listp->ea.name);
226 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
227 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
228 (unsigned int)*pea_total_len, dos_ea_name,
229 (unsigned int)listp->ea.value.length ));
231 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
233 /* Add on 4 for total length. */
234 if (*pea_total_len) {
239 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
243 /****************************************************************************
244 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
246 ****************************************************************************/
248 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
249 connection_struct *conn, struct ea_list *ea_list)
251 unsigned int ret_data_size = 4;
254 SMB_ASSERT(total_data_size >= 4);
256 if (!lp_ea_support(SNUM(conn))) {
261 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
264 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
265 dos_namelen = strlen(dos_ea_name);
266 if (dos_namelen > 255 || dos_namelen == 0) {
269 if (ea_list->ea.value.length > 65535) {
272 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
276 /* We know we have room. */
277 SCVAL(p,0,ea_list->ea.flags);
278 SCVAL(p,1,dos_namelen);
279 SSVAL(p,2,ea_list->ea.value.length);
280 fstrcpy(p+4, dos_ea_name);
281 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
283 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
284 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
287 ret_data_size = PTR_DIFF(p, pdata);
288 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
289 SIVAL(pdata,0,ret_data_size);
290 return ret_data_size;
293 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
295 size_t total_ea_len = 0;
296 TALLOC_CTX *mem_ctx = NULL;
298 if (!lp_ea_support(SNUM(conn))) {
301 mem_ctx = talloc_init("estimate_ea_size");
302 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
303 talloc_destroy(mem_ctx);
307 /****************************************************************************
308 Ensure the EA name is case insensitive by matching any existing EA name.
309 ****************************************************************************/
311 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
314 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
315 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
317 for (; ea_list; ea_list = ea_list->next) {
318 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
319 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
320 &unix_ea_name[5], ea_list->ea.name));
321 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
325 talloc_destroy(mem_ctx);
328 /****************************************************************************
329 Set or delete an extended attribute.
330 ****************************************************************************/
332 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
334 if (!lp_ea_support(SNUM(conn))) {
335 return NT_STATUS_EAS_NOT_SUPPORTED;
338 for (;ea_list; ea_list = ea_list->next) {
340 fstring unix_ea_name;
342 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
343 fstrcat(unix_ea_name, ea_list->ea.name);
345 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
347 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
349 if (samba_private_attr_name(unix_ea_name)) {
350 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
351 return NT_STATUS_ACCESS_DENIED;
354 if (ea_list->ea.value.length == 0) {
355 /* Remove the attribute. */
356 if (fsp && (fsp->fh->fd != -1)) {
357 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
358 unix_ea_name, fsp->fsp_name));
359 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
361 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
362 unix_ea_name, fname));
363 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
366 /* Removing a non existent attribute always succeeds. */
367 if (ret == -1 && errno == ENOATTR) {
368 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
374 if (fsp && (fsp->fh->fd != -1)) {
375 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
376 unix_ea_name, fsp->fsp_name));
377 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
378 ea_list->ea.value.data, ea_list->ea.value.length, 0);
380 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
381 unix_ea_name, fname));
382 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
383 ea_list->ea.value.data, ea_list->ea.value.length, 0);
389 if (errno == ENOTSUP) {
390 return NT_STATUS_EAS_NOT_SUPPORTED;
393 return map_nt_error_from_unix(errno);
399 /****************************************************************************
400 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
401 ****************************************************************************/
403 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
405 struct ea_list *ea_list_head = NULL;
408 while (offset + 2 < data_size) {
409 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
410 unsigned int namelen = CVAL(pdata,offset);
412 offset++; /* Go past the namelen byte. */
414 /* integer wrap paranioa. */
415 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
416 (offset > data_size) || (namelen > data_size) ||
417 (offset + namelen >= data_size)) {
420 /* Ensure the name is null terminated. */
421 if (pdata[offset + namelen] != '\0') {
424 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
429 offset += (namelen + 1); /* Go past the name + terminating zero. */
430 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
431 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
437 /****************************************************************************
438 Read one EA list entry from the buffer.
439 ****************************************************************************/
441 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
443 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
445 unsigned int namelen;
455 eal->ea.flags = CVAL(pdata,0);
456 namelen = CVAL(pdata,1);
457 val_len = SVAL(pdata,2);
459 if (4 + namelen + 1 + val_len > data_size) {
463 /* Ensure the name is null terminated. */
464 if (pdata[namelen + 4] != '\0') {
467 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
472 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
473 if (!eal->ea.value.data) {
477 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
479 /* Ensure we're null terminated just in case we print the value. */
480 eal->ea.value.data[val_len] = '\0';
481 /* But don't count the null. */
482 eal->ea.value.length--;
485 *pbytes_used = 4 + namelen + 1 + val_len;
488 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
489 dump_data(10, eal->ea.value.data, eal->ea.value.length);
494 /****************************************************************************
495 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
496 ****************************************************************************/
498 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
500 struct ea_list *ea_list_head = NULL;
502 size_t bytes_used = 0;
504 while (offset < data_size) {
505 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
511 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
512 offset += bytes_used;
518 /****************************************************************************
519 Count the total EA size needed.
520 ****************************************************************************/
522 static size_t ea_list_size(struct ea_list *ealist)
525 struct ea_list *listp;
528 for (listp = ealist; listp; listp = listp->next) {
529 push_ascii_fstring(dos_ea_name, listp->ea.name);
530 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
532 /* Add on 4 for total length. */
540 /****************************************************************************
541 Return a union of EA's from a file list and a list of names.
542 The TALLOC context for the two lists *MUST* be identical as we steal
543 memory from one list to add to another. JRA.
544 ****************************************************************************/
546 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
548 struct ea_list *nlistp, *flistp;
550 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
551 for (flistp = file_list; flistp; flistp = flistp->next) {
552 if (strequal(nlistp->ea.name, flistp->ea.name)) {
558 /* Copy the data from this entry. */
559 nlistp->ea.flags = flistp->ea.flags;
560 nlistp->ea.value = flistp->ea.value;
563 nlistp->ea.flags = 0;
564 ZERO_STRUCT(nlistp->ea.value);
568 *total_ea_len = ea_list_size(name_list);
572 /****************************************************************************
573 Send the required number of replies back.
574 We assume all fields other than the data fields are
575 set correctly for the type of call.
576 HACK ! Always assumes smb_setup field is zero.
577 ****************************************************************************/
579 void send_trans2_replies(struct smb_request *req,
586 /* As we are using a protocol > LANMAN1 then the max_send
587 variable must have been set in the sessetupX call.
588 This takes precedence over the max_xmit field in the
589 global struct. These different max_xmit variables should
590 be merged as this is now too confusing */
592 int data_to_send = datasize;
593 int params_to_send = paramsize;
595 const char *pp = params;
596 const char *pd = pdata;
597 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
598 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
599 int data_alignment_offset = 0;
600 BOOL overflow = False;
602 /* Modify the data_to_send and datasize and set the error if
603 we're trying to send more than max_data_bytes. We still send
604 the part of the packet(s) that fit. Strange, but needed
607 if (max_data_bytes > 0 && datasize > max_data_bytes) {
608 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
609 max_data_bytes, datasize ));
610 datasize = data_to_send = max_data_bytes;
614 /* If there genuinely are no parameters or data to send just send the empty packet */
616 if(params_to_send == 0 && data_to_send == 0) {
617 reply_outbuf(req, 10, 0);
618 show_msg((char *)req->outbuf);
622 /* When sending params and data ensure that both are nicely aligned */
623 /* Only do this alignment when there is also data to send - else
624 can cause NT redirector problems. */
626 if (((params_to_send % 4) != 0) && (data_to_send != 0))
627 data_alignment_offset = 4 - (params_to_send % 4);
629 /* Space is bufsize minus Netbios over TCP header minus SMB header */
630 /* The alignment_offset is to align the param bytes on an even byte
631 boundary. NT 4.0 Beta needs this to work correctly. */
633 useable_space = max_send - (smb_size
636 + data_alignment_offset);
638 /* useable_space can never be more than max_send minus the alignment offset. */
640 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
642 while (params_to_send || data_to_send) {
643 /* Calculate whether we will totally or partially fill this packet */
645 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
647 /* We can never send more than useable_space */
649 * Note that 'useable_space' does not include the alignment offsets,
650 * but we must include the alignment offsets in the calculation of
651 * the length of the data we send over the wire, as the alignment offsets
652 * are sent here. Fix from Marc_Jacobsen@hp.com.
655 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
657 reply_outbuf(req, 10, total_sent_thistime);
659 /* Set total params and data to be sent */
660 SSVAL(req->outbuf,smb_tprcnt,paramsize);
661 SSVAL(req->outbuf,smb_tdrcnt,datasize);
663 /* Calculate how many parameters and data we can fit into
664 * this packet. Parameters get precedence
667 params_sent_thistime = MIN(params_to_send,useable_space);
668 data_sent_thistime = useable_space - params_sent_thistime;
669 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
671 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
673 /* smb_proff is the offset from the start of the SMB header to the
674 parameter bytes, however the first 4 bytes of outbuf are
675 the Netbios over TCP header. Thus use smb_base() to subtract
676 them from the calculation */
678 SSVAL(req->outbuf,smb_proff,
679 ((smb_buf(req->outbuf)+alignment_offset)
680 - smb_base(req->outbuf)));
682 if(params_sent_thistime == 0)
683 SSVAL(req->outbuf,smb_prdisp,0);
685 /* Absolute displacement of param bytes sent in this packet */
686 SSVAL(req->outbuf,smb_prdisp,pp - params);
688 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
689 if(data_sent_thistime == 0) {
690 SSVAL(req->outbuf,smb_droff,0);
691 SSVAL(req->outbuf,smb_drdisp, 0);
693 /* The offset of the data bytes is the offset of the
694 parameter bytes plus the number of parameters being sent this time */
695 SSVAL(req->outbuf, smb_droff,
696 ((smb_buf(req->outbuf)+alignment_offset)
697 - smb_base(req->outbuf))
698 + params_sent_thistime + data_alignment_offset);
699 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
702 /* Initialize the padding for alignment */
704 if (alignment_offset != 0) {
705 memset(smb_buf(req->outbuf), 0, alignment_offset);
708 /* Copy the param bytes into the packet */
710 if(params_sent_thistime) {
711 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
712 params_sent_thistime);
715 /* Copy in the data bytes */
716 if(data_sent_thistime) {
717 if (data_alignment_offset != 0) {
718 memset((smb_buf(req->outbuf)+alignment_offset+
719 params_sent_thistime), 0,
720 data_alignment_offset);
722 memcpy(smb_buf(req->outbuf)+alignment_offset
723 +params_sent_thistime+data_alignment_offset,
724 pd,data_sent_thistime);
727 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
728 params_sent_thistime, data_sent_thistime, useable_space));
729 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
730 params_to_send, data_to_send, paramsize, datasize));
733 error_packet_set((char *)req->outbuf,
734 ERRDOS,ERRbufferoverflow,
735 STATUS_BUFFER_OVERFLOW,
739 /* Send the packet */
740 show_msg((char *)req->outbuf);
741 if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
742 exit_server_cleanly("send_trans2_replies: send_smb failed.");
744 TALLOC_FREE(req->outbuf);
746 pp += params_sent_thistime;
747 pd += data_sent_thistime;
749 params_to_send -= params_sent_thistime;
750 data_to_send -= data_sent_thistime;
753 if(params_to_send < 0 || data_to_send < 0) {
754 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
755 params_to_send, data_to_send));
763 /****************************************************************************
764 Reply to a TRANSACT2_OPEN.
765 ****************************************************************************/
767 static void call_trans2open(connection_struct *conn,
768 struct smb_request *req,
769 char **pparams, int total_params,
770 char **ppdata, int total_data,
771 unsigned int max_data_bytes)
773 char *params = *pparams;
774 char *pdata = *ppdata;
779 BOOL return_additional_info;
790 SMB_STRUCT_STAT sbuf;
793 struct ea_list *ea_list = NULL;
798 uint32 create_disposition;
799 uint32 create_options = 0;
800 TALLOC_CTX *ctx = talloc_tos();
803 * Ensure we have enough parameters to perform the operation.
806 if (total_params < 29) {
807 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
811 flags = SVAL(params, 0);
812 deny_mode = SVAL(params, 2);
813 open_attr = SVAL(params,6);
814 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
815 if (oplock_request) {
816 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
820 return_additional_info = BITSETW(params,0);
821 open_sattr = SVAL(params, 4);
822 open_time = make_unix_date3(params+8);
824 open_ofun = SVAL(params,12);
825 open_size = IVAL(params,14);
829 reply_doserror(req, ERRSRV, ERRaccess);
833 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
834 total_params - 28, STR_TERMINATE,
836 if (!NT_STATUS_IS_OK(status)) {
837 reply_nterror(req, status);
841 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
842 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
843 (unsigned int)open_ofun, open_size));
845 /* XXXX we need to handle passed times, sattr and flags */
847 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
848 if (!NT_STATUS_IS_OK(status)) {
849 reply_nterror(req, status);
853 status = check_name(conn, fname);
854 if (!NT_STATUS_IS_OK(status)) {
855 reply_nterror(req, status);
859 if (open_ofun == 0) {
860 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
864 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
869 reply_doserror(req, ERRDOS, ERRbadaccess);
873 /* Any data in this call is an EA list. */
874 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
875 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
879 if (total_data != 4) {
880 if (total_data < 10) {
881 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
885 if (IVAL(pdata,0) > total_data) {
886 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
887 IVAL(pdata,0), (unsigned int)total_data));
888 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
892 ea_list = read_ea_list(talloc_tos(), pdata + 4,
895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
898 } else if (IVAL(pdata,0) != 4) {
899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
903 status = open_file_ntcreate(conn, req, fname, &sbuf,
912 if (!NT_STATUS_IS_OK(status)) {
913 if (open_was_deferred(req->mid)) {
914 /* We have re-scheduled this call. */
917 reply_openerror(req, status);
921 size = get_file_size(sbuf);
922 fattr = dos_mode(conn,fname,&sbuf);
923 mtime = sbuf.st_mtime;
926 close_file(fsp,ERROR_CLOSE);
927 reply_doserror(req, ERRDOS,ERRnoaccess);
931 /* Save the requested allocation size. */
932 /* Allocate space for the file if a size hint is supplied */
933 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
934 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
935 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
936 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
937 if (fsp->is_directory) {
938 close_file(fsp,ERROR_CLOSE);
939 /* Can't set allocation size on a directory. */
940 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
943 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
944 close_file(fsp,ERROR_CLOSE);
945 reply_nterror(req, NT_STATUS_DISK_FULL);
949 /* Adjust size here to return the right size in the reply.
950 Windows does it this way. */
951 size = fsp->initial_allocation_size;
953 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
957 if (ea_list && smb_action == FILE_WAS_CREATED) {
958 status = set_ea(conn, fsp, fname, ea_list);
959 if (!NT_STATUS_IS_OK(status)) {
960 close_file(fsp,ERROR_CLOSE);
961 reply_nterror(req, status);
966 /* Realloc the size of parameters and data we will return */
967 *pparams = (char *)SMB_REALLOC(*pparams, 30);
968 if(*pparams == NULL ) {
969 reply_nterror(req, NT_STATUS_NO_MEMORY);
974 SSVAL(params,0,fsp->fnum);
975 SSVAL(params,2,fattr);
976 srv_put_dos_date2(params,4, mtime);
977 SIVAL(params,8, (uint32)size);
978 SSVAL(params,12,deny_mode);
979 SSVAL(params,14,0); /* open_type - file or directory. */
980 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
982 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
983 smb_action |= EXTENDED_OPLOCK_GRANTED;
986 SSVAL(params,18,smb_action);
989 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
991 SIVAL(params,20,inode);
992 SSVAL(params,24,0); /* Padding. */
994 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
995 SIVAL(params, 26, ea_size);
997 SIVAL(params, 26, 0);
1000 /* Send the required number of replies */
1001 send_trans2_replies(req, params, 30, *ppdata, 0, max_data_bytes);
1004 /*********************************************************
1005 Routine to check if a given string matches exactly.
1006 as a special case a mask of "." does NOT match. That
1007 is required for correct wildcard semantics
1008 Case can be significant or not.
1009 **********************************************************/
1011 static BOOL exact_match(connection_struct *conn,
1015 if (mask[0] == '.' && mask[1] == 0)
1017 if (conn->case_sensitive)
1018 return strcmp(str,mask)==0;
1019 if (StrCaseCmp(str,mask) != 0) {
1022 if (dptr_has_wild(conn->dirptr)) {
1028 /****************************************************************************
1029 Return the filetype for UNIX extensions.
1030 ****************************************************************************/
1032 static uint32 unix_filetype(mode_t mode)
1035 return UNIX_TYPE_FILE;
1036 else if(S_ISDIR(mode))
1037 return UNIX_TYPE_DIR;
1039 else if(S_ISLNK(mode))
1040 return UNIX_TYPE_SYMLINK;
1043 else if(S_ISCHR(mode))
1044 return UNIX_TYPE_CHARDEV;
1047 else if(S_ISBLK(mode))
1048 return UNIX_TYPE_BLKDEV;
1051 else if(S_ISFIFO(mode))
1052 return UNIX_TYPE_FIFO;
1055 else if(S_ISSOCK(mode))
1056 return UNIX_TYPE_SOCKET;
1059 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1060 return UNIX_TYPE_UNKNOWN;
1063 /****************************************************************************
1064 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1065 ****************************************************************************/
1067 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1069 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1070 SMB_STRUCT_STAT *psbuf,
1072 enum perm_type ptype,
1077 if (perms == SMB_MODE_NO_CHANGE) {
1078 if (!VALID_STAT(*psbuf)) {
1079 return NT_STATUS_INVALID_PARAMETER;
1081 *ret_perms = psbuf->st_mode;
1082 return NT_STATUS_OK;
1086 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1087 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1088 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1089 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1090 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1091 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1092 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1093 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1094 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1096 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1099 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1102 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1107 /* Apply mode mask */
1108 ret &= lp_create_mask(SNUM(conn));
1109 /* Add in force bits */
1110 ret |= lp_force_create_mode(SNUM(conn));
1113 ret &= lp_dir_mask(SNUM(conn));
1114 /* Add in force bits */
1115 ret |= lp_force_dir_mode(SNUM(conn));
1117 case PERM_EXISTING_FILE:
1118 /* Apply mode mask */
1119 ret &= lp_security_mask(SNUM(conn));
1120 /* Add in force bits */
1121 ret |= lp_force_security_mode(SNUM(conn));
1123 case PERM_EXISTING_DIR:
1124 /* Apply mode mask */
1125 ret &= lp_dir_security_mask(SNUM(conn));
1126 /* Add in force bits */
1127 ret |= lp_force_dir_security_mode(SNUM(conn));
1132 return NT_STATUS_OK;
1135 /****************************************************************************
1136 Get a level dependent lanman2 dir entry.
1137 ****************************************************************************/
1139 static BOOL get_lanman2_dir_entry(TALLOC_CTX *ctx,
1140 connection_struct *conn,
1142 const char *path_mask,
1145 int requires_resume_key,
1150 int space_remaining,
1152 BOOL *got_exact_match,
1153 int *last_entry_off,
1154 struct ea_list *name_list)
1158 SMB_STRUCT_STAT sbuf;
1159 const char *mask = NULL;
1160 char *pathreal = NULL;
1161 const char *fname = NULL;
1162 char *p, *q, *pdata = *ppdata;
1166 SMB_OFF_T file_size = 0;
1167 SMB_BIG_UINT allocation_size = 0;
1169 struct timespec mdate_ts, adate_ts, create_date_ts;
1170 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1172 char *last_entry_ptr;
1174 uint32 nt_extmode; /* Used for NT connections instead of mode */
1175 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1176 BOOL check_mangled_names = lp_manglednames(conn->params);
1177 char mangled_name[13]; /* mangled 8.3 name. */
1179 *out_of_space = False;
1180 *got_exact_match = False;
1182 ZERO_STRUCT(mdate_ts);
1183 ZERO_STRUCT(adate_ts);
1184 ZERO_STRUCT(create_date_ts);
1186 if (!conn->dirptr) {
1190 p = strrchr_m(path_mask,'/');
1193 mask = talloc_strdup(ctx,"*.*");
1203 BOOL ms_dfs_link = False;
1205 /* Needed if we run out of space */
1206 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1207 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1210 * Due to bugs in NT client redirectors we are not using
1211 * resume keys any more - set them to zero.
1212 * Check out the related comments in findfirst/findnext.
1218 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1219 (long)conn->dirptr,curr_dirpos));
1226 * fname may get mangled, dname is never mangled.
1227 * Whenever we're accessing the filesystem we use
1228 * pathreal which is composed from dname.
1234 /* Mangle fname if it's an illegal name. */
1235 if (mangle_must_mangle(dname,conn->params)) {
1236 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1237 continue; /* Error - couldn't mangle. */
1239 fname = mangled_name;
1242 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1243 got_match = mask_match(fname, mask, conn->case_sensitive);
1246 if(!got_match && check_mangled_names &&
1247 !mangle_is_8_3(fname, False, conn->params)) {
1249 * It turns out that NT matches wildcards against
1250 * both long *and* short names. This may explain some
1251 * of the wildcard wierdness from old DOS clients
1252 * that some people have been seeing.... JRA.
1254 /* Force the mangling into 8.3. */
1255 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1256 continue; /* Error - couldn't mangle. */
1259 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1260 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1265 BOOL isdots = (ISDOT(dname) || ISDOTDOT(dname));
1267 if (dont_descend && !isdots) {
1273 pathreal = talloc_asprintf(ctx,
1278 pathreal = talloc_asprintf(ctx,
1288 if (INFO_LEVEL_IS_UNIX(info_level)) {
1289 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1290 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1291 pathreal,strerror(errno)));
1292 TALLOC_FREE(pathreal);
1295 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1296 /* Needed to show the msdfs symlinks as
1299 if(lp_host_msdfs() &&
1300 lp_msdfs_root(SNUM(conn)) &&
1301 ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) {
1302 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1305 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1309 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1310 pathreal,strerror(errno)));
1311 TALLOC_FREE(pathreal);
1317 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1319 mode = dos_mode(conn,pathreal,&sbuf);
1322 if (!dir_check_ftype(conn,mode,dirtype)) {
1323 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1324 TALLOC_FREE(pathreal);
1328 if (!(mode & aDIR)) {
1329 file_size = get_file_size(sbuf);
1331 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1333 mdate_ts = get_mtimespec(&sbuf);
1334 adate_ts = get_atimespec(&sbuf);
1335 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1337 if (lp_dos_filetime_resolution(SNUM(conn))) {
1338 dos_filetime_timespec(&create_date_ts);
1339 dos_filetime_timespec(&mdate_ts);
1340 dos_filetime_timespec(&adate_ts);
1343 create_date = convert_timespec_to_time_t(create_date_ts);
1344 mdate = convert_timespec_to_time_t(mdate_ts);
1345 adate = convert_timespec_to_time_t(adate_ts);
1347 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1351 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1358 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1360 switch (info_level) {
1361 case SMB_FIND_INFO_STANDARD:
1362 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1363 if(requires_resume_key) {
1367 srv_put_dos_date2(p,0,create_date);
1368 srv_put_dos_date2(p,4,adate);
1369 srv_put_dos_date2(p,8,mdate);
1370 SIVAL(p,12,(uint32)file_size);
1371 SIVAL(p,16,(uint32)allocation_size);
1375 p += align_string(pdata, p, 0);
1376 len = srvstr_push(base_data, flags2, p,
1377 fname, PTR_DIFF(end_data, p),
1379 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1381 SCVAL(nameptr, -1, len - 2);
1383 SCVAL(nameptr, -1, 0);
1387 SCVAL(nameptr, -1, len - 1);
1389 SCVAL(nameptr, -1, 0);
1395 case SMB_FIND_EA_SIZE:
1396 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1397 if(requires_resume_key) {
1401 srv_put_dos_date2(p,0,create_date);
1402 srv_put_dos_date2(p,4,adate);
1403 srv_put_dos_date2(p,8,mdate);
1404 SIVAL(p,12,(uint32)file_size);
1405 SIVAL(p,16,(uint32)allocation_size);
1408 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1409 SIVAL(p,22,ea_size); /* Extended attributes */
1413 len = srvstr_push(base_data, flags2,
1414 p, fname, PTR_DIFF(end_data, p),
1415 STR_TERMINATE | STR_NOALIGN);
1416 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1429 SCVAL(nameptr,0,len);
1431 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1434 case SMB_FIND_EA_LIST:
1436 struct ea_list *file_list = NULL;
1439 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1443 if(requires_resume_key) {
1447 srv_put_dos_date2(p,0,create_date);
1448 srv_put_dos_date2(p,4,adate);
1449 srv_put_dos_date2(p,8,mdate);
1450 SIVAL(p,12,(uint32)file_size);
1451 SIVAL(p,16,(uint32)allocation_size);
1453 p += 22; /* p now points to the EA area. */
1455 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1456 name_list = ea_list_union(name_list, file_list, &ea_len);
1458 /* We need to determine if this entry will fit in the space available. */
1459 /* Max string size is 255 bytes. */
1460 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1461 /* Move the dirptr back to prev_dirpos */
1462 dptr_SeekDir(conn->dirptr, prev_dirpos);
1463 *out_of_space = True;
1464 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1465 return False; /* Not finished - just out of space */
1468 /* Push the ea_data followed by the name. */
1469 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1471 len = srvstr_push(base_data, flags2,
1472 p + 1, fname, PTR_DIFF(end_data, p),
1473 STR_TERMINATE | STR_NOALIGN);
1474 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1487 SCVAL(nameptr,0,len);
1489 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1493 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1494 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1495 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1497 SIVAL(p,0,reskey); p += 4;
1498 put_long_date_timespec(p,create_date_ts); p += 8;
1499 put_long_date_timespec(p,adate_ts); p += 8;
1500 put_long_date_timespec(p,mdate_ts); p += 8;
1501 put_long_date_timespec(p,mdate_ts); p += 8;
1502 SOFF_T(p,0,file_size); p += 8;
1503 SOFF_T(p,0,allocation_size); p += 8;
1504 SIVAL(p,0,nt_extmode); p += 4;
1505 q = p; p += 4; /* q is placeholder for name length. */
1507 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1508 SIVAL(p,0,ea_size); /* Extended attributes */
1511 /* Clear the short name buffer. This is
1512 * IMPORTANT as not doing so will trigger
1513 * a Win2k client bug. JRA.
1515 if (!was_8_3 && check_mangled_names) {
1516 if (!name_to_8_3(fname,mangled_name,True,
1518 /* Error - mangle failed ! */
1519 memset(mangled_name,'\0',12);
1521 mangled_name[12] = 0;
1522 len = srvstr_push(base_data, flags2,
1523 p+2, mangled_name, 24,
1524 STR_UPPER|STR_UNICODE);
1526 memset(p + 2 + len,'\0',24 - len);
1533 len = srvstr_push(base_data, flags2, p,
1534 fname, PTR_DIFF(end_data, p),
1535 STR_TERMINATE_ASCII);
1538 SIVAL(p,0,0); /* Ensure any padding is null. */
1539 len = PTR_DIFF(p, pdata);
1540 len = (len + 3) & ~3;
1545 case SMB_FIND_FILE_DIRECTORY_INFO:
1546 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1548 SIVAL(p,0,reskey); p += 4;
1549 put_long_date_timespec(p,create_date_ts); p += 8;
1550 put_long_date_timespec(p,adate_ts); p += 8;
1551 put_long_date_timespec(p,mdate_ts); p += 8;
1552 put_long_date_timespec(p,mdate_ts); p += 8;
1553 SOFF_T(p,0,file_size); p += 8;
1554 SOFF_T(p,0,allocation_size); p += 8;
1555 SIVAL(p,0,nt_extmode); p += 4;
1556 len = srvstr_push(base_data, flags2,
1557 p + 4, fname, PTR_DIFF(end_data, p),
1558 STR_TERMINATE_ASCII);
1561 SIVAL(p,0,0); /* Ensure any padding is null. */
1562 len = PTR_DIFF(p, pdata);
1563 len = (len + 3) & ~3;
1568 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1569 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1571 SIVAL(p,0,reskey); p += 4;
1572 put_long_date_timespec(p,create_date_ts); p += 8;
1573 put_long_date_timespec(p,adate_ts); p += 8;
1574 put_long_date_timespec(p,mdate_ts); p += 8;
1575 put_long_date_timespec(p,mdate_ts); p += 8;
1576 SOFF_T(p,0,file_size); p += 8;
1577 SOFF_T(p,0,allocation_size); p += 8;
1578 SIVAL(p,0,nt_extmode); p += 4;
1579 q = p; p += 4; /* q is placeholder for name length. */
1581 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1582 SIVAL(p,0,ea_size); /* Extended attributes */
1585 len = srvstr_push(base_data, flags2, p,
1586 fname, PTR_DIFF(end_data, p),
1587 STR_TERMINATE_ASCII);
1591 SIVAL(p,0,0); /* Ensure any padding is null. */
1592 len = PTR_DIFF(p, pdata);
1593 len = (len + 3) & ~3;
1598 case SMB_FIND_FILE_NAMES_INFO:
1599 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1601 SIVAL(p,0,reskey); p += 4;
1603 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1604 acl on a dir (tridge) */
1605 len = srvstr_push(base_data, flags2, p,
1606 fname, PTR_DIFF(end_data, p),
1607 STR_TERMINATE_ASCII);
1610 SIVAL(p,0,0); /* Ensure any padding is null. */
1611 len = PTR_DIFF(p, pdata);
1612 len = (len + 3) & ~3;
1617 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1618 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1620 SIVAL(p,0,reskey); p += 4;
1621 put_long_date_timespec(p,create_date_ts); p += 8;
1622 put_long_date_timespec(p,adate_ts); p += 8;
1623 put_long_date_timespec(p,mdate_ts); p += 8;
1624 put_long_date_timespec(p,mdate_ts); p += 8;
1625 SOFF_T(p,0,file_size); p += 8;
1626 SOFF_T(p,0,allocation_size); p += 8;
1627 SIVAL(p,0,nt_extmode); p += 4;
1628 q = p; p += 4; /* q is placeholder for name length. */
1630 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1631 SIVAL(p,0,ea_size); /* Extended attributes */
1634 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1635 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1636 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1637 len = srvstr_push(base_data, flags2, p,
1638 fname, PTR_DIFF(end_data, p),
1639 STR_TERMINATE_ASCII);
1642 SIVAL(p,0,0); /* Ensure any padding is null. */
1643 len = PTR_DIFF(p, pdata);
1644 len = (len + 3) & ~3;
1649 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1650 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1651 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1653 SIVAL(p,0,reskey); p += 4;
1654 put_long_date_timespec(p,create_date_ts); p += 8;
1655 put_long_date_timespec(p,adate_ts); p += 8;
1656 put_long_date_timespec(p,mdate_ts); p += 8;
1657 put_long_date_timespec(p,mdate_ts); p += 8;
1658 SOFF_T(p,0,file_size); p += 8;
1659 SOFF_T(p,0,allocation_size); p += 8;
1660 SIVAL(p,0,nt_extmode); p += 4;
1661 q = p; p += 4; /* q is placeholder for name length */
1663 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1664 SIVAL(p,0,ea_size); /* Extended attributes */
1667 /* Clear the short name buffer. This is
1668 * IMPORTANT as not doing so will trigger
1669 * a Win2k client bug. JRA.
1671 if (!was_8_3 && check_mangled_names) {
1672 if (!name_to_8_3(fname,mangled_name,True,
1674 /* Error - mangle failed ! */
1675 memset(mangled_name,'\0',12);
1677 mangled_name[12] = 0;
1678 len = srvstr_push(base_data, flags2,
1679 p+2, mangled_name, 24,
1680 STR_UPPER|STR_UNICODE);
1683 memset(p + 2 + len,'\0',24 - len);
1690 SSVAL(p,0,0); p += 2; /* Reserved ? */
1691 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1692 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1693 len = srvstr_push(base_data, flags2, p,
1694 fname, PTR_DIFF(end_data, p),
1695 STR_TERMINATE_ASCII);
1698 SIVAL(p,0,0); /* Ensure any padding is null. */
1699 len = PTR_DIFF(p, pdata);
1700 len = (len + 3) & ~3;
1705 /* CIFS UNIX Extension. */
1707 case SMB_FIND_FILE_UNIX:
1708 case SMB_FIND_FILE_UNIX_INFO2:
1710 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1712 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1714 if (info_level == SMB_FIND_FILE_UNIX) {
1715 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1716 p = store_file_unix_basic(conn, p,
1718 len = srvstr_push(base_data, flags2, p,
1719 fname, PTR_DIFF(end_data, p),
1722 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1723 p = store_file_unix_basic_info2(conn, p,
1727 len = srvstr_push(base_data, flags2, p, fname,
1728 PTR_DIFF(end_data, p), 0);
1729 SIVAL(nameptr, 0, len);
1733 SIVAL(p,0,0); /* Ensure any padding is null. */
1735 len = PTR_DIFF(p, pdata);
1736 len = (len + 3) & ~3;
1737 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1739 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1748 if (PTR_DIFF(p,pdata) > space_remaining) {
1749 /* Move the dirptr back to prev_dirpos */
1750 dptr_SeekDir(conn->dirptr, prev_dirpos);
1751 *out_of_space = True;
1752 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1753 return False; /* Not finished - just out of space */
1756 /* Setup the last entry pointer, as an offset from base_data */
1757 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1758 /* Advance the data pointer to the next slot */
1764 /****************************************************************************
1765 Reply to a TRANS2_FINDFIRST.
1766 ****************************************************************************/
1768 static void call_trans2findfirst(connection_struct *conn,
1769 struct smb_request *req,
1770 char **pparams, int total_params,
1771 char **ppdata, int total_data,
1772 unsigned int max_data_bytes)
1774 /* We must be careful here that we don't return more than the
1775 allowed number of data bytes. If this means returning fewer than
1776 maxentries then so be it. We assume that the redirector has
1777 enough room for the fixed number of parameter bytes it has
1779 char *params = *pparams;
1780 char *pdata = *ppdata;
1784 uint16 findfirst_flags;
1785 BOOL close_after_first;
1787 BOOL requires_resume_key;
1789 char *directory = NULL;
1790 const char *mask = NULL;
1792 int last_entry_off=0;
1796 BOOL finished = False;
1797 BOOL dont_descend = False;
1798 BOOL out_of_space = False;
1799 int space_remaining;
1800 BOOL mask_contains_wcard = False;
1801 SMB_STRUCT_STAT sbuf;
1802 struct ea_list *ea_list = NULL;
1803 NTSTATUS ntstatus = NT_STATUS_OK;
1804 TALLOC_CTX *ctx = talloc_tos();
1806 if (total_params < 13) {
1807 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1811 dirtype = SVAL(params,0);
1812 maxentries = SVAL(params,2);
1813 findfirst_flags = SVAL(params,4);
1814 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1815 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1816 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1817 info_level = SVAL(params,6);
1819 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1820 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1821 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1822 info_level, max_data_bytes));
1825 /* W2K3 seems to treat zero as 1. */
1829 switch (info_level) {
1830 case SMB_FIND_INFO_STANDARD:
1831 case SMB_FIND_EA_SIZE:
1832 case SMB_FIND_EA_LIST:
1833 case SMB_FIND_FILE_DIRECTORY_INFO:
1834 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1835 case SMB_FIND_FILE_NAMES_INFO:
1836 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1837 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1838 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1840 case SMB_FIND_FILE_UNIX:
1841 case SMB_FIND_FILE_UNIX_INFO2:
1842 if (!lp_unix_extensions()) {
1843 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1848 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1852 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1853 params+12, total_params - 12,
1854 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1855 if (!NT_STATUS_IS_OK(ntstatus)) {
1856 reply_nterror(req, ntstatus);
1860 ntstatus = resolve_dfspath_wcard(ctx, conn,
1861 req->flags2 & FLAGS2_DFS_PATHNAMES,
1864 &mask_contains_wcard);
1865 if (!NT_STATUS_IS_OK(ntstatus)) {
1866 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1867 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1868 ERRSRV, ERRbadpath);
1871 reply_nterror(req, ntstatus);
1875 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1876 if (!NT_STATUS_IS_OK(ntstatus)) {
1877 reply_nterror(req, ntstatus);
1881 ntstatus = check_name(conn, directory);
1882 if (!NT_STATUS_IS_OK(ntstatus)) {
1883 reply_nterror(req, ntstatus);
1887 p = strrchr_m(directory,'/');
1889 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1890 if((directory[0] == '.') && (directory[1] == '\0')) {
1892 mask_contains_wcard = True;
1896 directory = talloc_strdup(talloc_tos(), "./");
1898 reply_nterror(req, NT_STATUS_NO_MEMORY);
1906 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1908 if (info_level == SMB_FIND_EA_LIST) {
1911 if (total_data < 4) {
1912 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1916 ea_size = IVAL(pdata,0);
1917 if (ea_size != total_data) {
1918 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1919 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1920 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1924 if (!lp_ea_support(SNUM(conn))) {
1925 reply_doserror(req, ERRDOS, ERReasnotsupported);
1929 /* Pull out the list of names. */
1930 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1932 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1937 *ppdata = (char *)SMB_REALLOC(
1938 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1939 if(*ppdata == NULL ) {
1940 reply_nterror(req, NT_STATUS_NO_MEMORY);
1944 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1946 /* Realloc the params space */
1947 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1948 if (*pparams == NULL) {
1949 reply_nterror(req, NT_STATUS_NO_MEMORY);
1954 /* Save the wildcard match and attribs we are using on this directory -
1955 needed as lanman2 assumes these are being saved between calls */
1957 ntstatus = dptr_create(conn,
1963 mask_contains_wcard,
1967 if (!NT_STATUS_IS_OK(ntstatus)) {
1968 reply_nterror(req, ntstatus);
1972 dptr_num = dptr_dnum(conn->dirptr);
1973 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1975 /* We don't need to check for VOL here as this is returned by
1976 a different TRANS2 call. */
1978 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1979 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1980 dont_descend = True;
1983 space_remaining = max_data_bytes;
1984 out_of_space = False;
1986 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1987 BOOL got_exact_match = False;
1989 /* this is a heuristic to avoid seeking the dirptr except when
1990 absolutely necessary. It allows for a filename of about 40 chars */
1991 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1992 out_of_space = True;
1995 TALLOC_CTX *sub_ctx = talloc_stackframe();
1997 finished = !get_lanman2_dir_entry(sub_ctx,
2000 mask,dirtype,info_level,
2001 requires_resume_key,dont_descend,
2003 space_remaining, &out_of_space,
2005 &last_entry_off, ea_list);
2007 TALLOC_FREE(sub_ctx);
2010 if (finished && out_of_space)
2013 if (!finished && !out_of_space)
2017 * As an optimisation if we know we aren't looking
2018 * for a wildcard name (ie. the name matches the wildcard exactly)
2019 * then we can finish on any (first) match.
2020 * This speeds up large directory searches. JRA.
2026 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2029 /* Check if we can close the dirptr */
2030 if(close_after_first || (finished && close_if_end)) {
2031 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2032 dptr_close(&dptr_num);
2036 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2037 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2038 * the protocol level is less than NT1. Tested with smbclient. JRA.
2039 * This should fix the OS/2 client bug #2335.
2042 if(numentries == 0) {
2043 dptr_close(&dptr_num);
2044 if (Protocol < PROTOCOL_NT1) {
2045 reply_doserror(req, ERRDOS, ERRnofiles);
2048 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2049 ERRDOS, ERRbadfile);
2054 /* At this point pdata points to numentries directory entries. */
2056 /* Set up the return parameter block */
2057 SSVAL(params,0,dptr_num);
2058 SSVAL(params,2,numentries);
2059 SSVAL(params,4,finished);
2060 SSVAL(params,6,0); /* Never an EA error */
2061 SSVAL(params,8,last_entry_off);
2063 send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
2066 if ((! *directory) && dptr_path(dptr_num)) {
2067 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2069 reply_nterror(req, NT_STATUS_NO_MEMORY);
2073 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2074 smb_fn_name(CVAL(req->inbuf,smb_com)),
2075 mask, directory, dirtype, numentries ) );
2078 * Force a name mangle here to ensure that the
2079 * mask as an 8.3 name is top of the mangled cache.
2080 * The reasons for this are subtle. Don't remove
2081 * this code unless you know what you are doing
2082 * (see PR#13758). JRA.
2085 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2086 char mangled_name[13];
2087 name_to_8_3(mask, mangled_name, True, conn->params);
2093 /****************************************************************************
2094 Reply to a TRANS2_FINDNEXT.
2095 ****************************************************************************/
2097 static void call_trans2findnext(connection_struct *conn,
2098 struct smb_request *req,
2099 char **pparams, int total_params,
2100 char **ppdata, int total_data,
2101 unsigned int max_data_bytes)
2103 /* We must be careful here that we don't return more than the
2104 allowed number of data bytes. If this means returning fewer than
2105 maxentries then so be it. We assume that the redirector has
2106 enough room for the fixed number of parameter bytes it has
2108 char *params = *pparams;
2109 char *pdata = *ppdata;
2115 uint16 findnext_flags;
2116 BOOL close_after_request;
2118 BOOL requires_resume_key;
2120 BOOL mask_contains_wcard = False;
2121 char *resume_name = NULL;
2122 const char *mask = NULL;
2123 const char *directory = NULL;
2127 int i, last_entry_off=0;
2128 BOOL finished = False;
2129 BOOL dont_descend = False;
2130 BOOL out_of_space = False;
2131 int space_remaining;
2132 struct ea_list *ea_list = NULL;
2133 NTSTATUS ntstatus = NT_STATUS_OK;
2134 TALLOC_CTX *ctx = talloc_tos();
2136 if (total_params < 13) {
2137 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2141 dptr_num = SVAL(params,0);
2142 maxentries = SVAL(params,2);
2143 info_level = SVAL(params,4);
2144 resume_key = IVAL(params,6);
2145 findnext_flags = SVAL(params,10);
2146 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2147 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2148 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2149 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2151 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2153 total_params - 12, STR_TERMINATE, &ntstatus,
2154 &mask_contains_wcard);
2155 if (!NT_STATUS_IS_OK(ntstatus)) {
2156 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2157 complain (it thinks we're asking for the directory above the shared
2158 path or an invalid name). Catch this as the resume name is only compared, never used in
2159 a file access. JRA. */
2160 srvstr_pull_talloc(ctx, params, req->flags2,
2161 &resume_name, params+12,
2165 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2166 reply_nterror(req, ntstatus);
2171 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2172 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2173 resume_key = %d resume name = %s continue=%d level = %d\n",
2174 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2175 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2178 /* W2K3 seems to treat zero as 1. */
2182 switch (info_level) {
2183 case SMB_FIND_INFO_STANDARD:
2184 case SMB_FIND_EA_SIZE:
2185 case SMB_FIND_EA_LIST:
2186 case SMB_FIND_FILE_DIRECTORY_INFO:
2187 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2188 case SMB_FIND_FILE_NAMES_INFO:
2189 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2190 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2191 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2193 case SMB_FIND_FILE_UNIX:
2194 case SMB_FIND_FILE_UNIX_INFO2:
2195 if (!lp_unix_extensions()) {
2196 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2201 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2205 if (info_level == SMB_FIND_EA_LIST) {
2208 if (total_data < 4) {
2209 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2213 ea_size = IVAL(pdata,0);
2214 if (ea_size != total_data) {
2215 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2216 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2217 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2221 if (!lp_ea_support(SNUM(conn))) {
2222 reply_doserror(req, ERRDOS, ERReasnotsupported);
2226 /* Pull out the list of names. */
2227 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2229 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2234 *ppdata = (char *)SMB_REALLOC(
2235 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2236 if(*ppdata == NULL) {
2237 reply_nterror(req, NT_STATUS_NO_MEMORY);
2242 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2244 /* Realloc the params space */
2245 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2246 if(*pparams == NULL ) {
2247 reply_nterror(req, NT_STATUS_NO_MEMORY);
2253 /* Check that the dptr is valid */
2254 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2255 reply_doserror(req, ERRDOS, ERRnofiles);
2259 string_set(&conn->dirpath,dptr_path(dptr_num));
2261 /* Get the wildcard mask from the dptr */
2262 if((p = dptr_wcard(dptr_num))== NULL) {
2263 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2264 reply_doserror(req, ERRDOS, ERRnofiles);
2269 directory = conn->dirpath;
2271 /* Get the attr mask from the dptr */
2272 dirtype = dptr_attr(dptr_num);
2274 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2275 dptr_num, mask, dirtype,
2277 dptr_TellDir(conn->dirptr)));
2279 /* We don't need to check for VOL here as this is returned by
2280 a different TRANS2 call. */
2282 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2283 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2284 dont_descend = True;
2287 space_remaining = max_data_bytes;
2288 out_of_space = False;
2291 * Seek to the correct position. We no longer use the resume key but
2292 * depend on the last file name instead.
2295 if(*resume_name && !continue_bit) {
2298 long current_pos = 0;
2300 * Remember, name_to_8_3 is called by
2301 * get_lanman2_dir_entry(), so the resume name
2302 * could be mangled. Ensure we check the unmangled name.
2305 if (mangle_is_mangled(resume_name, conn->params)) {
2306 char *new_resume_name = NULL;
2307 mangle_lookup_name_from_8_3(ctx,
2311 if (new_resume_name) {
2312 resume_name = new_resume_name;
2317 * Fix for NT redirector problem triggered by resume key indexes
2318 * changing between directory scans. We now return a resume key of 0
2319 * and instead look for the filename to continue from (also given
2320 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2321 * findfirst/findnext (as is usual) then the directory pointer
2322 * should already be at the correct place.
2325 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2326 } /* end if resume_name && !continue_bit */
2328 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2329 BOOL got_exact_match = False;
2331 /* this is a heuristic to avoid seeking the dirptr except when
2332 absolutely necessary. It allows for a filename of about 40 chars */
2333 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2334 out_of_space = True;
2337 TALLOC_CTX *sub_ctx = talloc_stackframe();
2339 finished = !get_lanman2_dir_entry(sub_ctx,
2342 mask,dirtype,info_level,
2343 requires_resume_key,dont_descend,
2345 space_remaining, &out_of_space,
2347 &last_entry_off, ea_list);
2349 TALLOC_FREE(sub_ctx);
2352 if (finished && out_of_space)
2355 if (!finished && !out_of_space)
2359 * As an optimisation if we know we aren't looking
2360 * for a wildcard name (ie. the name matches the wildcard exactly)
2361 * then we can finish on any (first) match.
2362 * This speeds up large directory searches. JRA.
2368 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2371 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2372 smb_fn_name(CVAL(req->inbuf,smb_com)),
2373 mask, directory, dirtype, numentries ) );
2375 /* Check if we can close the dirptr */
2376 if(close_after_request || (finished && close_if_end)) {
2377 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2378 dptr_close(&dptr_num); /* This frees up the saved mask */
2381 /* Set up the return parameter block */
2382 SSVAL(params,0,numentries);
2383 SSVAL(params,2,finished);
2384 SSVAL(params,4,0); /* Never an EA error */
2385 SSVAL(params,6,last_entry_off);
2387 send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata),
2393 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2395 E_md4hash(lp_servicename(SNUM(conn)),objid);
2399 /****************************************************************************
2400 Reply to a TRANS2_QFSINFO (query filesystem info).
2401 ****************************************************************************/
2403 static void call_trans2qfsinfo(connection_struct *conn,
2404 struct smb_request *req,
2405 char **pparams, int total_params,
2406 char **ppdata, int total_data,
2407 unsigned int max_data_bytes)
2409 char *pdata, *end_data;
2410 char *params = *pparams;
2414 const char *vname = volume_label(SNUM(conn));
2415 int snum = SNUM(conn);
2416 char *fstype = lp_fstype(SNUM(conn));
2419 if (total_params < 2) {
2420 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2424 info_level = SVAL(params,0);
2426 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2428 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2429 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2430 reply_doserror(req, ERRSRV, ERRinvdevice);
2434 *ppdata = (char *)SMB_REALLOC(
2435 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2436 if (*ppdata == NULL ) {
2437 reply_nterror(req, NT_STATUS_NO_MEMORY);
2442 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2443 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2445 switch (info_level) {
2446 case SMB_INFO_ALLOCATION:
2448 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2450 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2451 reply_unixerror(req, ERRHRD, ERRgeneral);
2455 block_size = lp_block_size(snum);
2456 if (bsize < block_size) {
2457 SMB_BIG_UINT factor = block_size/bsize;
2462 if (bsize > block_size) {
2463 SMB_BIG_UINT factor = bsize/block_size;
2468 bytes_per_sector = 512;
2469 sectors_per_unit = bsize/bytes_per_sector;
2471 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2472 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2473 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2475 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2476 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2477 SIVAL(pdata,l1_cUnit,dsize);
2478 SIVAL(pdata,l1_cUnitAvail,dfree);
2479 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2483 case SMB_INFO_VOLUME:
2484 /* Return volume name */
2486 * Add volume serial number - hash of a combination of
2487 * the called hostname and the service name.
2489 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2491 * Win2k3 and previous mess this up by sending a name length
2492 * one byte short. I believe only older clients (OS/2 Win9x) use
2493 * this call so try fixing this by adding a terminating null to
2494 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2498 pdata+l2_vol_szVolLabel, vname,
2499 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2500 STR_NOALIGN|STR_TERMINATE);
2501 SCVAL(pdata,l2_vol_cch,len);
2502 data_len = l2_vol_szVolLabel + len;
2503 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2504 (unsigned)st.st_ctime, len, vname));
2507 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2508 case SMB_FS_ATTRIBUTE_INFORMATION:
2511 #if defined(HAVE_SYS_QUOTAS)
2512 quota_flag = FILE_VOLUME_QUOTAS;
2515 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2516 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2517 FILE_SUPPORTS_OBJECT_IDS|
2518 FILE_UNICODE_ON_DISK|
2519 quota_flag); /* FS ATTRIBUTES */
2521 SIVAL(pdata,4,255); /* Max filename component length */
2522 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2523 and will think we can't do long filenames */
2524 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2525 PTR_DIFF(end_data, pdata+12),
2528 data_len = 12 + len;
2531 case SMB_QUERY_FS_LABEL_INFO:
2532 case SMB_FS_LABEL_INFORMATION:
2533 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2534 PTR_DIFF(end_data, pdata+4), 0);
2539 case SMB_QUERY_FS_VOLUME_INFO:
2540 case SMB_FS_VOLUME_INFORMATION:
2543 * Add volume serial number - hash of a combination of
2544 * the called hostname and the service name.
2546 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2547 (str_checksum(get_local_machine_name())<<16));
2549 /* Max label len is 32 characters. */
2550 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2551 PTR_DIFF(end_data, pdata+18),
2553 SIVAL(pdata,12,len);
2556 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2557 (int)strlen(vname),vname, lp_servicename(snum)));
2560 case SMB_QUERY_FS_SIZE_INFO:
2561 case SMB_FS_SIZE_INFORMATION:
2563 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2565 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2566 reply_unixerror(req, ERRHRD, ERRgeneral);
2569 block_size = lp_block_size(snum);
2570 if (bsize < block_size) {
2571 SMB_BIG_UINT factor = block_size/bsize;
2576 if (bsize > block_size) {
2577 SMB_BIG_UINT factor = bsize/block_size;
2582 bytes_per_sector = 512;
2583 sectors_per_unit = bsize/bytes_per_sector;
2584 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2585 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2586 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2587 SBIG_UINT(pdata,0,dsize);
2588 SBIG_UINT(pdata,8,dfree);
2589 SIVAL(pdata,16,sectors_per_unit);
2590 SIVAL(pdata,20,bytes_per_sector);
2594 case SMB_FS_FULL_SIZE_INFORMATION:
2596 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2598 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2599 reply_unixerror(req, ERRHRD, ERRgeneral);
2602 block_size = lp_block_size(snum);
2603 if (bsize < block_size) {
2604 SMB_BIG_UINT factor = block_size/bsize;
2609 if (bsize > block_size) {
2610 SMB_BIG_UINT factor = bsize/block_size;
2615 bytes_per_sector = 512;
2616 sectors_per_unit = bsize/bytes_per_sector;
2617 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2618 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2619 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2620 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2621 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2622 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2623 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2624 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2628 case SMB_QUERY_FS_DEVICE_INFO:
2629 case SMB_FS_DEVICE_INFORMATION:
2631 SIVAL(pdata,0,0); /* dev type */
2632 SIVAL(pdata,4,0); /* characteristics */
2635 #ifdef HAVE_SYS_QUOTAS
2636 case SMB_FS_QUOTA_INFORMATION:
2638 * what we have to send --metze:
2640 * Unknown1: 24 NULL bytes
2641 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2642 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2643 * Quota Flags: 2 byte :
2644 * Unknown3: 6 NULL bytes
2648 * details for Quota Flags:
2650 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2651 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2652 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2653 * 0x0001 Enable Quotas: enable quota for this fs
2657 /* we need to fake up a fsp here,
2658 * because its not send in this call
2661 SMB_NTQUOTA_STRUCT quotas;
2664 ZERO_STRUCT(quotas);
2670 if (current_user.ut.uid != 0) {
2671 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2672 lp_servicename(SNUM(conn)),conn->user));
2673 reply_doserror(req, ERRDOS, ERRnoaccess);
2677 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2678 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2679 reply_doserror(req, ERRSRV, ERRerror);
2685 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2687 /* Unknown1 24 NULL bytes*/
2688 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2689 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2690 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2692 /* Default Soft Quota 8 bytes */
2693 SBIG_UINT(pdata,24,quotas.softlim);
2695 /* Default Hard Quota 8 bytes */
2696 SBIG_UINT(pdata,32,quotas.hardlim);
2698 /* Quota flag 2 bytes */
2699 SSVAL(pdata,40,quotas.qflags);
2701 /* Unknown3 6 NULL bytes */
2707 #endif /* HAVE_SYS_QUOTAS */
2708 case SMB_FS_OBJECTID_INFORMATION:
2710 unsigned char objid[16];
2711 memcpy(pdata,create_volume_objectid(conn, objid),16);
2717 * Query the version and capabilities of the CIFS UNIX extensions
2721 case SMB_QUERY_CIFS_UNIX_INFO:
2722 if (!lp_unix_extensions()) {
2723 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2727 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2728 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2729 /* We have POSIX ACLs, pathname and locking capability. */
2730 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2731 CIFS_UNIX_POSIX_ACLS_CAP|
2732 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2733 CIFS_UNIX_FCNTL_LOCKS_CAP|
2734 CIFS_UNIX_EXTATTR_CAP|
2735 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2736 /* Ensure we don't do this on signed or sealed data. */
2737 (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2741 case SMB_QUERY_POSIX_FS_INFO:
2744 vfs_statvfs_struct svfs;
2746 if (!lp_unix_extensions()) {
2747 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2751 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2755 SIVAL(pdata,0,svfs.OptimalTransferSize);
2756 SIVAL(pdata,4,svfs.BlockSize);
2757 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2758 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2759 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2760 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2761 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2762 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2763 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2765 } else if (rc == EOPNOTSUPP) {
2766 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2768 #endif /* EOPNOTSUPP */
2770 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2771 reply_doserror(req, ERRSRV, ERRerror);
2777 case SMB_QUERY_POSIX_WHOAMI:
2783 if (!lp_unix_extensions()) {
2784 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2788 if (max_data_bytes < 40) {
2789 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2793 /* We ARE guest if global_sid_Builtin_Guests is
2794 * in our list of SIDs.
2796 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2797 current_user.nt_user_token)) {
2798 flags |= SMB_WHOAMI_GUEST;
2801 /* We are NOT guest if global_sid_Authenticated_Users
2802 * is in our list of SIDs.
2804 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2805 current_user.nt_user_token)) {
2806 flags &= ~SMB_WHOAMI_GUEST;
2809 /* NOTE: 8 bytes for UID/GID, irrespective of native
2810 * platform size. This matches
2811 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2813 data_len = 4 /* flags */
2820 + 4 /* pad/reserved */
2821 + (current_user.ut.ngroups * 8)
2823 + (current_user.nt_user_token->num_sids *
2827 SIVAL(pdata, 0, flags);
2828 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2829 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2830 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2833 if (data_len >= max_data_bytes) {
2834 /* Potential overflow, skip the GIDs and SIDs. */
2836 SIVAL(pdata, 24, 0); /* num_groups */
2837 SIVAL(pdata, 28, 0); /* num_sids */
2838 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2839 SIVAL(pdata, 36, 0); /* reserved */
2845 SIVAL(pdata, 24, current_user.ut.ngroups);
2847 current_user.nt_user_token->num_sids);
2849 /* We walk the SID list twice, but this call is fairly
2850 * infrequent, and I don't expect that it's performance
2851 * sensitive -- jpeach
2853 for (i = 0, sid_bytes = 0;
2854 i < current_user.nt_user_token->num_sids; ++i) {
2856 sid_size(¤t_user.nt_user_token->user_sids[i]);
2859 /* SID list byte count */
2860 SIVAL(pdata, 32, sid_bytes);
2862 /* 4 bytes pad/reserved - must be zero */
2863 SIVAL(pdata, 36, 0);
2867 for (i = 0; i < current_user.ut.ngroups; ++i) {
2868 SBIG_UINT(pdata, data_len,
2869 (SMB_BIG_UINT)current_user.ut.groups[i]);
2875 i < current_user.nt_user_token->num_sids; ++i) {
2877 sid_size(¤t_user.nt_user_token->user_sids[i]);
2879 sid_linearize(pdata + data_len, sid_len,
2880 ¤t_user.nt_user_token->user_sids[i]);
2881 data_len += sid_len;
2887 case SMB_MAC_QUERY_FS_INFO:
2889 * Thursby MAC extension... ONLY on NTFS filesystems
2890 * once we do streams then we don't need this
2892 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2894 SIVAL(pdata,84,0x100); /* Don't support mac... */
2899 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2904 send_trans2_replies(req, params, 0, pdata, data_len,
2907 DEBUG( 4, ( "%s info_level = %d\n",
2908 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2913 /****************************************************************************
2914 Reply to a TRANS2_SETFSINFO (set filesystem info).
2915 ****************************************************************************/
2917 static void call_trans2setfsinfo(connection_struct *conn,
2918 struct smb_request *req,
2919 char **pparams, int total_params,
2920 char **ppdata, int total_data,
2921 unsigned int max_data_bytes)
2923 char *pdata = *ppdata;
2924 char *params = *pparams;
2927 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2930 if (total_params < 4) {
2931 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2933 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2937 info_level = SVAL(params,2);
2939 switch(info_level) {
2940 case SMB_SET_CIFS_UNIX_INFO:
2942 uint16 client_unix_major;
2943 uint16 client_unix_minor;
2944 uint32 client_unix_cap_low;
2945 uint32 client_unix_cap_high;
2947 if (!lp_unix_extensions()) {
2949 NT_STATUS_INVALID_LEVEL);
2953 /* There should be 12 bytes of capabilities set. */
2954 if (total_data < 8) {
2957 NT_STATUS_INVALID_PARAMETER);
2960 client_unix_major = SVAL(pdata,0);
2961 client_unix_minor = SVAL(pdata,2);
2962 client_unix_cap_low = IVAL(pdata,4);
2963 client_unix_cap_high = IVAL(pdata,8);
2964 /* Just print these values for now. */
2965 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2966 cap_low = 0x%x, cap_high = 0x%x\n",
2967 (unsigned int)client_unix_major,
2968 (unsigned int)client_unix_minor,
2969 (unsigned int)client_unix_cap_low,
2970 (unsigned int)client_unix_cap_high ));
2972 /* Here is where we must switch to posix pathname processing... */
2973 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2974 lp_set_posix_pathnames();
2975 mangle_change_to_posix();
2978 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2979 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2980 /* Client that knows how to do posix locks,
2981 * but not posix open/mkdir operations. Set a
2982 * default type for read/write checks. */
2984 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2989 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2992 size_t param_len = 0;
2993 size_t data_len = total_data;
2995 if (!lp_unix_extensions()) {
2997 req, NT_STATUS_INVALID_LEVEL);
3001 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
3003 status = srv_request_encryption_setup(conn,
3004 (unsigned char **)ppdata,
3006 (unsigned char **)pparams,
3010 if (!NT_STATUS_IS_OK(status)) {
3013 * MORE_PROCESSING_REQUIRED, this used
3014 * to have special handling here.
3016 reply_nterror(req, status);
3020 send_trans2_replies(req,
3021 *pparams, param_len,
3025 if (NT_STATUS_IS_OK(status)) {
3026 /* Server-side transport encryption is now *on*. */
3027 status = srv_encryption_start(conn);
3028 if (!NT_STATUS_IS_OK(status)) {
3029 exit_server_cleanly("Failure in setting up encrypted transport");
3034 case SMB_FS_QUOTA_INFORMATION:
3036 files_struct *fsp = NULL;
3037 SMB_NTQUOTA_STRUCT quotas;
3039 ZERO_STRUCT(quotas);
3042 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3043 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3044 lp_servicename(SNUM(conn)),conn->user));
3045 reply_doserror(req, ERRSRV, ERRaccess);
3049 /* note: normaly there're 48 bytes,
3050 * but we didn't use the last 6 bytes for now
3053 fsp = file_fsp(SVAL(params,0));
3054 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3055 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3057 req, NT_STATUS_INVALID_HANDLE);
3061 if (total_data < 42) {
3062 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3066 NT_STATUS_INVALID_PARAMETER);
3070 /* unknown_1 24 NULL bytes in pdata*/
3072 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3073 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3074 #ifdef LARGE_SMB_OFF_T
3075 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3076 #else /* LARGE_SMB_OFF_T */
3077 if ((IVAL(pdata,28) != 0)&&
3078 ((quotas.softlim != 0xFFFFFFFF)||
3079 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3080 /* more than 32 bits? */
3083 NT_STATUS_INVALID_PARAMETER);
3086 #endif /* LARGE_SMB_OFF_T */
3088 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3089 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3090 #ifdef LARGE_SMB_OFF_T
3091 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3092 #else /* LARGE_SMB_OFF_T */
3093 if ((IVAL(pdata,36) != 0)&&
3094 ((quotas.hardlim != 0xFFFFFFFF)||
3095 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3096 /* more than 32 bits? */
3099 NT_STATUS_INVALID_PARAMETER);
3102 #endif /* LARGE_SMB_OFF_T */
3104 /* quota_flags 2 bytes **/
3105 quotas.qflags = SVAL(pdata,40);
3107 /* unknown_2 6 NULL bytes follow*/
3109 /* now set the quotas */
3110 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3111 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3112 reply_doserror(req, ERRSRV, ERRerror);
3119 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3121 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3127 * sending this reply works fine,
3128 * but I'm not sure it's the same
3129 * like windows do...
3132 reply_outbuf(req, 10, 0);
3135 #if defined(HAVE_POSIX_ACLS)
3136 /****************************************************************************
3137 Utility function to count the number of entries in a POSIX acl.
3138 ****************************************************************************/
3140 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3142 unsigned int ace_count = 0;
3143 int entry_id = SMB_ACL_FIRST_ENTRY;
3144 SMB_ACL_ENTRY_T entry;
3146 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3148 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3149 entry_id = SMB_ACL_NEXT_ENTRY;
3156 /****************************************************************************
3157 Utility function to marshall a POSIX acl into wire format.
3158 ****************************************************************************/
3160 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3162 int entry_id = SMB_ACL_FIRST_ENTRY;
3163 SMB_ACL_ENTRY_T entry;
3165 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3166 SMB_ACL_TAG_T tagtype;
3167 SMB_ACL_PERMSET_T permset;
3168 unsigned char perms = 0;
3169 unsigned int own_grp;
3172 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3173 entry_id = SMB_ACL_NEXT_ENTRY;
3176 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3177 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3181 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3182 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3186 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3187 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3188 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3190 SCVAL(pdata,1,perms);
3193 case SMB_ACL_USER_OBJ:
3194 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3195 own_grp = (unsigned int)pst->st_uid;
3196 SIVAL(pdata,2,own_grp);
3201 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3203 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3206 own_grp = (unsigned int)*puid;
3207 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3208 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3209 SIVAL(pdata,2,own_grp);
3213 case SMB_ACL_GROUP_OBJ:
3214 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3215 own_grp = (unsigned int)pst->st_gid;
3216 SIVAL(pdata,2,own_grp);
3221 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3223 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3226 own_grp = (unsigned int)*pgid;
3227 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3228 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3229 SIVAL(pdata,2,own_grp);
3234 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3235 SIVAL(pdata,2,0xFFFFFFFF);
3236 SIVAL(pdata,6,0xFFFFFFFF);
3239 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3240 SIVAL(pdata,2,0xFFFFFFFF);
3241 SIVAL(pdata,6,0xFFFFFFFF);
3244 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3247 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3254 /****************************************************************************
3255 Store the FILE_UNIX_BASIC info.
3256 ****************************************************************************/
3258 static char *store_file_unix_basic(connection_struct *conn,
3261 const SMB_STRUCT_STAT *psbuf)
3263 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3264 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3266 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3269 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3272 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3273 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3274 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3277 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3281 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3285 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3288 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3292 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3296 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3299 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3303 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3310 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3311 * the chflags(2) (or equivalent) flags.
3313 * XXX: this really should be behind the VFS interface. To do this, we would
3314 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3315 * Each VFS module could then implement it's own mapping as appropriate for the
3316 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3318 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3322 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3326 { UF_IMMUTABLE, EXT_IMMUTABLE },
3330 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3334 { UF_HIDDEN, EXT_HIDDEN },
3337 /* Do not remove. We need to guarantee that this array has at least one
3338 * entry to build on HP-UX.
3344 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3345 uint32 *smb_fflags, uint32 *smb_fmask)
3347 #ifdef HAVE_STAT_ST_FLAGS
3350 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3351 *smb_fmask |= info2_flags_map[i].smb_fflag;
3352 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3353 *smb_fflags |= info2_flags_map[i].smb_fflag;
3356 #endif /* HAVE_STAT_ST_FLAGS */
3359 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3360 const uint32 smb_fflags,
3361 const uint32 smb_fmask,
3364 #ifdef HAVE_STAT_ST_FLAGS
3365 uint32 max_fmask = 0;
3368 *stat_fflags = psbuf->st_flags;
3370 /* For each flags requested in smb_fmask, check the state of the
3371 * corresponding flag in smb_fflags and set or clear the matching
3375 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3376 max_fmask |= info2_flags_map[i].smb_fflag;
3377 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3378 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3379 *stat_fflags |= info2_flags_map[i].stat_fflag;
3381 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3386 /* If smb_fmask is asking to set any bits that are not supported by
3387 * our flag mappings, we should fail.
3389 if ((smb_fmask & max_fmask) != smb_fmask) {
3396 #endif /* HAVE_STAT_ST_FLAGS */
3400 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3401 * of file flags and birth (create) time.
3403 static char *store_file_unix_basic_info2(connection_struct *conn,
3406 const SMB_STRUCT_STAT *psbuf)
3408 uint32 file_flags = 0;
3409 uint32 flags_mask = 0;
3411 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3413 /* Create (birth) time 64 bit */
3414 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3417 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3418 SIVAL(pdata, 0, file_flags); /* flags */
3419 SIVAL(pdata, 4, flags_mask); /* mask */
3425 /****************************************************************************
3426 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3427 ****************************************************************************/
3429 static void call_trans2qpipeinfo(connection_struct *conn,
3430 struct smb_request *req,
3431 unsigned int tran_call,
3432 char **pparams, int total_params,
3433 char **ppdata, int total_data,
3434 unsigned int max_data_bytes)
3436 char *params = *pparams;
3437 char *pdata = *ppdata;
3438 unsigned int data_size = 0;
3439 unsigned int param_size = 2;
3441 smb_np_struct *p_pipe = NULL;
3444 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3448 if (total_params < 4) {
3449 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3453 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3454 if (p_pipe == NULL) {
3455 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3459 info_level = SVAL(params,2);
3461 *pparams = (char *)SMB_REALLOC(*pparams,2);
3462 if (*pparams == NULL) {
3463 reply_nterror(req, NT_STATUS_NO_MEMORY);
3468 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3469 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3470 if (*ppdata == NULL ) {
3471 reply_nterror(req, NT_STATUS_NO_MEMORY);
3476 switch (info_level) {
3477 case SMB_FILE_STANDARD_INFORMATION:
3479 SOFF_T(pdata,0,4096LL);
3486 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3490 send_trans2_replies(req, params, param_size, *ppdata, data_size,
3496 /****************************************************************************
3497 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3498 file name or file id).
3499 ****************************************************************************/
3501 static void call_trans2qfilepathinfo(connection_struct *conn,
3502 struct smb_request *req,
3503 unsigned int tran_call,
3504 char **pparams, int total_params,
3505 char **ppdata, int total_data,
3506 unsigned int max_data_bytes)
3508 char *params = *pparams;
3509 char *pdata = *ppdata;
3510 char *dstart, *dend;
3514 SMB_OFF_T file_size=0;
3515 SMB_BIG_UINT allocation_size=0;
3516 unsigned int data_size = 0;
3517 unsigned int param_size = 2;
3518 SMB_STRUCT_STAT sbuf;
3519 char *dos_fname = NULL;
3525 BOOL delete_pending = False;
3527 time_t create_time, mtime, atime;
3528 struct timespec create_time_ts, mtime_ts, atime_ts;
3529 files_struct *fsp = NULL;
3530 struct file_id fileid;
3531 struct ea_list *ea_list = NULL;
3532 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3533 char *lock_data = NULL;
3534 TALLOC_CTX *ctx = talloc_tos();
3537 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3543 if (tran_call == TRANSACT2_QFILEINFO) {
3544 if (total_params < 4) {
3545 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3550 call_trans2qpipeinfo(conn, req, tran_call,
3551 pparams, total_params,
3557 fsp = file_fsp(SVAL(params,0));
3558 info_level = SVAL(params,2);
3560 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3562 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3563 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3567 /* Initial check for valid fsp ptr. */
3568 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
3572 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3574 reply_nterror(req, NT_STATUS_NO_MEMORY);
3578 if(fsp->fake_file_handle) {
3580 * This is actually for the QUOTA_FAKE_FILE --metze
3583 /* We know this name is ok, it's already passed the checks. */
3585 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3587 * This is actually a QFILEINFO on a directory
3588 * handle (returned from an NT SMB). NT5.0 seems
3589 * to do this call. JRA.
3592 if (INFO_LEVEL_IS_UNIX(info_level)) {
3593 /* Always do lstat for UNIX calls. */
3594 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3595 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3596 reply_unixerror(req,ERRDOS,ERRbadpath);
3599 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3600 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3601 reply_unixerror(req, ERRDOS, ERRbadpath);
3605 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3606 delete_pending = get_delete_on_close_flag(fileid);
3609 * Original code - this is an open file.
3611 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3615 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3616 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3617 reply_unixerror(req, ERRDOS, ERRbadfid);
3620 pos = fsp->fh->position_information;
3621 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3622 delete_pending = get_delete_on_close_flag(fileid);
3623 access_mask = fsp->access_mask;
3627 NTSTATUS status = NT_STATUS_OK;
3630 if (total_params < 7) {
3631 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3635 info_level = SVAL(params,0);
3637 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3639 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3640 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3644 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3646 STR_TERMINATE, &status);
3647 if (!NT_STATUS_IS_OK(status)) {
3648 reply_nterror(req, status);
3652 status = resolve_dfspath(ctx,
3654 req->flags2 & FLAGS2_DFS_PATHNAMES,
3657 if (!NT_STATUS_IS_OK(status)) {
3658 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3659 reply_botherror(req,
3660 NT_STATUS_PATH_NOT_COVERED,
3661 ERRSRV, ERRbadpath);
3663 reply_nterror(req, status);
3667 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3668 if (!NT_STATUS_IS_OK(status)) {
3669 reply_nterror(req, status);
3672 status = check_name(conn, fname);
3673 if (!NT_STATUS_IS_OK(status)) {
3674 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3675 reply_nterror(req, status);
3679 if (INFO_LEVEL_IS_UNIX(info_level)) {
3680 /* Always do lstat for UNIX calls. */
3681 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3682 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3683 reply_unixerror(req, ERRDOS, ERRbadpath);
3686 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3687 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3688 reply_unixerror(req, ERRDOS, ERRbadpath);
3692 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3693 delete_pending = get_delete_on_close_flag(fileid);
3694 if (delete_pending) {
3695 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3700 nlink = sbuf.st_nlink;
3702 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3703 /* NTFS does not seem to count ".." */
3707 if ((nlink > 0) && delete_pending) {
3711 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3712 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3716 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3717 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3719 p = strrchr_m(fname,'/');
3725 mode = dos_mode(conn,fname,&sbuf);
3727 mode = FILE_ATTRIBUTE_NORMAL;
3729 fullpathname = fname;
3731 file_size = get_file_size(sbuf);
3733 /* Pull out any data sent here before we realloc. */
3734 switch (info_level) {
3735 case SMB_INFO_QUERY_EAS_FROM_LIST:
3737 /* Pull any EA list from the data portion. */
3740 if (total_data < 4) {
3742 req, NT_STATUS_INVALID_PARAMETER);
3745 ea_size = IVAL(pdata,0);
3747 if (total_data > 0 && ea_size != total_data) {
3748 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3749 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3751 req, NT_STATUS_INVALID_PARAMETER);
3755 if (!lp_ea_support(SNUM(conn))) {
3756 reply_doserror(req, ERRDOS,
3757 ERReasnotsupported);
3761 /* Pull out the list of names. */
3762 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3765 req, NT_STATUS_INVALID_PARAMETER);
3771 case SMB_QUERY_POSIX_LOCK:
3773 if (fsp == NULL || fsp->fh->fd == -1) {
3774 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3778 if (total_data != POSIX_LOCK_DATA_SIZE) {
3780 req, NT_STATUS_INVALID_PARAMETER);
3784 /* Copy the lock range data. */
3785 lock_data = (char *)TALLOC_MEMDUP(
3786 ctx, pdata, total_data);
3788 reply_nterror(req, NT_STATUS_NO_MEMORY);
3796 *pparams = (char *)SMB_REALLOC(*pparams,2);
3797 if (*pparams == NULL) {
3798 reply_nterror(req, NT_STATUS_NO_MEMORY);
3803 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3804 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3805 if (*ppdata == NULL ) {
3806 reply_nterror(req, NT_STATUS_NO_MEMORY);
3811 dend = dstart + data_size - 1;
3813 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3814 mtime_ts = get_mtimespec(&sbuf);
3815 atime_ts = get_atimespec(&sbuf);
3817 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3820 if (!null_timespec(fsp->pending_modtime)) {
3821 /* the pending modtime overrides the current modtime */
3822 mtime_ts = fsp->pending_modtime;
3826 /* Do we have this path open ? */
3827 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3828 fsp1 = file_find_di_first(fileid);
3829 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3830 /* the pending modtime overrides the current modtime */
3831 mtime_ts = fsp1->pending_modtime;
3833 if (fsp1 && fsp1->initial_allocation_size) {
3834 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3838 if (lp_dos_filetime_resolution(SNUM(conn))) {
3839 dos_filetime_timespec(&create_time_ts);
3840 dos_filetime_timespec(&mtime_ts);
3841 dos_filetime_timespec(&atime_ts);
3844 create_time = convert_timespec_to_time_t(create_time_ts);
3845 mtime = convert_timespec_to_time_t(mtime_ts);
3846 atime = convert_timespec_to_time_t(atime_ts);
3848 /* NT expects the name to be in an exact form of the *full*
3849 filename. See the trans2 torture test */
3850 if (ISDOT(base_name)) {
3851 dos_fname = talloc_strdup(ctx, "\\");
3853 reply_nterror(req, NT_STATUS_NO_MEMORY);
3857 dos_fname = talloc_asprintf(ctx,
3861 reply_nterror(req, NT_STATUS_NO_MEMORY);
3864 string_replace(dos_fname, '/', '\\');
3867 switch (info_level) {
3868 case SMB_INFO_STANDARD:
3869 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3871 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3872 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3873 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3874 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3875 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3876 SSVAL(pdata,l1_attrFile,mode);
3879 case SMB_INFO_QUERY_EA_SIZE:
3881 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3882 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3884 srv_put_dos_date2(pdata,0,create_time);
3885 srv_put_dos_date2(pdata,4,atime);
3886 srv_put_dos_date2(pdata,8,mtime); /* write time */
3887 SIVAL(pdata,12,(uint32)file_size);
3888 SIVAL(pdata,16,(uint32)allocation_size);
3889 SSVAL(pdata,20,mode);
3890 SIVAL(pdata,22,ea_size);
3894 case SMB_INFO_IS_NAME_VALID:
3895 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3896 if (tran_call == TRANSACT2_QFILEINFO) {
3897 /* os/2 needs this ? really ?*/
3898 reply_doserror(req, ERRDOS, ERRbadfunc);
3905 case SMB_INFO_QUERY_EAS_FROM_LIST:
3907 size_t total_ea_len = 0;
3908 struct ea_list *ea_file_list = NULL;
3910 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3912 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3913 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3915 if (!ea_list || (total_ea_len > data_size)) {
3917 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3921 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3925 case SMB_INFO_QUERY_ALL_EAS:
3927 /* We have data_size bytes to put EA's into. */
3928 size_t total_ea_len = 0;
3930 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3932 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3933 if (!ea_list || (total_ea_len > data_size)) {
3935 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3939 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3943 case SMB_FILE_BASIC_INFORMATION:
3944 case SMB_QUERY_FILE_BASIC_INFO:
3946 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3947 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3948 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3950 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3954 put_long_date_timespec(pdata,create_time_ts);
3955 put_long_date_timespec(pdata+8,atime_ts);
3956 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3957 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3958 SIVAL(pdata,32,mode);
3960 DEBUG(5,("SMB_QFBI - "));
3961 DEBUG(5,("create: %s ", ctime(&create_time)));
3962 DEBUG(5,("access: %s ", ctime(&atime)));
3963 DEBUG(5,("write: %s ", ctime(&mtime)));
3964 DEBUG(5,("change: %s ", ctime(&mtime)));
3965 DEBUG(5,("mode: %x\n", mode));
3968 case SMB_FILE_STANDARD_INFORMATION:
3969 case SMB_QUERY_FILE_STANDARD_INFO:
3971 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3973 SOFF_T(pdata,0,allocation_size);
3974 SOFF_T(pdata,8,file_size);
3975 SIVAL(pdata,16,nlink);
3976 SCVAL(pdata,20,delete_pending?1:0);
3977 SCVAL(pdata,21,(mode&aDIR)?1:0);
3978 SSVAL(pdata,22,0); /* Padding. */
3981 case SMB_FILE_EA_INFORMATION:
3982 case SMB_QUERY_FILE_EA_INFO:
3984 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3985 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3987 SIVAL(pdata,0,ea_size);
3991 /* Get the 8.3 name - used if NT SMB was negotiated. */
3992 case SMB_QUERY_FILE_ALT_NAME_INFO:
3993 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3995 char mangled_name[13];
3996 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3997 if (!name_to_8_3(base_name,mangled_name,
3998 True,conn->params)) {
4001 NT_STATUS_NO_MEMORY);
4003 len = srvstr_push(dstart, req->flags2,
4004 pdata+4, mangled_name,
4005 PTR_DIFF(dend, pdata+4),
4007 data_size = 4 + len;
4012 case SMB_QUERY_FILE_NAME_INFO:
4014 this must be *exactly* right for ACLs on mapped drives to work
4016 len = srvstr_push(dstart, req->flags2,
4018 PTR_DIFF(dend, pdata+4),
4020 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4021 data_size = 4 + len;
4025 case SMB_FILE_ALLOCATION_INFORMATION:
4026 case SMB_QUERY_FILE_ALLOCATION_INFO:
4027 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4029 SOFF_T(pdata,0,allocation_size);
4032 case SMB_FILE_END_OF_FILE_INFORMATION:
4033 case SMB_QUERY_FILE_END_OF_FILEINFO:
4034 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4036 SOFF_T(pdata,0,file_size);
4039 case SMB_QUERY_FILE_ALL_INFO:
4040 case SMB_FILE_ALL_INFORMATION:
4042 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4043 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4044 put_long_date_timespec(pdata,create_time_ts);
4045 put_long_date_timespec(pdata+8,atime_ts);
4046 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4047 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4048 SIVAL(pdata,32,mode);
4049 SIVAL(pdata,36,0); /* padding. */
4051 SOFF_T(pdata,0,allocation_size);
4052 SOFF_T(pdata,8,file_size);
4053 SIVAL(pdata,16,nlink);
4054 SCVAL(pdata,20,delete_pending);
4055 SCVAL(pdata,21,(mode&aDIR)?1:0);
4058 SIVAL(pdata,0,ea_size);
4059 pdata += 4; /* EA info */
4060 len = srvstr_push(dstart, req->flags2,
4062 PTR_DIFF(dend, pdata+4),
4066 data_size = PTR_DIFF(pdata,(*ppdata));
4069 case SMB_FILE_INTERNAL_INFORMATION:
4070 /* This should be an index number - looks like
4073 I think this causes us to fail the IFSKIT
4074 BasicFileInformationTest. -tpot */
4076 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4077 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4078 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4082 case SMB_FILE_ACCESS_INFORMATION:
4083 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4084 SIVAL(pdata,0,access_mask);
4088 case SMB_FILE_NAME_INFORMATION:
4089 /* Pathname with leading '\'. */
4092 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4093 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4094 SIVAL(pdata,0,byte_len);
4095 data_size = 4 + byte_len;
4099 case SMB_FILE_DISPOSITION_INFORMATION:
4100 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4102 SCVAL(pdata,0,delete_pending);
4105 case SMB_FILE_POSITION_INFORMATION:
4106 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4108 SOFF_T(pdata,0,pos);
4111 case SMB_FILE_MODE_INFORMATION:
4112 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4113 SIVAL(pdata,0,mode);
4117 case SMB_FILE_ALIGNMENT_INFORMATION:
4118 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4119 SIVAL(pdata,0,0); /* No alignment needed. */
4125 * NT4 server just returns "invalid query" to this - if we try to answer
4126 * it then NTws gets a BSOD! (tridge).
4127 * W2K seems to want this. JRA.
4129 case SMB_QUERY_FILE_STREAM_INFO:
4131 case SMB_FILE_STREAM_INFORMATION:
4132 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4136 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4137 SIVAL(pdata,0,0); /* ??? */
4138 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4139 SOFF_T(pdata,8,file_size);
4140 SOFF_T(pdata,16,allocation_size);
4141 data_size = 24 + byte_len;
4145 case SMB_QUERY_COMPRESSION_INFO:
4146 case SMB_FILE_COMPRESSION_INFORMATION:
4147 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4148 SOFF_T(pdata,0,file_size);
4149 SIVAL(pdata,8,0); /* ??? */
4150 SIVAL(pdata,12,0); /* ??? */
4154 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4155 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4156 put_long_date_timespec(pdata,create_time_ts);
4157 put_long_date_timespec(pdata+8,atime_ts);
4158 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4159 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4160 SOFF_T(pdata,32,allocation_size);
4161 SOFF_T(pdata,40,file_size);
4162 SIVAL(pdata,48,mode);
4163 SIVAL(pdata,52,0); /* ??? */
4167 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4168 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4169 SIVAL(pdata,0,mode);
4175 * CIFS UNIX Extensions.
4178 case SMB_QUERY_FILE_UNIX_BASIC:
4180 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4181 data_size = PTR_DIFF(pdata,(*ppdata));
4185 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4187 for (i=0; i<100; i++)
4188 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4194 case SMB_QUERY_FILE_UNIX_INFO2:
4196 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4197 data_size = PTR_DIFF(pdata,(*ppdata));
4201 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4203 for (i=0; i<100; i++)
4204 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4210 case SMB_QUERY_FILE_UNIX_LINK:
4212 char *buffer = TALLOC_SIZE(ctx, 1024);
4215 reply_nterror(req, NT_STATUS_NO_MEMORY);
4219 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4221 if(!S_ISLNK(sbuf.st_mode)) {
4222 reply_unixerror(req, ERRSRV,
4227 reply_unixerror(req, ERRDOS, ERRbadlink);
4230 len = SMB_VFS_READLINK(conn,fullpathname,
4233 reply_unixerror(req, ERRDOS,
4238 len = srvstr_push(dstart, req->flags2,
4240 PTR_DIFF(dend, pdata),
4243 data_size = PTR_DIFF(pdata,(*ppdata));
4248 #if defined(HAVE_POSIX_ACLS)
4249 case SMB_QUERY_POSIX_ACL:
4251 SMB_ACL_T file_acl = NULL;
4252 SMB_ACL_T def_acl = NULL;
4253 uint16 num_file_acls = 0;
4254 uint16 num_def_acls = 0;
4256 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4257 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4259 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4262 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4263 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4267 NT_STATUS_NOT_IMPLEMENTED);
4271 if (S_ISDIR(sbuf.st_mode)) {
4272 if (fsp && fsp->is_directory) {
4273 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4275 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4277 def_acl = free_empty_sys_acl(conn, def_acl);
4280 num_file_acls = count_acl_entries(conn, file_acl);
4281 num_def_acls = count_acl_entries(conn, def_acl);
4283 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4284 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4286 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4287 SMB_POSIX_ACL_HEADER_SIZE) ));
4289 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4292 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4296 NT_STATUS_BUFFER_TOO_SMALL);
4300 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4301 SSVAL(pdata,2,num_file_acls);
4302 SSVAL(pdata,4,num_def_acls);
4303 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4305 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4308 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4311 req, NT_STATUS_INTERNAL_ERROR);
4314 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4316 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4319 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4323 NT_STATUS_INTERNAL_ERROR);
4328 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4331 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4333 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4339 case SMB_QUERY_POSIX_LOCK:
4341 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4343 SMB_BIG_UINT offset;
4345 enum brl_type lock_type;
4347 if (total_data != POSIX_LOCK_DATA_SIZE) {
4349 req, NT_STATUS_INVALID_PARAMETER);
4353 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4354 case POSIX_LOCK_TYPE_READ:
4355 lock_type = READ_LOCK;
4357 case POSIX_LOCK_TYPE_WRITE:
4358 lock_type = WRITE_LOCK;
4360 case POSIX_LOCK_TYPE_UNLOCK:
4362 /* There's no point in asking for an unlock... */
4365 NT_STATUS_INVALID_PARAMETER);
4369 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4370 #if defined(HAVE_LONGLONG)
4371 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4372 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4373 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4374 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4375 #else /* HAVE_LONGLONG */
4376 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4377 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4378 #endif /* HAVE_LONGLONG */
4380 status = query_lock(fsp,
4387 if (ERROR_WAS_LOCK_DENIED(status)) {
4388 /* Here we need to report who has it locked... */
4389 data_size = POSIX_LOCK_DATA_SIZE;
4391 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4392 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4393 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4394 #if defined(HAVE_LONGLONG)
4395 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4396 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4397 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4398 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4399 #else /* HAVE_LONGLONG */
4400 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4401 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4402 #endif /* HAVE_LONGLONG */
4404 } else if (NT_STATUS_IS_OK(status)) {
4405 /* For success we just return a copy of what we sent
4406 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4407 data_size = POSIX_LOCK_DATA_SIZE;
4408 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4409 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4411 reply_nterror(req, status);
4418 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4422 send_trans2_replies(req, params, param_size, *ppdata, data_size,
4428 /****************************************************************************
4429 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4431 ****************************************************************************/
4433 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4434 connection_struct *conn,
4435 const char *oldname_in,
4436 const char *newname_in)
4438 SMB_STRUCT_STAT sbuf1, sbuf2;
4439 char *last_component_oldname = NULL;
4440 char *last_component_newname = NULL;
4441 char *oldname = NULL;
4442 char *newname = NULL;
4443 NTSTATUS status = NT_STATUS_OK;
4448 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4449 &last_component_oldname, &sbuf1);
4450 if (!NT_STATUS_IS_OK(status)) {
4454 status = check_name(conn, oldname);
4455 if (!NT_STATUS_IS_OK(status)) {
4459 /* source must already exist. */
4460 if (!VALID_STAT(sbuf1)) {
4461 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4464 status = unix_convert(ctx, conn, newname_in, False, &newname,
4465 &last_component_newname, &sbuf2);
4466 if (!NT_STATUS_IS_OK(status)) {
4470 status = check_name(conn, newname);
4471 if (!NT_STATUS_IS_OK(status)) {
4475 /* Disallow if newname already exists. */
4476 if (VALID_STAT(sbuf2)) {
4477 return NT_STATUS_OBJECT_NAME_COLLISION;
4480 /* No links from a directory. */
4481 if (S_ISDIR(sbuf1.st_mode)) {
4482 return NT_STATUS_FILE_IS_A_DIRECTORY;
4485 /* Ensure this is within the share. */
4486 status = check_reduced_name(conn, oldname);
4487 if (!NT_STATUS_IS_OK(status)) {
4491 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4493 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4494 status = map_nt_error_from_unix(errno);
4495 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4496 nt_errstr(status), newname, oldname));
4502 /****************************************************************************
4503 Deal with setting the time from any of the setfilepathinfo functions.
4504 ****************************************************************************/
4506 static NTSTATUS smb_set_file_time(connection_struct *conn,
4509 const SMB_STRUCT_STAT *psbuf,
4510 struct timespec ts[2])
4513 FILE_NOTIFY_CHANGE_LAST_ACCESS
4514 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4517 if (!VALID_STAT(*psbuf)) {
4518 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4521 /* get some defaults (no modifications) if any info is zero or -1. */
4522 if (null_timespec(ts[0])) {
4523 ts[0] = get_atimespec(psbuf);
4524 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4527 if (null_timespec(ts[1])) {
4528 ts[1] = get_mtimespec(psbuf);
4529 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4532 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4533 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4536 * Try and set the times of this file if
4537 * they are different from the current values.
4541 struct timespec mts = get_mtimespec(psbuf);
4542 struct timespec ats = get_atimespec(psbuf);
4543 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4544 return NT_STATUS_OK;
4550 * This was a setfileinfo on an open file.
4551 * NT does this a lot. We also need to
4552 * set the time here, as it can be read by
4553 * FindFirst/FindNext and with the patch for bug #2045
4554 * in smbd/fileio.c it ensures that this timestamp is
4555 * kept sticky even after a write. We save the request
4556 * away and will set it on file close and after a write. JRA.
4559 if (!null_timespec(ts[1])) {
4560 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4561 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4562 fsp_set_pending_modtime(fsp, ts[1]);
4566 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4568 if(file_ntimes(conn, fname, ts)!=0) {
4569 return map_nt_error_from_unix(errno);
4572 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4574 return NT_STATUS_OK;
4577 /****************************************************************************
4578 Deal with setting the dosmode from any of the setfilepathinfo functions.
4579 ****************************************************************************/
4581 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4583 SMB_STRUCT_STAT *psbuf,
4586 if (!VALID_STAT(*psbuf)) {
4587 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4591 if (S_ISDIR(psbuf->st_mode)) {
4598 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4600 /* check the mode isn't different, before changing it */
4601 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4603 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4604 fname, (unsigned int)dosmode ));
4606 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4607 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4608 fname, strerror(errno)));
4609 return map_nt_error_from_unix(errno);
4612 return NT_STATUS_OK;
4615 /****************************************************************************
4616 Deal with setting the size from any of the setfilepathinfo functions.
4617 ****************************************************************************/
4619 static NTSTATUS smb_set_file_size(connection_struct *conn,
4620 struct smb_request *req,
4623 SMB_STRUCT_STAT *psbuf,
4626 NTSTATUS status = NT_STATUS_OK;
4627 files_struct *new_fsp = NULL;
4629 if (!VALID_STAT(*psbuf)) {
4630 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4633 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4635 if (size == get_file_size(*psbuf)) {
4636 return NT_STATUS_OK;
4639 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4640 fname, (double)size ));
4642 if (fsp && fsp->fh->fd != -1) {
4643 /* Handle based call. */
4644 if (vfs_set_filelen(fsp, size) == -1) {
4645 return map_nt_error_from_unix(errno);
4647 return NT_STATUS_OK;
4650 status = open_file_ntcreate(conn, req, fname, psbuf,
4652 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4655 FILE_ATTRIBUTE_NORMAL,
4656 FORCE_OPLOCK_BREAK_TO_NONE,
4659 if (!NT_STATUS_IS_OK(status)) {
4660 /* NB. We check for open_was_deferred in the caller. */
4664 if (vfs_set_filelen(new_fsp, size) == -1) {
4665 status = map_nt_error_from_unix(errno);
4666 close_file(new_fsp,NORMAL_CLOSE);
4670 close_file(new_fsp,NORMAL_CLOSE);
4671 return NT_STATUS_OK;
4674 /****************************************************************************
4675 Deal with SMB_INFO_SET_EA.
4676 ****************************************************************************/
4678 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4684 struct ea_list *ea_list = NULL;
4685 TALLOC_CTX *ctx = NULL;
4686 NTSTATUS status = NT_STATUS_OK;
4688 if (total_data < 10) {
4690 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4691 length. They seem to have no effect. Bug #3212. JRA */
4693 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4694 /* We're done. We only get EA info in this call. */
4695 return NT_STATUS_OK;
4698 return NT_STATUS_INVALID_PARAMETER;
4701 if (IVAL(pdata,0) > total_data) {
4702 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4703 IVAL(pdata,0), (unsigned int)total_data));
4704 return NT_STATUS_INVALID_PARAMETER;
4707 ctx = talloc_init("SMB_INFO_SET_EA");
4709 return NT_STATUS_NO_MEMORY;
4711 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4713 talloc_destroy(ctx);
4714 return NT_STATUS_INVALID_PARAMETER;
4716 status = set_ea(conn, fsp, fname, ea_list);
4717 talloc_destroy(ctx);
4722 /****************************************************************************
4723 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4724 ****************************************************************************/
4726 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4731 SMB_STRUCT_STAT *psbuf)
4733 NTSTATUS status = NT_STATUS_OK;
4734 BOOL delete_on_close;
4737 if (total_data < 1) {
4738 return NT_STATUS_INVALID_PARAMETER;
4742 return NT_STATUS_INVALID_HANDLE;
4745 delete_on_close = (CVAL(pdata,0) ? True : False);
4746 dosmode = dos_mode(conn, fname, psbuf);
4748 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4749 "delete_on_close = %u\n",
4751 (unsigned int)dosmode,
4752 (unsigned int)delete_on_close ));
4754 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4756 if (!NT_STATUS_IS_OK(status)) {
4760 /* The set is across all open files on this dev/inode pair. */
4761 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4762 return NT_STATUS_ACCESS_DENIED;
4764 return NT_STATUS_OK;
4767 /****************************************************************************
4768 Deal with SMB_FILE_POSITION_INFORMATION.
4769 ****************************************************************************/
4771 static NTSTATUS smb_file_position_information(connection_struct *conn,
4776 SMB_BIG_UINT position_information;
4778 if (total_data < 8) {
4779 return NT_STATUS_INVALID_PARAMETER;
4783 /* Ignore on pathname based set. */
4784 return NT_STATUS_OK;
4787 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4788 #ifdef LARGE_SMB_OFF_T
4789 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4790 #else /* LARGE_SMB_OFF_T */
4791 if (IVAL(pdata,4) != 0) {
4792 /* more than 32 bits? */
4793 return NT_STATUS_INVALID_PARAMETER;
4795 #endif /* LARGE_SMB_OFF_T */
4797 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4798 fsp->fsp_name, (double)position_information ));
4799 fsp->fh->position_information = position_information;
4800 return NT_STATUS_OK;
4803 /****************************************************************************
4804 Deal with SMB_FILE_MODE_INFORMATION.
4805 ****************************************************************************/
4807 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4813 if (total_data < 4) {
4814 return NT_STATUS_INVALID_PARAMETER;
4816 mode = IVAL(pdata,0);
4817 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4818 return NT_STATUS_INVALID_PARAMETER;
4820 return NT_STATUS_OK;
4823 /****************************************************************************
4824 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4825 ****************************************************************************/
4827 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4828 struct smb_request *req,
4833 char *link_target = NULL;
4834 const char *newname = fname;
4835 NTSTATUS status = NT_STATUS_OK;
4836 TALLOC_CTX *ctx = talloc_tos();
4838 /* Set a symbolic link. */
4839 /* Don't allow this if follow links is false. */
4841 if (total_data == 0) {
4842 return NT_STATUS_INVALID_PARAMETER;
4845 if (!lp_symlinks(SNUM(conn))) {
4846 return NT_STATUS_ACCESS_DENIED;
4849 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
4850 total_data, STR_TERMINATE);
4853 return NT_STATUS_INVALID_PARAMETER;
4856 /* !widelinks forces the target path to be within the share. */
4857 /* This means we can interpret the target as a pathname. */
4858 if (!lp_widelinks(SNUM(conn))) {
4859 char *rel_name = NULL;
4860 char *last_dirp = NULL;
4862 if (*link_target == '/') {
4863 /* No absolute paths allowed. */
4864 return NT_STATUS_ACCESS_DENIED;
4866 rel_name = talloc_strdup(ctx,newname);
4868 return NT_STATUS_NO_MEMORY;
4870 last_dirp = strrchr_m(rel_name, '/');
4872 last_dirp[1] = '\0';
4874 rel_name = talloc_strdup(ctx,"./");
4876 return NT_STATUS_NO_MEMORY;
4879 rel_name = talloc_asprintf_append(ctx,
4883 return NT_STATUS_NO_MEMORY;
4886 status = check_name(conn, rel_name);
4887 if (!NT_STATUS_IS_OK(status)) {
4892 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4893 newname, link_target ));
4895 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4896 return map_nt_error_from_unix(errno);
4899 return NT_STATUS_OK;
4902 /****************************************************************************
4903 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4904 ****************************************************************************/
4906 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4907 struct smb_request *req,
4908 const char *pdata, int total_data,
4911 char *oldname = NULL;
4912 TALLOC_CTX *ctx = talloc_tos();
4913 NTSTATUS status = NT_STATUS_OK;
4915 /* Set a hard link. */
4916 if (total_data == 0) {
4917 return NT_STATUS_INVALID_PARAMETER;
4920 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
4921 total_data, STR_TERMINATE, &status);
4922 if (!NT_STATUS_IS_OK(status)) {
4926 status = resolve_dfspath(ctx, conn,
4927 req->flags2 & FLAGS2_DFS_PATHNAMES,
4930 if (!NT_STATUS_IS_OK(status)) {
4934 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4937 return hardlink_internals(ctx, conn, oldname, fname);
4940 /****************************************************************************
4941 Deal with SMB_FILE_RENAME_INFORMATION.
4942 ****************************************************************************/
4944 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4945 struct smb_request *req,
4954 char *newname = NULL;
4955 char *base_name = NULL;
4956 BOOL dest_has_wcard = False;
4957 NTSTATUS status = NT_STATUS_OK;
4959 TALLOC_CTX *ctx = talloc_tos();
4961 if (total_data < 13) {
4962 return NT_STATUS_INVALID_PARAMETER;
4965 overwrite = (CVAL(pdata,0) ? True : False);
4966 root_fid = IVAL(pdata,4);
4967 len = IVAL(pdata,8);
4969 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4970 return NT_STATUS_INVALID_PARAMETER;
4973 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
4976 if (!NT_STATUS_IS_OK(status)) {
4980 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4983 status = resolve_dfspath_wcard(ctx, conn,
4984 req->flags2 & FLAGS2_DFS_PATHNAMES,
4988 if (!NT_STATUS_IS_OK(status)) {
4992 /* Check the new name has no '/' characters. */
4993 if (strchr_m(newname, '/')) {
4994 return NT_STATUS_NOT_SUPPORTED;
4997 /* Create the base directory. */
4998 base_name = talloc_strdup(ctx, fname);
5000 return NT_STATUS_NO_MEMORY;
5002 p = strrchr_m(base_name, '/');
5006 base_name = talloc_strdup(ctx, "./");
5008 return NT_STATUS_NO_MEMORY;
5011 /* Append the new name. */
5012 base_name = talloc_asprintf_append(base_name,
5016 return NT_STATUS_NO_MEMORY;
5020 SMB_STRUCT_STAT sbuf;
5021 char *newname_last_component = NULL;
5025 status = unix_convert(ctx, conn, newname, False,
5027 &newname_last_component,
5030 /* If an error we expect this to be
5031 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5033 if (!NT_STATUS_IS_OK(status)
5034 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5039 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5040 fsp->fnum, fsp->fsp_name, base_name ));
5041 status = rename_internals_fsp(conn, fsp, base_name,
5042 newname_last_component, 0,
5045 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5046 fname, base_name ));
5047 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5048 overwrite, False, dest_has_wcard);
5054 /****************************************************************************
5055 Deal with SMB_SET_POSIX_ACL.
5056 ****************************************************************************/
5058 #if defined(HAVE_POSIX_ACLS)
5059 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5064 SMB_STRUCT_STAT *psbuf)
5066 uint16 posix_acl_version;
5067 uint16 num_file_acls;
5068 uint16 num_def_acls;
5069 BOOL valid_file_acls = True;
5070 BOOL valid_def_acls = True;
5072 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5073 return NT_STATUS_INVALID_PARAMETER;
5075 posix_acl_version = SVAL(pdata,0);
5076 num_file_acls = SVAL(pdata,2);
5077 num_def_acls = SVAL(pdata,4);
5079 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5080 valid_file_acls = False;
5084 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5085 valid_def_acls = False;
5089 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5090 return NT_STATUS_INVALID_PARAMETER;
5093 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5094 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5095 return NT_STATUS_INVALID_PARAMETER;
5098 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5099 fname ? fname : fsp->fsp_name,
5100 (unsigned int)num_file_acls,
5101 (unsigned int)num_def_acls));
5103 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5104 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5105 return map_nt_error_from_unix(errno);
5108 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5109 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5110 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5111 return map_nt_error_from_unix(errno);
5113 return NT_STATUS_OK;
5117 /****************************************************************************
5118 Deal with SMB_SET_POSIX_LOCK.
5119 ****************************************************************************/
5121 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5129 SMB_BIG_UINT offset;
5131 BOOL blocking_lock = False;
5132 enum brl_type lock_type;
5133 NTSTATUS status = NT_STATUS_OK;
5135 if (fsp == NULL || fsp->fh->fd == -1) {
5136 return NT_STATUS_INVALID_HANDLE;
5139 if (total_data != POSIX_LOCK_DATA_SIZE) {
5140 return NT_STATUS_INVALID_PARAMETER;
5143 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5144 case POSIX_LOCK_TYPE_READ:
5145 lock_type = READ_LOCK;
5147 case POSIX_LOCK_TYPE_WRITE:
5148 /* Return the right POSIX-mappable error code for files opened read-only. */
5149 if (!fsp->can_write) {
5150 return NT_STATUS_INVALID_HANDLE;
5152 lock_type = WRITE_LOCK;
5154 case POSIX_LOCK_TYPE_UNLOCK:
5155 lock_type = UNLOCK_LOCK;
5158 return NT_STATUS_INVALID_PARAMETER;
5161 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5162 blocking_lock = False;
5163 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5164 blocking_lock = True;
5166 return NT_STATUS_INVALID_PARAMETER;
5169 if (!lp_blocking_locks(SNUM(conn))) {
5170 blocking_lock = False;
5173 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5174 #if defined(HAVE_LONGLONG)
5175 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5176 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5177 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5178 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5179 #else /* HAVE_LONGLONG */
5180 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5181 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5182 #endif /* HAVE_LONGLONG */
5184 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5185 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5187 (unsigned int)lock_type,
5188 (unsigned int)lock_pid,
5192 if (lock_type == UNLOCK_LOCK) {
5193 status = do_unlock(smbd_messaging_context(),
5200 uint32 block_smbpid;
5202 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5213 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5215 * A blocking lock was requested. Package up
5216 * this smb into a queued request and push it
5217 * onto the blocking lock queue.
5219 if(push_blocking_lock_request(br_lck,
5220 (char *)inbuf, length,
5222 -1, /* infinite timeout. */
5230 TALLOC_FREE(br_lck);
5234 TALLOC_FREE(br_lck);
5240 /****************************************************************************
5241 Deal with SMB_INFO_STANDARD.
5242 ****************************************************************************/
5244 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5249 const SMB_STRUCT_STAT *psbuf)
5251 struct timespec ts[2];
5253 if (total_data < 12) {
5254 return NT_STATUS_INVALID_PARAMETER;
5258 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5260 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5262 DEBUG(10,("smb_set_info_standard: file %s\n",
5263 fname ? fname : fsp->fsp_name ));
5265 return smb_set_file_time(conn,
5272 /****************************************************************************
5273 Deal with SMB_SET_FILE_BASIC_INFO.
5274 ****************************************************************************/
5276 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5281 SMB_STRUCT_STAT *psbuf)
5283 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5284 struct timespec write_time;
5285 struct timespec changed_time;
5287 struct timespec ts[2];
5288 NTSTATUS status = NT_STATUS_OK;
5290 if (total_data < 36) {
5291 return NT_STATUS_INVALID_PARAMETER;
5294 /* Set the attributes */
5295 dosmode = IVAL(pdata,32);
5296 status = smb_set_file_dosmode(conn,
5300 if (!NT_STATUS_IS_OK(status)) {
5304 /* Ignore create time at offset pdata. */
5307 ts[0] = interpret_long_date(pdata+8);
5309 write_time = interpret_long_date(pdata+16);
5310 changed_time = interpret_long_date(pdata+24);
5313 ts[1] = timespec_min(&write_time, &changed_time);
5315 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5319 /* Prefer a defined time to an undefined one. */
5320 if (null_timespec(ts[1])) {
5321 ts[1] = null_timespec(write_time) ? changed_time : write_time;
5324 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5325 fname ? fname : fsp->fsp_name ));
5327 return smb_set_file_time(conn,
5334 /****************************************************************************
5335 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5336 ****************************************************************************/
5338 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5339 struct smb_request *req,
5344 SMB_STRUCT_STAT *psbuf)
5346 SMB_BIG_UINT allocation_size = 0;
5347 NTSTATUS status = NT_STATUS_OK;
5348 files_struct *new_fsp = NULL;
5350 if (!VALID_STAT(*psbuf)) {
5351 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5354 if (total_data < 8) {
5355 return NT_STATUS_INVALID_PARAMETER;
5358 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5359 #ifdef LARGE_SMB_OFF_T
5360 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5361 #else /* LARGE_SMB_OFF_T */
5362 if (IVAL(pdata,4) != 0) {
5363 /* more than 32 bits? */
5364 return NT_STATUS_INVALID_PARAMETER;
5366 #endif /* LARGE_SMB_OFF_T */
5368 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5369 fname, (double)allocation_size ));
5371 if (allocation_size) {
5372 allocation_size = smb_roundup(conn, allocation_size);
5375 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5376 fname, (double)allocation_size ));
5378 if (fsp && fsp->fh->fd != -1) {
5379 /* Open file handle. */
5380 /* Only change if needed. */
5381 if (allocation_size != get_file_size(*psbuf)) {
5382 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5383 return map_nt_error_from_unix(errno);
5386 /* But always update the time. */
5387 if (null_timespec(fsp->pending_modtime)) {
5389 * This is equivalent to a write. Ensure it's seen immediately
5390 * if there are no pending writes.
5392 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
5394 return NT_STATUS_OK;
5397 /* Pathname or stat or directory file. */
5399 status = open_file_ntcreate(conn, req, fname, psbuf,
5401 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5404 FILE_ATTRIBUTE_NORMAL,
5405 FORCE_OPLOCK_BREAK_TO_NONE,
5408 if (!NT_STATUS_IS_OK(status)) {
5409 /* NB. We check for open_was_deferred in the caller. */
5413 /* Only change if needed. */
5414 if (allocation_size != get_file_size(*psbuf)) {
5415 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5416 status = map_nt_error_from_unix(errno);
5417 close_file(new_fsp,NORMAL_CLOSE);
5422 /* Changing the allocation size should set the last mod time. */
5423 /* Don't need to call set_filetime as this will be flushed on
5426 fsp_set_pending_modtime(new_fsp, timespec_current());
5428 close_file(new_fsp,NORMAL_CLOSE);
5429 return NT_STATUS_OK;
5432 /****************************************************************************
5433 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5434 ****************************************************************************/
5436 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5437 struct smb_request *req,
5442 SMB_STRUCT_STAT *psbuf)
5446 if (total_data < 8) {
5447 return NT_STATUS_INVALID_PARAMETER;
5450 size = IVAL(pdata,0);
5451 #ifdef LARGE_SMB_OFF_T
5452 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5453 #else /* LARGE_SMB_OFF_T */
5454 if (IVAL(pdata,4) != 0) {
5455 /* more than 32 bits? */
5456 return NT_STATUS_INVALID_PARAMETER;
5458 #endif /* LARGE_SMB_OFF_T */
5459 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5460 "file %s to %.0f\n", fname, (double)size ));
5462 return smb_set_file_size(conn, req,
5469 /****************************************************************************
5470 Allow a UNIX info mknod.
5471 ****************************************************************************/
5473 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5477 SMB_STRUCT_STAT *psbuf)
5479 uint32 file_type = IVAL(pdata,56);
5480 #if defined(HAVE_MAKEDEV)
5481 uint32 dev_major = IVAL(pdata,60);
5482 uint32 dev_minor = IVAL(pdata,68);
5484 SMB_DEV_T dev = (SMB_DEV_T)0;
5485 uint32 raw_unixmode = IVAL(pdata,84);
5489 if (total_data < 100) {
5490 return NT_STATUS_INVALID_PARAMETER;
5493 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5494 if (!NT_STATUS_IS_OK(status)) {
5498 #if defined(HAVE_MAKEDEV)
5499 dev = makedev(dev_major, dev_minor);
5502 switch (file_type) {
5503 #if defined(S_IFIFO)
5504 case UNIX_TYPE_FIFO:
5505 unixmode |= S_IFIFO;
5508 #if defined(S_IFSOCK)
5509 case UNIX_TYPE_SOCKET:
5510 unixmode |= S_IFSOCK;
5513 #if defined(S_IFCHR)
5514 case UNIX_TYPE_CHARDEV:
5515 unixmode |= S_IFCHR;
5518 #if defined(S_IFBLK)
5519 case UNIX_TYPE_BLKDEV:
5520 unixmode |= S_IFBLK;
5524 return NT_STATUS_INVALID_PARAMETER;
5527 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5528 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5530 /* Ok - do the mknod. */
5531 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5532 return map_nt_error_from_unix(errno);
5535 /* If any of the other "set" calls fail we
5536 * don't want to end up with a half-constructed mknod.
5539 if (lp_inherit_perms(SNUM(conn))) {
5541 conn, parent_dirname(fname),
5545 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5546 status = map_nt_error_from_unix(errno);
5547 SMB_VFS_UNLINK(conn,fname);
5550 return NT_STATUS_OK;
5553 /****************************************************************************
5554 Deal with SMB_SET_FILE_UNIX_BASIC.
5555 ****************************************************************************/
5557 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5558 struct smb_request *req,
5563 SMB_STRUCT_STAT *psbuf)
5565 struct timespec ts[2];
5566 uint32 raw_unixmode;
5569 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5570 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5571 NTSTATUS status = NT_STATUS_OK;
5572 BOOL delete_on_fail = False;
5573 enum perm_type ptype;
5575 if (total_data < 100) {
5576 return NT_STATUS_INVALID_PARAMETER;
5579 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5580 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5581 size=IVAL(pdata,0); /* first 8 Bytes are size */
5582 #ifdef LARGE_SMB_OFF_T
5583 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5584 #else /* LARGE_SMB_OFF_T */
5585 if (IVAL(pdata,4) != 0) {
5586 /* more than 32 bits? */
5587 return NT_STATUS_INVALID_PARAMETER;
5589 #endif /* LARGE_SMB_OFF_T */
5592 ts[0] = interpret_long_date(pdata+24); /* access_time */
5593 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5594 set_owner = (uid_t)IVAL(pdata,40);
5595 set_grp = (gid_t)IVAL(pdata,48);
5596 raw_unixmode = IVAL(pdata,84);
5598 if (VALID_STAT(*psbuf)) {
5599 if (S_ISDIR(psbuf->st_mode)) {
5600 ptype = PERM_EXISTING_DIR;
5602 ptype = PERM_EXISTING_FILE;
5605 ptype = PERM_NEW_FILE;
5608 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5609 if (!NT_STATUS_IS_OK(status)) {
5613 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5614 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5615 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5617 if (!VALID_STAT(*psbuf)) {
5619 * The only valid use of this is to create character and block
5620 * devices, and named pipes. This is deprecated (IMHO) and
5621 * a new info level should be used for mknod. JRA.
5624 status = smb_unix_mknod(conn,
5629 if (!NT_STATUS_IS_OK(status)) {
5633 /* Ensure we don't try and change anything else. */
5634 raw_unixmode = SMB_MODE_NO_CHANGE;
5635 size = get_file_size(*psbuf);
5636 ts[0] = get_atimespec(psbuf);
5637 ts[1] = get_mtimespec(psbuf);
5639 * We continue here as we might want to change the
5642 delete_on_fail = True;
5646 /* Horrible backwards compatibility hack as an old server bug
5647 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5651 size = get_file_size(*psbuf);
5656 * Deal with the UNIX specific mode set.
5659 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5660 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5661 (unsigned int)unixmode, fname ));
5662 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5663 return map_nt_error_from_unix(errno);
5668 * Deal with the UNIX specific uid set.
5671 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5674 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5675 (unsigned int)set_owner, fname ));
5677 if (S_ISLNK(psbuf->st_mode)) {
5678 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5680 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5684 status = map_nt_error_from_unix(errno);
5685 if (delete_on_fail) {
5686 SMB_VFS_UNLINK(conn,fname);
5693 * Deal with the UNIX specific gid set.
5696 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5697 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5698 (unsigned int)set_owner, fname ));
5699 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5700 status = map_nt_error_from_unix(errno);
5701 if (delete_on_fail) {
5702 SMB_VFS_UNLINK(conn,fname);
5708 /* Deal with any size changes. */
5710 status = smb_set_file_size(conn, req,
5715 if (!NT_STATUS_IS_OK(status)) {
5719 /* Deal with any time changes. */
5721 return smb_set_file_time(conn,
5728 /****************************************************************************
5729 Deal with SMB_SET_FILE_UNIX_INFO2.
5730 ****************************************************************************/
5732 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5733 struct smb_request *req,
5738 SMB_STRUCT_STAT *psbuf)
5744 if (total_data < 116) {
5745 return NT_STATUS_INVALID_PARAMETER;
5748 /* Start by setting all the fields that are common between UNIX_BASIC
5751 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5753 if (!NT_STATUS_IS_OK(status)) {
5757 smb_fflags = IVAL(pdata, 108);
5758 smb_fmask = IVAL(pdata, 112);
5760 /* NB: We should only attempt to alter the file flags if the client
5761 * sends a non-zero mask.
5763 if (smb_fmask != 0) {
5764 int stat_fflags = 0;
5766 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5768 /* Client asked to alter a flag we don't understand. */
5769 return NT_STATUS_INVALID_PARAMETER;
5772 if (fsp && fsp->fh->fd != -1) {
5773 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5774 return NT_STATUS_NOT_SUPPORTED;
5776 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5777 return map_nt_error_from_unix(errno);
5782 /* XXX: need to add support for changing the create_time here. You
5783 * can do this for paths on Darwin with setattrlist(2). The right way
5784 * to hook this up is probably by extending the VFS utimes interface.
5787 return NT_STATUS_OK;
5790 /****************************************************************************
5791 Create a directory with POSIX semantics.
5792 ****************************************************************************/
5794 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5795 struct smb_request *req,
5799 SMB_STRUCT_STAT *psbuf,
5800 int *pdata_return_size)
5802 NTSTATUS status = NT_STATUS_OK;
5803 uint32 raw_unixmode = 0;
5804 uint32 mod_unixmode = 0;
5805 mode_t unixmode = (mode_t)0;
5806 files_struct *fsp = NULL;
5807 uint16 info_level_return = 0;
5809 char *pdata = *ppdata;
5811 if (total_data < 18) {
5812 return NT_STATUS_INVALID_PARAMETER;
5815 raw_unixmode = IVAL(pdata,8);
5816 /* Next 4 bytes are not yet defined. */
5818 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5819 if (!NT_STATUS_IS_OK(status)) {
5823 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5825 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5826 fname, (unsigned int)unixmode ));
5828 status = open_directory(conn, req,
5831 FILE_READ_ATTRIBUTES, /* Just a stat open */
5832 FILE_SHARE_NONE, /* Ignored for stat opens */
5839 if (NT_STATUS_IS_OK(status)) {
5840 close_file(fsp, NORMAL_CLOSE);
5843 info_level_return = SVAL(pdata,16);
5845 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5846 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5847 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5848 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5850 *pdata_return_size = 12;
5853 /* Realloc the data size */
5854 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5855 if (*ppdata == NULL) {
5856 *pdata_return_size = 0;
5857 return NT_STATUS_NO_MEMORY;
5861 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5862 SSVAL(pdata,2,0); /* No fnum. */
5863 SIVAL(pdata,4,info); /* Was directory created. */
5865 switch (info_level_return) {
5866 case SMB_QUERY_FILE_UNIX_BASIC:
5867 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5868 SSVAL(pdata,10,0); /* Padding. */
5869 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5871 case SMB_QUERY_FILE_UNIX_INFO2:
5872 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5873 SSVAL(pdata,10,0); /* Padding. */
5874 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5877 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5878 SSVAL(pdata,10,0); /* Padding. */
5885 /****************************************************************************
5886 Open/Create a file with POSIX semantics.
5887 ****************************************************************************/
5889 static NTSTATUS smb_posix_open(connection_struct *conn,
5890 struct smb_request *req,
5894 SMB_STRUCT_STAT *psbuf,
5895 int *pdata_return_size)
5897 BOOL extended_oplock_granted = False;
5898 char *pdata = *ppdata;
5900 uint32 wire_open_mode = 0;
5901 uint32 raw_unixmode = 0;
5902 uint32 mod_unixmode = 0;
5903 uint32 create_disp = 0;
5904 uint32 access_mask = 0;
5905 uint32 create_options = 0;
5906 NTSTATUS status = NT_STATUS_OK;
5907 mode_t unixmode = (mode_t)0;
5908 files_struct *fsp = NULL;
5909 int oplock_request = 0;
5911 uint16 info_level_return = 0;
5913 if (total_data < 18) {
5914 return NT_STATUS_INVALID_PARAMETER;
5917 flags = IVAL(pdata,0);
5918 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5919 if (oplock_request) {
5920 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5923 wire_open_mode = IVAL(pdata,4);
5925 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5926 return smb_posix_mkdir(conn, req,
5934 switch (wire_open_mode & SMB_ACCMODE) {
5936 access_mask = FILE_READ_DATA;
5939 access_mask = FILE_WRITE_DATA;
5942 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5945 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5946 (unsigned int)wire_open_mode ));
5947 return NT_STATUS_INVALID_PARAMETER;
5950 wire_open_mode &= ~SMB_ACCMODE;
5952 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5953 create_disp = FILE_CREATE;
5954 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5955 create_disp = FILE_OVERWRITE_IF;
5956 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5957 create_disp = FILE_OPEN_IF;
5959 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5960 (unsigned int)wire_open_mode ));
5961 return NT_STATUS_INVALID_PARAMETER;
5964 raw_unixmode = IVAL(pdata,8);
5965 /* Next 4 bytes are not yet defined. */
5967 status = unix_perms_from_wire(conn,
5970 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5973 if (!NT_STATUS_IS_OK(status)) {
5977 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5979 if (wire_open_mode & SMB_O_SYNC) {
5980 create_options |= FILE_WRITE_THROUGH;
5982 if (wire_open_mode & SMB_O_APPEND) {
5983 access_mask |= FILE_APPEND_DATA;
5985 if (wire_open_mode & SMB_O_DIRECT) {
5986 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5989 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5991 (unsigned int)wire_open_mode,
5992 (unsigned int)unixmode ));
5994 status = open_file_ntcreate(conn, req,
5998 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6000 0, /* no create options yet. */
6006 if (!NT_STATUS_IS_OK(status)) {
6010 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6011 extended_oplock_granted = True;
6014 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6015 extended_oplock_granted = True;
6018 info_level_return = SVAL(pdata,16);
6020 /* Allocate the correct return size. */
6022 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6023 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6024 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6025 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6027 *pdata_return_size = 12;
6030 /* Realloc the data size */
6031 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6032 if (*ppdata == NULL) {
6033 close_file(fsp,ERROR_CLOSE);
6034 *pdata_return_size = 0;
6035 return NT_STATUS_NO_MEMORY;
6039 if (extended_oplock_granted) {
6040 if (flags & REQUEST_BATCH_OPLOCK) {
6041 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6043 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6045 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6046 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6048 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6051 SSVAL(pdata,2,fsp->fnum);
6052 SIVAL(pdata,4,info); /* Was file created etc. */
6054 switch (info_level_return) {
6055 case SMB_QUERY_FILE_UNIX_BASIC:
6056 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6057 SSVAL(pdata,10,0); /* padding. */
6058 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6060 case SMB_QUERY_FILE_UNIX_INFO2:
6061 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6062 SSVAL(pdata,10,0); /* padding. */
6063 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6066 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6067 SSVAL(pdata,10,0); /* padding. */
6070 return NT_STATUS_OK;
6073 /****************************************************************************
6074 Delete a file with POSIX semantics.
6075 ****************************************************************************/
6077 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6078 struct smb_request *req,
6082 SMB_STRUCT_STAT *psbuf)
6084 NTSTATUS status = NT_STATUS_OK;
6085 files_struct *fsp = NULL;
6090 struct share_mode_lock *lck = NULL;
6092 if (total_data < 2) {
6093 return NT_STATUS_INVALID_PARAMETER;
6096 flags = SVAL(pdata,0);
6098 if (!VALID_STAT(*psbuf)) {
6099 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6102 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6103 !VALID_STAT_OF_DIR(*psbuf)) {
6104 return NT_STATUS_NOT_A_DIRECTORY;
6107 DEBUG(10,("smb_posix_unlink: %s %s\n",
6108 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6111 if (VALID_STAT_OF_DIR(*psbuf)) {
6112 status = open_directory(conn, req,
6116 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6119 FILE_FLAG_POSIX_SEMANTICS|0777,
6124 status = open_file_ntcreate(conn, req,
6128 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6131 FILE_FLAG_POSIX_SEMANTICS|0777,
6132 0, /* No oplock, but break existing ones. */
6137 if (!NT_STATUS_IS_OK(status)) {
6142 * Don't lie to client. If we can't really delete due to
6143 * non-POSIX opens return SHARING_VIOLATION.
6146 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
6148 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6149 "lock for file %s\n", fsp->fsp_name));
6150 close_file(fsp, NORMAL_CLOSE);
6151 return NT_STATUS_INVALID_PARAMETER;
6155 * See if others still have the file open. If this is the case, then
6156 * don't delete. If all opens are POSIX delete we can set the delete
6157 * on close disposition.
6159 for (i=0; i<lck->num_share_modes; i++) {
6160 struct share_mode_entry *e = &lck->share_modes[i];
6161 if (is_valid_share_mode_entry(e)) {
6162 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6165 /* Fail with sharing violation. */
6166 close_file(fsp, NORMAL_CLOSE);
6168 return NT_STATUS_SHARING_VIOLATION;
6173 * Set the delete on close.
6175 status = smb_set_file_disposition_info(conn,
6182 if (!NT_STATUS_IS_OK(status)) {
6183 close_file(fsp, NORMAL_CLOSE);
6188 return close_file(fsp, NORMAL_CLOSE);
6191 /****************************************************************************
6192 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6193 ****************************************************************************/
6195 static void call_trans2setfilepathinfo(connection_struct *conn,
6196 struct smb_request *req,
6197 unsigned int tran_call,
6198 char **pparams, int total_params,
6199 char **ppdata, int total_data,
6200 unsigned int max_data_bytes)
6202 char *params = *pparams;
6203 char *pdata = *ppdata;
6205 SMB_STRUCT_STAT sbuf;
6207 files_struct *fsp = NULL;
6208 NTSTATUS status = NT_STATUS_OK;
6209 int data_return_size = 0;
6210 TALLOC_CTX *ctx = talloc_tos();
6213 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6219 if (tran_call == TRANSACT2_SETFILEINFO) {
6220 if (total_params < 4) {
6221 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6225 fsp = file_fsp(SVAL(params,0));
6226 /* Basic check for non-null fsp. */
6227 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
6230 info_level = SVAL(params,2);
6232 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6234 reply_nterror(req, NT_STATUS_NO_MEMORY);
6238 if(fsp->is_directory || fsp->fh->fd == -1) {
6240 * This is actually a SETFILEINFO on a directory
6241 * handle (returned from an NT SMB). NT5.0 seems
6242 * to do this call. JRA.
6244 if (INFO_LEVEL_IS_UNIX(info_level)) {
6245 /* Always do lstat for UNIX calls. */
6246 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6247 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6248 reply_unixerror(req,ERRDOS,ERRbadpath);
6252 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6253 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6254 reply_unixerror(req,ERRDOS,ERRbadpath);
6258 } else if (fsp->print_file) {
6260 * Doing a DELETE_ON_CLOSE should cancel a print job.
6262 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6263 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6265 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6268 send_trans2_replies(req, params, 2,
6273 reply_unixerror(req, ERRDOS, ERRbadpath);
6278 * Original code - this is an open file.
6280 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6284 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6285 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6286 reply_unixerror(req, ERRDOS, ERRbadfid);
6292 if (total_params < 7) {
6293 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6297 info_level = SVAL(params,0);
6298 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6299 total_params - 6, STR_TERMINATE,
6301 if (!NT_STATUS_IS_OK(status)) {
6302 reply_nterror(req, status);
6306 status = resolve_dfspath(ctx, conn,
6307 req->flags2 & FLAGS2_DFS_PATHNAMES,
6310 if (!NT_STATUS_IS_OK(status)) {
6311 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6312 reply_botherror(req,
6313 NT_STATUS_PATH_NOT_COVERED,
6314 ERRSRV, ERRbadpath);
6317 reply_nterror(req, status);
6321 status = unix_convert(ctx, conn, fname, False,
6322 &fname, NULL, &sbuf);
6323 if (!NT_STATUS_IS_OK(status)) {
6324 reply_nterror(req, status);
6328 status = check_name(conn, fname);
6329 if (!NT_STATUS_IS_OK(status)) {
6330 reply_nterror(req, status);
6334 if (INFO_LEVEL_IS_UNIX(info_level)) {
6336 * For CIFS UNIX extensions the target name may not exist.
6339 /* Always do lstat for UNIX calls. */
6340 SMB_VFS_LSTAT(conn,fname,&sbuf);
6342 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6343 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6344 reply_unixerror(req, ERRDOS, ERRbadpath);
6349 if (!CAN_WRITE(conn)) {
6350 reply_doserror(req, ERRSRV, ERRaccess);
6354 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6355 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6359 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6360 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6362 /* Realloc the parameter size */
6363 *pparams = (char *)SMB_REALLOC(*pparams,2);
6364 if (*pparams == NULL) {
6365 reply_nterror(req, NT_STATUS_NO_MEMORY);
6372 if (fsp && !null_timespec(fsp->pending_modtime)) {
6373 /* the pending modtime overrides the current modtime */
6374 set_mtimespec(&sbuf, fsp->pending_modtime);
6377 switch (info_level) {
6379 case SMB_INFO_STANDARD:
6381 status = smb_set_info_standard(conn,
6390 case SMB_INFO_SET_EA:
6392 status = smb_info_set_ea(conn,
6400 case SMB_SET_FILE_BASIC_INFO:
6401 case SMB_FILE_BASIC_INFORMATION:
6403 status = smb_set_file_basic_info(conn,
6412 case SMB_FILE_ALLOCATION_INFORMATION:
6413 case SMB_SET_FILE_ALLOCATION_INFO:
6415 status = smb_set_file_allocation_info(conn, req,
6424 case SMB_FILE_END_OF_FILE_INFORMATION:
6425 case SMB_SET_FILE_END_OF_FILE_INFO:
6427 status = smb_set_file_end_of_file_info(conn, req,
6436 case SMB_FILE_DISPOSITION_INFORMATION:
6437 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6440 /* JRA - We used to just ignore this on a path ?
6441 * Shouldn't this be invalid level on a pathname
6444 if (tran_call != TRANSACT2_SETFILEINFO) {
6445 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6448 status = smb_set_file_disposition_info(conn,
6457 case SMB_FILE_POSITION_INFORMATION:
6459 status = smb_file_position_information(conn,
6466 /* From tridge Samba4 :
6467 * MODE_INFORMATION in setfileinfo (I have no
6468 * idea what "mode information" on a file is - it takes a value of 0,
6469 * 2, 4 or 6. What could it be?).
6472 case SMB_FILE_MODE_INFORMATION:
6474 status = smb_file_mode_information(conn,
6481 * CIFS UNIX extensions.
6484 case SMB_SET_FILE_UNIX_BASIC:
6486 status = smb_set_file_unix_basic(conn, req,
6495 case SMB_SET_FILE_UNIX_INFO2:
6497 status = smb_set_file_unix_info2(conn, req,
6506 case SMB_SET_FILE_UNIX_LINK:
6508 if (tran_call != TRANSACT2_SETPATHINFO) {
6509 /* We must have a pathname for this. */
6510 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6513 status = smb_set_file_unix_link(conn, req, pdata,
6518 case SMB_SET_FILE_UNIX_HLINK:
6520 if (tran_call != TRANSACT2_SETPATHINFO) {
6521 /* We must have a pathname for this. */
6522 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6525 status = smb_set_file_unix_hlink(conn, req,
6531 case SMB_FILE_RENAME_INFORMATION:
6533 status = smb_file_rename_information(conn, req,
6539 #if defined(HAVE_POSIX_ACLS)
6540 case SMB_SET_POSIX_ACL:
6542 status = smb_set_posix_acl(conn,
6552 case SMB_SET_POSIX_LOCK:
6554 if (tran_call != TRANSACT2_SETFILEINFO) {
6555 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6558 status = smb_set_posix_lock(conn, req->inbuf,
6559 smb_len(req->inbuf) + 4,
6560 pdata, total_data, fsp);
6564 case SMB_POSIX_PATH_OPEN:
6566 if (tran_call != TRANSACT2_SETPATHINFO) {
6567 /* We must have a pathname for this. */
6568 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6572 status = smb_posix_open(conn, req,
6581 case SMB_POSIX_PATH_UNLINK:
6583 if (tran_call != TRANSACT2_SETPATHINFO) {
6584 /* We must have a pathname for this. */
6585 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6589 status = smb_posix_unlink(conn, req,
6598 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6603 if (!NT_STATUS_IS_OK(status)) {
6604 if (open_was_deferred(req->mid)) {
6605 /* We have re-scheduled this call. */
6608 if (blocking_lock_was_deferred(req->mid)) {
6609 /* We have re-scheduled this call. */
6612 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6613 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6614 ERRSRV, ERRbadpath);
6617 if (info_level == SMB_POSIX_PATH_OPEN) {
6618 reply_openerror(req, status);
6622 reply_nterror(req, status);
6627 send_trans2_replies(req, params, 2, *ppdata, data_return_size,
6633 /****************************************************************************
6634 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6635 ****************************************************************************/
6637 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6638 char **pparams, int total_params,
6639 char **ppdata, int total_data,
6640 unsigned int max_data_bytes)
6642 char *params = *pparams;
6643 char *pdata = *ppdata;
6644 char *directory = NULL;
6645 SMB_STRUCT_STAT sbuf;
6646 NTSTATUS status = NT_STATUS_OK;
6647 struct ea_list *ea_list = NULL;
6648 TALLOC_CTX *ctx = talloc_tos();
6650 if (!CAN_WRITE(conn)) {
6651 reply_doserror(req, ERRSRV, ERRaccess);
6655 if (total_params < 5) {
6656 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6660 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
6661 total_params - 4, STR_TERMINATE,
6663 if (!NT_STATUS_IS_OK(status)) {
6664 reply_nterror(req, status);
6668 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6670 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6671 if (!NT_STATUS_IS_OK(status)) {
6672 reply_nterror(req, status);
6676 status = check_name(conn, directory);
6677 if (!NT_STATUS_IS_OK(status)) {
6678 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6679 reply_nterror(req, status);
6683 /* Any data in this call is an EA list. */
6684 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6685 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6690 * OS/2 workplace shell seems to send SET_EA requests of "null"
6691 * length (4 bytes containing IVAL 4).
6692 * They seem to have no effect. Bug #3212. JRA.
6695 if (total_data != 4) {
6696 if (total_data < 10) {
6697 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6701 if (IVAL(pdata,0) > total_data) {
6702 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6703 IVAL(pdata,0), (unsigned int)total_data));
6704 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6708 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6711 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6714 } else if (IVAL(pdata,0) != 4) {
6715 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6719 status = create_directory(conn, directory);
6721 if (!NT_STATUS_IS_OK(status)) {
6722 reply_nterror(req, status);
6726 /* Try and set any given EA. */
6728 status = set_ea(conn, NULL, directory, ea_list);
6729 if (!NT_STATUS_IS_OK(status)) {
6730 reply_nterror(req, status);
6735 /* Realloc the parameter and data sizes */
6736 *pparams = (char *)SMB_REALLOC(*pparams,2);
6737 if(*pparams == NULL) {
6738 reply_nterror(req, NT_STATUS_NO_MEMORY);
6745 send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
6750 /****************************************************************************
6751 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6752 We don't actually do this - we just send a null response.
6753 ****************************************************************************/
6755 static void call_trans2findnotifyfirst(connection_struct *conn,
6756 struct smb_request *req,
6757 char **pparams, int total_params,
6758 char **ppdata, int total_data,
6759 unsigned int max_data_bytes)
6761 static uint16 fnf_handle = 257;
6762 char *params = *pparams;
6765 if (total_params < 6) {
6766 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6770 info_level = SVAL(params,4);
6771 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6773 switch (info_level) {
6778 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6782 /* Realloc the parameter and data sizes */
6783 *pparams = (char *)SMB_REALLOC(*pparams,6);
6784 if (*pparams == NULL) {
6785 reply_nterror(req, NT_STATUS_NO_MEMORY);
6790 SSVAL(params,0,fnf_handle);
6791 SSVAL(params,2,0); /* No changes */
6792 SSVAL(params,4,0); /* No EA errors */
6799 send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
6804 /****************************************************************************
6805 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6806 changes). Currently this does nothing.
6807 ****************************************************************************/
6809 static void call_trans2findnotifynext(connection_struct *conn,
6810 struct smb_request *req,
6811 char **pparams, int total_params,
6812 char **ppdata, int total_data,
6813 unsigned int max_data_bytes)
6815 char *params = *pparams;
6817 DEBUG(3,("call_trans2findnotifynext\n"));
6819 /* Realloc the parameter and data sizes */
6820 *pparams = (char *)SMB_REALLOC(*pparams,4);
6821 if (*pparams == NULL) {
6822 reply_nterror(req, NT_STATUS_NO_MEMORY);
6827 SSVAL(params,0,0); /* No changes */
6828 SSVAL(params,2,0); /* No EA errors */
6830 send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes);
6835 /****************************************************************************
6836 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6837 ****************************************************************************/
6839 static void call_trans2getdfsreferral(connection_struct *conn,
6840 struct smb_request *req,
6841 char **pparams, int total_params,
6842 char **ppdata, int total_data,
6843 unsigned int max_data_bytes)
6845 char *params = *pparams;
6846 char *pathname = NULL;
6848 int max_referral_level;
6849 NTSTATUS status = NT_STATUS_OK;
6850 TALLOC_CTX *ctx = talloc_tos();
6852 DEBUG(10,("call_trans2getdfsreferral\n"));
6854 if (total_params < 3) {
6855 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6859 max_referral_level = SVAL(params,0);
6861 if(!lp_host_msdfs()) {
6862 reply_doserror(req, ERRDOS, ERRbadfunc);
6866 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
6867 total_params - 2, STR_TERMINATE);
6869 reply_nterror(req, NT_STATUS_NOT_FOUND);
6872 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6873 ppdata,&status)) < 0) {
6874 reply_nterror(req, status);
6878 SSVAL(req->inbuf, smb_flg2,
6879 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6880 send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes);
6885 #define LMCAT_SPL 0x53
6886 #define LMFUNC_GETJOBID 0x60
6888 /****************************************************************************
6889 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6890 ****************************************************************************/
6892 static void call_trans2ioctl(connection_struct *conn,
6893 struct smb_request *req,
6894 char **pparams, int total_params,
6895 char **ppdata, int total_data,
6896 unsigned int max_data_bytes)
6898 char *pdata = *ppdata;
6899 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6901 /* check for an invalid fid before proceeding */
6904 reply_doserror(req, ERRDOS, ERRbadfid);
6908 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6909 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6910 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6911 if (*ppdata == NULL) {
6912 reply_nterror(req, NT_STATUS_NO_MEMORY);
6917 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6918 CAN ACCEPT THIS IN UNICODE. JRA. */
6920 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6921 srvstr_push(pdata, req->flags2, pdata + 2,
6922 global_myname(), 15,
6923 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6924 srvstr_push(pdata, req->flags2, pdata+18,
6925 lp_servicename(SNUM(conn)), 13,
6926 STR_ASCII|STR_TERMINATE); /* Service name */
6927 send_trans2_replies(req, *pparams, 0, *ppdata, 32,
6932 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6933 reply_doserror(req, ERRSRV, ERRerror);
6936 /****************************************************************************
6937 Reply to a SMBfindclose (stop trans2 directory search).
6938 ****************************************************************************/
6940 void reply_findclose(connection_struct *conn, struct smb_request *req)
6944 START_PROFILE(SMBfindclose);
6947 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6948 END_PROFILE(SMBfindclose);
6952 dptr_num = SVALS(req->inbuf,smb_vwv0);
6954 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6956 dptr_close(&dptr_num);
6958 reply_outbuf(req, 0, 0);
6960 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6962 END_PROFILE(SMBfindclose);
6966 /****************************************************************************
6967 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6968 ****************************************************************************/
6970 void reply_findnclose(connection_struct *conn, struct smb_request *req)
6974 START_PROFILE(SMBfindnclose);
6977 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6978 END_PROFILE(SMBfindnclose);
6982 dptr_num = SVAL(req->inbuf,smb_vwv0);
6984 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6986 /* We never give out valid handles for a
6987 findnotifyfirst - so any dptr_num is ok here.
6990 reply_outbuf(req, 0, 0);
6992 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6994 END_PROFILE(SMBfindnclose);
6998 static void handle_trans2(connection_struct *conn, struct smb_request *req,
6999 struct trans_state *state)
7001 if (Protocol >= PROTOCOL_NT1) {
7002 req->flags2 |= 0x40; /* IS_LONG_NAME */
7003 SSVAL(req->inbuf,smb_flg2,req->flags2);
7006 /* Now we must call the relevant TRANS2 function */
7007 switch(state->call) {
7008 case TRANSACT2_OPEN:
7010 START_PROFILE(Trans2_open);
7011 call_trans2open(conn, req,
7012 &state->param, state->total_param,
7013 &state->data, state->total_data,
7014 state->max_data_return);
7015 END_PROFILE(Trans2_open);
7019 case TRANSACT2_FINDFIRST:
7021 START_PROFILE(Trans2_findfirst);
7022 call_trans2findfirst(conn, req,
7023 &state->param, state->total_param,
7024 &state->data, state->total_data,
7025 state->max_data_return);
7026 END_PROFILE(Trans2_findfirst);
7030 case TRANSACT2_FINDNEXT:
7032 START_PROFILE(Trans2_findnext);
7033 call_trans2findnext(conn, req,
7034 &state->param, state->total_param,
7035 &state->data, state->total_data,
7036 state->max_data_return);
7037 END_PROFILE(Trans2_findnext);
7041 case TRANSACT2_QFSINFO:
7043 START_PROFILE(Trans2_qfsinfo);
7044 call_trans2qfsinfo(conn, req,
7045 &state->param, state->total_param,
7046 &state->data, state->total_data,
7047 state->max_data_return);
7048 END_PROFILE(Trans2_qfsinfo);
7052 case TRANSACT2_SETFSINFO:
7054 START_PROFILE(Trans2_setfsinfo);
7055 call_trans2setfsinfo(conn, req,
7056 &state->param, state->total_param,
7057 &state->data, state->total_data,
7058 state->max_data_return);
7059 END_PROFILE(Trans2_setfsinfo);
7063 case TRANSACT2_QPATHINFO:
7064 case TRANSACT2_QFILEINFO:
7066 START_PROFILE(Trans2_qpathinfo);
7067 call_trans2qfilepathinfo(conn, req, state->call,
7068 &state->param, state->total_param,
7069 &state->data, state->total_data,
7070 state->max_data_return);
7071 END_PROFILE(Trans2_qpathinfo);
7075 case TRANSACT2_SETPATHINFO:
7076 case TRANSACT2_SETFILEINFO:
7078 START_PROFILE(Trans2_setpathinfo);
7079 call_trans2setfilepathinfo(conn, req, state->call,
7080 &state->param, state->total_param,
7081 &state->data, state->total_data,
7082 state->max_data_return);
7083 END_PROFILE(Trans2_setpathinfo);
7087 case TRANSACT2_FINDNOTIFYFIRST:
7089 START_PROFILE(Trans2_findnotifyfirst);
7090 call_trans2findnotifyfirst(conn, req,
7091 &state->param, state->total_param,
7092 &state->data, state->total_data,
7093 state->max_data_return);
7094 END_PROFILE(Trans2_findnotifyfirst);
7098 case TRANSACT2_FINDNOTIFYNEXT:
7100 START_PROFILE(Trans2_findnotifynext);
7101 call_trans2findnotifynext(conn, req,
7102 &state->param, state->total_param,
7103 &state->data, state->total_data,
7104 state->max_data_return);
7105 END_PROFILE(Trans2_findnotifynext);
7109 case TRANSACT2_MKDIR:
7111 START_PROFILE(Trans2_mkdir);
7112 call_trans2mkdir(conn, req,
7113 &state->param, state->total_param,
7114 &state->data, state->total_data,
7115 state->max_data_return);
7116 END_PROFILE(Trans2_mkdir);
7120 case TRANSACT2_GET_DFS_REFERRAL:
7122 START_PROFILE(Trans2_get_dfs_referral);
7123 call_trans2getdfsreferral(conn, req,
7124 &state->param, state->total_param,
7125 &state->data, state->total_data,
7126 state->max_data_return);
7127 END_PROFILE(Trans2_get_dfs_referral);
7131 case TRANSACT2_IOCTL:
7133 START_PROFILE(Trans2_ioctl);
7134 call_trans2ioctl(conn, req,
7135 &state->param, state->total_param,
7136 &state->data, state->total_data,
7137 state->max_data_return);
7138 END_PROFILE(Trans2_ioctl);
7143 /* Error in request */
7144 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7145 reply_doserror(req, ERRSRV,ERRerror);
7149 /****************************************************************************
7150 Reply to a SMBtrans2.
7151 ****************************************************************************/
7153 void reply_trans2(connection_struct *conn, struct smb_request *req)
7159 unsigned int tran_call;
7161 struct trans_state *state;
7164 START_PROFILE(SMBtrans2);
7166 if (req->wct < 14) {
7167 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7168 END_PROFILE(SMBtrans2);
7172 dsoff = SVAL(req->inbuf, smb_dsoff);
7173 dscnt = SVAL(req->inbuf, smb_dscnt);
7174 psoff = SVAL(req->inbuf, smb_psoff);
7175 pscnt = SVAL(req->inbuf, smb_pscnt);
7176 tran_call = SVAL(req->inbuf, smb_setup0);
7177 size = smb_len(req->inbuf) + 4;
7179 result = allow_new_trans(conn->pending_trans, req->mid);
7180 if (!NT_STATUS_IS_OK(result)) {
7181 DEBUG(2, ("Got invalid trans2 request: %s\n",
7182 nt_errstr(result)));
7183 reply_nterror(req, result);
7184 END_PROFILE(SMBtrans2);
7188 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
7189 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
7190 && (tran_call != TRANSACT2_QFILEINFO)) {
7191 reply_doserror(req, ERRSRV, ERRaccess);
7192 END_PROFILE(SMBtrans2);
7196 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7197 DEBUG(0, ("talloc failed\n"));
7198 reply_nterror(req, NT_STATUS_NO_MEMORY);
7199 END_PROFILE(SMBtrans2);
7203 state->cmd = SMBtrans2;
7205 state->mid = req->mid;
7206 state->vuid = req->vuid;
7207 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7208 state->setup = NULL;
7209 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7210 state->param = NULL;
7211 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7213 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7214 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7215 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7216 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7217 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7219 state->call = tran_call;
7221 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7222 is so as a sanity check */
7223 if (state->setup_count != 1) {
7225 * Need to have rc=0 for ioctl to get job id for OS/2.
7226 * Network printing will fail if function is not successful.
7227 * Similar function in reply.c will be used if protocol
7228 * is LANMAN1.0 instead of LM1.2X002.
7229 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7230 * outbuf doesn't have to be set(only job id is used).
7232 if ( (state->setup_count == 4)
7233 && (tran_call == TRANSACT2_IOCTL)
7234 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7235 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7236 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7238 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7239 DEBUG(2,("Transaction is %d\n",tran_call));
7241 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7242 END_PROFILE(SMBtrans2);
7247 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7250 if (state->total_data) {
7251 /* Can't use talloc here, the core routines do realloc on the
7252 * params and data. */
7253 state->data = (char *)SMB_MALLOC(state->total_data);
7254 if (state->data == NULL) {
7255 DEBUG(0,("reply_trans2: data malloc fail for %u "
7256 "bytes !\n", (unsigned int)state->total_data));
7258 reply_nterror(req, NT_STATUS_NO_MEMORY);
7259 END_PROFILE(SMBtrans2);
7262 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7264 if ((smb_base(req->inbuf)+dsoff+dscnt
7265 > (char *)req->inbuf + size) ||
7266 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7269 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7272 if (state->total_param) {
7273 /* Can't use talloc here, the core routines do realloc on the
7274 * params and data. */
7275 state->param = (char *)SMB_MALLOC(state->total_param);
7276 if (state->param == NULL) {
7277 DEBUG(0,("reply_trans: param malloc fail for %u "
7278 "bytes !\n", (unsigned int)state->total_param));
7279 SAFE_FREE(state->data);
7281 reply_nterror(req, NT_STATUS_NO_MEMORY);
7282 END_PROFILE(SMBtrans2);
7285 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7287 if ((smb_base(req->inbuf)+psoff+pscnt
7288 > (char *)req->inbuf + size) ||
7289 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7292 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7295 state->received_data = dscnt;
7296 state->received_param = pscnt;
7298 if ((state->received_param == state->total_param) &&
7299 (state->received_data == state->total_data)) {
7301 handle_trans2(conn, req, state);
7303 SAFE_FREE(state->data);
7304 SAFE_FREE(state->param);
7306 END_PROFILE(SMBtrans2);
7310 DLIST_ADD(conn->pending_trans, state);
7312 /* We need to send an interim response then receive the rest
7313 of the parameter/data bytes */
7314 reply_outbuf(req, 0, 0);
7315 show_msg((char *)req->outbuf);
7316 END_PROFILE(SMBtrans2);
7321 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7322 SAFE_FREE(state->data);
7323 SAFE_FREE(state->param);
7325 END_PROFILE(SMBtrans2);
7326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7330 /****************************************************************************
7331 Reply to a SMBtranss2
7332 ****************************************************************************/
7334 void reply_transs2(connection_struct *conn, struct smb_request *req)
7336 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7337 struct trans_state *state;
7340 START_PROFILE(SMBtranss2);
7342 show_msg((char *)req->inbuf);
7345 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7346 END_PROFILE(SMBtranss2);
7350 size = smb_len(req->inbuf)+4;
7352 for (state = conn->pending_trans; state != NULL;
7353 state = state->next) {
7354 if (state->mid == req->mid) {
7359 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7360 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7361 END_PROFILE(SMBtranss2);
7365 /* Revise state->total_param and state->total_data in case they have
7366 changed downwards */
7368 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7369 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7370 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7371 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7373 pcnt = SVAL(req->inbuf, smb_spscnt);
7374 poff = SVAL(req->inbuf, smb_spsoff);
7375 pdisp = SVAL(req->inbuf, smb_spsdisp);
7377 dcnt = SVAL(req->inbuf, smb_sdscnt);
7378 doff = SVAL(req->inbuf, smb_sdsoff);
7379 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7381 state->received_param += pcnt;
7382 state->received_data += dcnt;
7384 if ((state->received_data > state->total_data) ||
7385 (state->received_param > state->total_param))
7389 if (pdisp+pcnt > state->total_param)
7391 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7393 if (pdisp > state->total_param)
7395 if ((smb_base(req->inbuf) + poff + pcnt
7396 > (char *)req->inbuf + size) ||
7397 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7399 if (state->param + pdisp < state->param)
7402 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7407 if (ddisp+dcnt > state->total_data)
7409 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7411 if (ddisp > state->total_data)
7413 if ((smb_base(req->inbuf) + doff + dcnt
7414 > (char *)req->inbuf + size) ||
7415 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7417 if (state->data + ddisp < state->data)
7420 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7424 if ((state->received_param < state->total_param) ||
7425 (state->received_data < state->total_data)) {
7426 END_PROFILE(SMBtranss2);
7431 * construct_reply_common will copy smb_com from inbuf to
7432 * outbuf. SMBtranss2 is wrong here.
7434 SCVAL(req->inbuf,smb_com,SMBtrans2);
7436 handle_trans2(conn, req, state);
7438 DLIST_REMOVE(conn->pending_trans, state);
7439 SAFE_FREE(state->data);
7440 SAFE_FREE(state->param);
7443 END_PROFILE(SMBtranss2);
7448 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7449 DLIST_REMOVE(conn->pending_trans, state);
7450 SAFE_FREE(state->data);
7451 SAFE_FREE(state->param);
7453 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7454 END_PROFILE(SMBtranss2);