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(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, char *str, char *mask)
1013 if (mask[0] == '.' && mask[1] == 0)
1015 if (conn->case_sensitive)
1016 return strcmp(str,mask)==0;
1017 if (StrCaseCmp(str,mask) != 0) {
1020 if (dptr_has_wild(conn->dirptr)) {
1026 /****************************************************************************
1027 Return the filetype for UNIX extensions.
1028 ****************************************************************************/
1030 static uint32 unix_filetype(mode_t mode)
1033 return UNIX_TYPE_FILE;
1034 else if(S_ISDIR(mode))
1035 return UNIX_TYPE_DIR;
1037 else if(S_ISLNK(mode))
1038 return UNIX_TYPE_SYMLINK;
1041 else if(S_ISCHR(mode))
1042 return UNIX_TYPE_CHARDEV;
1045 else if(S_ISBLK(mode))
1046 return UNIX_TYPE_BLKDEV;
1049 else if(S_ISFIFO(mode))
1050 return UNIX_TYPE_FIFO;
1053 else if(S_ISSOCK(mode))
1054 return UNIX_TYPE_SOCKET;
1057 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1058 return UNIX_TYPE_UNKNOWN;
1061 /****************************************************************************
1062 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1063 ****************************************************************************/
1065 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1067 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1068 SMB_STRUCT_STAT *psbuf,
1070 enum perm_type ptype,
1075 if (perms == SMB_MODE_NO_CHANGE) {
1076 if (!VALID_STAT(*psbuf)) {
1077 return NT_STATUS_INVALID_PARAMETER;
1079 *ret_perms = psbuf->st_mode;
1080 return NT_STATUS_OK;
1084 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1085 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1086 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1087 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1088 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1089 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1090 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1091 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1092 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1094 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1097 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1100 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1105 /* Apply mode mask */
1106 ret &= lp_create_mask(SNUM(conn));
1107 /* Add in force bits */
1108 ret |= lp_force_create_mode(SNUM(conn));
1111 ret &= lp_dir_mask(SNUM(conn));
1112 /* Add in force bits */
1113 ret |= lp_force_dir_mode(SNUM(conn));
1115 case PERM_EXISTING_FILE:
1116 /* Apply mode mask */
1117 ret &= lp_security_mask(SNUM(conn));
1118 /* Add in force bits */
1119 ret |= lp_force_security_mode(SNUM(conn));
1121 case PERM_EXISTING_DIR:
1122 /* Apply mode mask */
1123 ret &= lp_dir_security_mask(SNUM(conn));
1124 /* Add in force bits */
1125 ret |= lp_force_dir_security_mode(SNUM(conn));
1130 return NT_STATUS_OK;
1133 /****************************************************************************
1134 Get a level dependent lanman2 dir entry.
1135 ****************************************************************************/
1137 static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
1138 char *path_mask,uint32 dirtype,int info_level,
1139 int requires_resume_key,
1140 BOOL dont_descend,char **ppdata,
1141 char *base_data, char *end_data,
1142 int space_remaining,
1143 BOOL *out_of_space, BOOL *got_exact_match,
1144 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1148 SMB_STRUCT_STAT sbuf;
1152 char *p, *q, *pdata = *ppdata;
1156 SMB_OFF_T file_size = 0;
1157 SMB_BIG_UINT allocation_size = 0;
1159 struct timespec mdate_ts, adate_ts, create_date_ts;
1160 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1162 char *last_entry_ptr;
1164 uint32 nt_extmode; /* Used for NT connections instead of mode */
1165 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1166 BOOL check_mangled_names = lp_manglednames(conn->params);
1167 char mangled_name[13]; /* mangled 8.3 name. */
1170 *out_of_space = False;
1171 *got_exact_match = False;
1173 ZERO_STRUCT(mdate_ts);
1174 ZERO_STRUCT(adate_ts);
1175 ZERO_STRUCT(create_date_ts);
1180 p = strrchr_m(path_mask,'/');
1183 pstrcpy(mask,"*.*");
1187 pstrcpy(mask, path_mask);
1192 BOOL ms_dfs_link = False;
1194 /* Needed if we run out of space */
1195 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1196 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1199 * Due to bugs in NT client redirectors we are not using
1200 * resume keys any more - set them to zero.
1201 * Check out the related comments in findfirst/findnext.
1207 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1208 (long)conn->dirptr,curr_dirpos));
1215 * fname may get mangled, dname is never mangled.
1216 * Whenever we're accessing the filesystem we use
1217 * pathreal which is composed from dname.
1220 pstrcpy(fname,dname);
1222 /* Mangle fname if it's an illegal name. */
1223 if (mangle_must_mangle(fname,conn->params)) {
1224 if (!name_to_8_3(fname,mangled_name,True,conn->params)) {
1225 continue; /* Error - couldn't mangle. */
1227 pstrcpy(fname,mangled_name);
1230 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1231 got_match = mask_match(fname, mask, conn->case_sensitive);
1234 if(!got_match && check_mangled_names &&
1235 !mangle_is_8_3(fname, False, conn->params)) {
1237 * It turns out that NT matches wildcards against
1238 * both long *and* short names. This may explain some
1239 * of the wildcard wierdness from old DOS clients
1240 * that some people have been seeing.... JRA.
1242 /* Force the mangling into 8.3. */
1243 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1244 continue; /* Error - couldn't mangle. */
1247 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1248 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1253 BOOL isdots = (strequal(dname,"..") || strequal(dname,"."));
1254 if (dont_descend && !isdots) {
1258 pstrcpy(pathreal,conn->dirpath);
1260 pstrcat(pathreal,"/");
1262 pstrcat(pathreal,dname);
1264 if (INFO_LEVEL_IS_UNIX(info_level)) {
1265 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1266 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1267 pathreal,strerror(errno)));
1270 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1271 /* Needed to show the msdfs symlinks as
1274 if(lp_host_msdfs() &&
1275 lp_msdfs_root(SNUM(conn)) &&
1276 ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) {
1277 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1280 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1284 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1285 pathreal,strerror(errno)));
1291 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1293 mode = dos_mode(conn,pathreal,&sbuf);
1296 if (!dir_check_ftype(conn,mode,dirtype)) {
1297 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1301 if (!(mode & aDIR)) {
1302 file_size = get_file_size(sbuf);
1304 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1306 mdate_ts = get_mtimespec(&sbuf);
1307 adate_ts = get_atimespec(&sbuf);
1308 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1310 if (lp_dos_filetime_resolution(SNUM(conn))) {
1311 dos_filetime_timespec(&create_date_ts);
1312 dos_filetime_timespec(&mdate_ts);
1313 dos_filetime_timespec(&adate_ts);
1316 create_date = convert_timespec_to_time_t(create_date_ts);
1317 mdate = convert_timespec_to_time_t(mdate_ts);
1318 adate = convert_timespec_to_time_t(adate_ts);
1320 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1324 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1331 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1333 switch (info_level) {
1334 case SMB_FIND_INFO_STANDARD:
1335 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1336 if(requires_resume_key) {
1340 srv_put_dos_date2(p,0,create_date);
1341 srv_put_dos_date2(p,4,adate);
1342 srv_put_dos_date2(p,8,mdate);
1343 SIVAL(p,12,(uint32)file_size);
1344 SIVAL(p,16,(uint32)allocation_size);
1348 p += align_string(pdata, p, 0);
1349 len = srvstr_push(base_data, flags2, p,
1350 fname, PTR_DIFF(end_data, p),
1352 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1354 SCVAL(nameptr, -1, len - 2);
1356 SCVAL(nameptr, -1, 0);
1360 SCVAL(nameptr, -1, len - 1);
1362 SCVAL(nameptr, -1, 0);
1368 case SMB_FIND_EA_SIZE:
1369 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1370 if(requires_resume_key) {
1374 srv_put_dos_date2(p,0,create_date);
1375 srv_put_dos_date2(p,4,adate);
1376 srv_put_dos_date2(p,8,mdate);
1377 SIVAL(p,12,(uint32)file_size);
1378 SIVAL(p,16,(uint32)allocation_size);
1381 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1382 SIVAL(p,22,ea_size); /* Extended attributes */
1386 len = srvstr_push(base_data, flags2,
1387 p, fname, PTR_DIFF(end_data, p),
1388 STR_TERMINATE | STR_NOALIGN);
1389 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1402 SCVAL(nameptr,0,len);
1404 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1407 case SMB_FIND_EA_LIST:
1409 struct ea_list *file_list = NULL;
1412 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1416 if(requires_resume_key) {
1420 srv_put_dos_date2(p,0,create_date);
1421 srv_put_dos_date2(p,4,adate);
1422 srv_put_dos_date2(p,8,mdate);
1423 SIVAL(p,12,(uint32)file_size);
1424 SIVAL(p,16,(uint32)allocation_size);
1426 p += 22; /* p now points to the EA area. */
1428 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1429 name_list = ea_list_union(name_list, file_list, &ea_len);
1431 /* We need to determine if this entry will fit in the space available. */
1432 /* Max string size is 255 bytes. */
1433 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1434 /* Move the dirptr back to prev_dirpos */
1435 dptr_SeekDir(conn->dirptr, prev_dirpos);
1436 *out_of_space = True;
1437 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1438 return False; /* Not finished - just out of space */
1441 /* Push the ea_data followed by the name. */
1442 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1444 len = srvstr_push(base_data, flags2,
1445 p + 1, fname, PTR_DIFF(end_data, p),
1446 STR_TERMINATE | STR_NOALIGN);
1447 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1460 SCVAL(nameptr,0,len);
1462 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1466 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1467 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1468 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1470 SIVAL(p,0,reskey); p += 4;
1471 put_long_date_timespec(p,create_date_ts); p += 8;
1472 put_long_date_timespec(p,adate_ts); p += 8;
1473 put_long_date_timespec(p,mdate_ts); p += 8;
1474 put_long_date_timespec(p,mdate_ts); p += 8;
1475 SOFF_T(p,0,file_size); p += 8;
1476 SOFF_T(p,0,allocation_size); p += 8;
1477 SIVAL(p,0,nt_extmode); p += 4;
1478 q = p; p += 4; /* q is placeholder for name length. */
1480 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1481 SIVAL(p,0,ea_size); /* Extended attributes */
1484 /* Clear the short name buffer. This is
1485 * IMPORTANT as not doing so will trigger
1486 * a Win2k client bug. JRA.
1488 if (!was_8_3 && check_mangled_names) {
1489 if (!name_to_8_3(fname,mangled_name,True,
1491 /* Error - mangle failed ! */
1492 memset(mangled_name,'\0',12);
1494 mangled_name[12] = 0;
1495 len = srvstr_push(base_data, flags2,
1496 p+2, mangled_name, 24,
1497 STR_UPPER|STR_UNICODE);
1499 memset(p + 2 + len,'\0',24 - len);
1506 len = srvstr_push(base_data, flags2, p,
1507 fname, PTR_DIFF(end_data, p),
1508 STR_TERMINATE_ASCII);
1511 SIVAL(p,0,0); /* Ensure any padding is null. */
1512 len = PTR_DIFF(p, pdata);
1513 len = (len + 3) & ~3;
1518 case SMB_FIND_FILE_DIRECTORY_INFO:
1519 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1521 SIVAL(p,0,reskey); p += 4;
1522 put_long_date_timespec(p,create_date_ts); p += 8;
1523 put_long_date_timespec(p,adate_ts); p += 8;
1524 put_long_date_timespec(p,mdate_ts); p += 8;
1525 put_long_date_timespec(p,mdate_ts); p += 8;
1526 SOFF_T(p,0,file_size); p += 8;
1527 SOFF_T(p,0,allocation_size); p += 8;
1528 SIVAL(p,0,nt_extmode); p += 4;
1529 len = srvstr_push(base_data, flags2,
1530 p + 4, fname, PTR_DIFF(end_data, p),
1531 STR_TERMINATE_ASCII);
1534 SIVAL(p,0,0); /* Ensure any padding is null. */
1535 len = PTR_DIFF(p, pdata);
1536 len = (len + 3) & ~3;
1541 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1542 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1544 SIVAL(p,0,reskey); p += 4;
1545 put_long_date_timespec(p,create_date_ts); p += 8;
1546 put_long_date_timespec(p,adate_ts); p += 8;
1547 put_long_date_timespec(p,mdate_ts); p += 8;
1548 put_long_date_timespec(p,mdate_ts); p += 8;
1549 SOFF_T(p,0,file_size); p += 8;
1550 SOFF_T(p,0,allocation_size); p += 8;
1551 SIVAL(p,0,nt_extmode); p += 4;
1552 q = p; p += 4; /* q is placeholder for name length. */
1554 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1555 SIVAL(p,0,ea_size); /* Extended attributes */
1558 len = srvstr_push(base_data, flags2, p,
1559 fname, PTR_DIFF(end_data, p),
1560 STR_TERMINATE_ASCII);
1564 SIVAL(p,0,0); /* Ensure any padding is null. */
1565 len = PTR_DIFF(p, pdata);
1566 len = (len + 3) & ~3;
1571 case SMB_FIND_FILE_NAMES_INFO:
1572 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1574 SIVAL(p,0,reskey); p += 4;
1576 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1577 acl on a dir (tridge) */
1578 len = srvstr_push(base_data, flags2, p,
1579 fname, PTR_DIFF(end_data, p),
1580 STR_TERMINATE_ASCII);
1583 SIVAL(p,0,0); /* Ensure any padding is null. */
1584 len = PTR_DIFF(p, pdata);
1585 len = (len + 3) & ~3;
1590 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1591 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1593 SIVAL(p,0,reskey); p += 4;
1594 put_long_date_timespec(p,create_date_ts); p += 8;
1595 put_long_date_timespec(p,adate_ts); p += 8;
1596 put_long_date_timespec(p,mdate_ts); p += 8;
1597 put_long_date_timespec(p,mdate_ts); p += 8;
1598 SOFF_T(p,0,file_size); p += 8;
1599 SOFF_T(p,0,allocation_size); p += 8;
1600 SIVAL(p,0,nt_extmode); p += 4;
1601 q = p; p += 4; /* q is placeholder for name length. */
1603 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1604 SIVAL(p,0,ea_size); /* Extended attributes */
1607 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1608 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1609 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1610 len = srvstr_push(base_data, flags2, p,
1611 fname, PTR_DIFF(end_data, p),
1612 STR_TERMINATE_ASCII);
1615 SIVAL(p,0,0); /* Ensure any padding is null. */
1616 len = PTR_DIFF(p, pdata);
1617 len = (len + 3) & ~3;
1622 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1623 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1624 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1626 SIVAL(p,0,reskey); p += 4;
1627 put_long_date_timespec(p,create_date_ts); p += 8;
1628 put_long_date_timespec(p,adate_ts); p += 8;
1629 put_long_date_timespec(p,mdate_ts); p += 8;
1630 put_long_date_timespec(p,mdate_ts); p += 8;
1631 SOFF_T(p,0,file_size); p += 8;
1632 SOFF_T(p,0,allocation_size); p += 8;
1633 SIVAL(p,0,nt_extmode); p += 4;
1634 q = p; p += 4; /* q is placeholder for name length */
1636 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1637 SIVAL(p,0,ea_size); /* Extended attributes */
1640 /* Clear the short name buffer. This is
1641 * IMPORTANT as not doing so will trigger
1642 * a Win2k client bug. JRA.
1644 if (!was_8_3 && check_mangled_names) {
1645 if (!name_to_8_3(fname,mangled_name,True,
1647 /* Error - mangle failed ! */
1648 memset(mangled_name,'\0',12);
1650 mangled_name[12] = 0;
1651 len = srvstr_push(base_data, flags2,
1652 p+2, mangled_name, 24,
1653 STR_UPPER|STR_UNICODE);
1656 memset(p + 2 + len,'\0',24 - len);
1663 SSVAL(p,0,0); p += 2; /* Reserved ? */
1664 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1665 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1666 len = srvstr_push(base_data, flags2, p,
1667 fname, PTR_DIFF(end_data, p),
1668 STR_TERMINATE_ASCII);
1671 SIVAL(p,0,0); /* Ensure any padding is null. */
1672 len = PTR_DIFF(p, pdata);
1673 len = (len + 3) & ~3;
1678 /* CIFS UNIX Extension. */
1680 case SMB_FIND_FILE_UNIX:
1681 case SMB_FIND_FILE_UNIX_INFO2:
1683 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1685 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1687 if (info_level == SMB_FIND_FILE_UNIX) {
1688 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1689 p = store_file_unix_basic(conn, p,
1691 len = srvstr_push(base_data, flags2, p,
1692 fname, PTR_DIFF(end_data, p),
1695 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1696 p = store_file_unix_basic_info2(conn, p,
1700 len = srvstr_push(base_data, flags2, p, fname,
1701 PTR_DIFF(end_data, p), 0);
1702 SIVAL(nameptr, 0, len);
1706 SIVAL(p,0,0); /* Ensure any padding is null. */
1708 len = PTR_DIFF(p, pdata);
1709 len = (len + 3) & ~3;
1710 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1712 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1721 if (PTR_DIFF(p,pdata) > space_remaining) {
1722 /* Move the dirptr back to prev_dirpos */
1723 dptr_SeekDir(conn->dirptr, prev_dirpos);
1724 *out_of_space = True;
1725 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1726 return False; /* Not finished - just out of space */
1729 /* Setup the last entry pointer, as an offset from base_data */
1730 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1731 /* Advance the data pointer to the next slot */
1737 /****************************************************************************
1738 Reply to a TRANS2_FINDFIRST.
1739 ****************************************************************************/
1741 static void call_trans2findfirst(connection_struct *conn,
1742 struct smb_request *req,
1743 char **pparams, int total_params,
1744 char **ppdata, int total_data,
1745 unsigned int max_data_bytes)
1747 /* We must be careful here that we don't return more than the
1748 allowed number of data bytes. If this means returning fewer than
1749 maxentries then so be it. We assume that the redirector has
1750 enough room for the fixed number of parameter bytes it has
1752 char *params = *pparams;
1753 char *pdata = *ppdata;
1757 uint16 findfirst_flags;
1758 BOOL close_after_first;
1760 BOOL requires_resume_key;
1762 char *directory = NULL;
1765 int last_entry_off=0;
1769 BOOL finished = False;
1770 BOOL dont_descend = False;
1771 BOOL out_of_space = False;
1772 int space_remaining;
1773 BOOL mask_contains_wcard = False;
1774 SMB_STRUCT_STAT sbuf;
1775 TALLOC_CTX *ea_ctx = NULL;
1776 struct ea_list *ea_list = NULL;
1777 NTSTATUS ntstatus = NT_STATUS_OK;
1778 TALLOC_CTX *ctx = talloc_tos();
1780 if (total_params < 13) {
1781 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1785 dirtype = SVAL(params,0);
1786 maxentries = SVAL(params,2);
1787 findfirst_flags = SVAL(params,4);
1788 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1789 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1790 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1791 info_level = SVAL(params,6);
1795 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1796 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1797 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1798 info_level, max_data_bytes));
1801 /* W2K3 seems to treat zero as 1. */
1805 switch (info_level) {
1806 case SMB_FIND_INFO_STANDARD:
1807 case SMB_FIND_EA_SIZE:
1808 case SMB_FIND_EA_LIST:
1809 case SMB_FIND_FILE_DIRECTORY_INFO:
1810 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1811 case SMB_FIND_FILE_NAMES_INFO:
1812 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1813 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1814 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1816 case SMB_FIND_FILE_UNIX:
1817 case SMB_FIND_FILE_UNIX_INFO2:
1818 if (!lp_unix_extensions()) {
1819 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1824 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1828 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1829 params+12, total_params - 12,
1830 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1831 if (!NT_STATUS_IS_OK(ntstatus)) {
1832 reply_nterror(req, ntstatus);
1836 ntstatus = resolve_dfspath_wcard(ctx, conn,
1837 req->flags2 & FLAGS2_DFS_PATHNAMES,
1840 &mask_contains_wcard);
1841 if (!NT_STATUS_IS_OK(ntstatus)) {
1842 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1843 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1844 ERRSRV, ERRbadpath);
1847 reply_nterror(req, ntstatus);
1851 ntstatus = unix_convert(conn, directory, True, &directory, NULL, &sbuf);
1852 if (!NT_STATUS_IS_OK(ntstatus)) {
1853 reply_nterror(req, ntstatus);
1857 ntstatus = check_name(conn, directory);
1858 if (!NT_STATUS_IS_OK(ntstatus)) {
1859 reply_nterror(req, ntstatus);
1863 p = strrchr_m(directory,'/');
1865 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1866 if((directory[0] == '.') && (directory[1] == '\0')) {
1868 mask_contains_wcard = True;
1870 pstrcpy(mask,directory);
1872 directory = talloc_strdup(talloc_tos(), "./");
1874 reply_nterror(req, NT_STATUS_NO_MEMORY);
1882 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1884 if (info_level == SMB_FIND_EA_LIST) {
1887 if (total_data < 4) {
1888 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1892 ea_size = IVAL(pdata,0);
1893 if (ea_size != total_data) {
1894 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1895 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1900 if (!lp_ea_support(SNUM(conn))) {
1901 reply_doserror(req, ERRDOS, ERReasnotsupported);
1905 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1906 reply_nterror(req, NT_STATUS_NO_MEMORY);
1910 /* Pull out the list of names. */
1911 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1913 talloc_destroy(ea_ctx);
1914 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1919 *ppdata = (char *)SMB_REALLOC(
1920 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1921 if(*ppdata == NULL ) {
1922 talloc_destroy(ea_ctx);
1923 reply_nterror(req, NT_STATUS_NO_MEMORY);
1927 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1929 /* Realloc the params space */
1930 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1931 if (*pparams == NULL) {
1932 talloc_destroy(ea_ctx);
1933 reply_nterror(req, NT_STATUS_NO_MEMORY);
1938 /* Save the wildcard match and attribs we are using on this directory -
1939 needed as lanman2 assumes these are being saved between calls */
1941 ntstatus = dptr_create(conn,
1947 mask_contains_wcard,
1951 if (!NT_STATUS_IS_OK(ntstatus)) {
1952 talloc_destroy(ea_ctx);
1953 reply_nterror(req, ntstatus);
1957 dptr_num = dptr_dnum(conn->dirptr);
1958 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1960 /* We don't need to check for VOL here as this is returned by
1961 a different TRANS2 call. */
1963 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1964 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1965 dont_descend = True;
1968 space_remaining = max_data_bytes;
1969 out_of_space = False;
1971 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1972 BOOL got_exact_match = False;
1974 /* this is a heuristic to avoid seeking the dirptr except when
1975 absolutely necessary. It allows for a filename of about 40 chars */
1976 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1977 out_of_space = True;
1980 finished = !get_lanman2_dir_entry(conn,
1982 mask,dirtype,info_level,
1983 requires_resume_key,dont_descend,
1985 space_remaining, &out_of_space,
1987 &last_entry_off, ea_list, ea_ctx);
1990 if (finished && out_of_space)
1993 if (!finished && !out_of_space)
1997 * As an optimisation if we know we aren't looking
1998 * for a wildcard name (ie. the name matches the wildcard exactly)
1999 * then we can finish on any (first) match.
2000 * This speeds up large directory searches. JRA.
2006 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2009 talloc_destroy(ea_ctx);
2011 /* Check if we can close the dirptr */
2012 if(close_after_first || (finished && close_if_end)) {
2013 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2014 dptr_close(&dptr_num);
2018 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2019 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2020 * the protocol level is less than NT1. Tested with smbclient. JRA.
2021 * This should fix the OS/2 client bug #2335.
2024 if(numentries == 0) {
2025 dptr_close(&dptr_num);
2026 if (Protocol < PROTOCOL_NT1) {
2027 reply_doserror(req, ERRDOS, ERRnofiles);
2030 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2031 ERRDOS, ERRbadfile);
2036 /* At this point pdata points to numentries directory entries. */
2038 /* Set up the return parameter block */
2039 SSVAL(params,0,dptr_num);
2040 SSVAL(params,2,numentries);
2041 SSVAL(params,4,finished);
2042 SSVAL(params,6,0); /* Never an EA error */
2043 SSVAL(params,8,last_entry_off);
2045 send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
2048 if ((! *directory) && dptr_path(dptr_num)) {
2049 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2051 reply_nterror(req, NT_STATUS_NO_MEMORY);
2055 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2056 smb_fn_name(CVAL(req->inbuf,smb_com)),
2057 mask, directory, dirtype, numentries ) );
2060 * Force a name mangle here to ensure that the
2061 * mask as an 8.3 name is top of the mangled cache.
2062 * The reasons for this are subtle. Don't remove
2063 * this code unless you know what you are doing
2064 * (see PR#13758). JRA.
2067 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2068 char mangled_name[13];
2069 name_to_8_3(mask, mangled_name, True, conn->params);
2075 /****************************************************************************
2076 Reply to a TRANS2_FINDNEXT.
2077 ****************************************************************************/
2079 static void call_trans2findnext(connection_struct *conn,
2080 struct smb_request *req,
2081 char **pparams, int total_params,
2082 char **ppdata, int total_data,
2083 unsigned int max_data_bytes)
2085 /* We must be careful here that we don't return more than the
2086 allowed number of data bytes. If this means returning fewer than
2087 maxentries then so be it. We assume that the redirector has
2088 enough room for the fixed number of parameter bytes it has
2090 char *params = *pparams;
2091 char *pdata = *ppdata;
2097 uint16 findnext_flags;
2098 BOOL close_after_request;
2100 BOOL requires_resume_key;
2102 BOOL mask_contains_wcard = False;
2103 char *resume_name = NULL;
2109 int i, last_entry_off=0;
2110 BOOL finished = False;
2111 BOOL dont_descend = False;
2112 BOOL out_of_space = False;
2113 int space_remaining;
2114 TALLOC_CTX *ea_ctx = NULL;
2115 struct ea_list *ea_list = NULL;
2116 NTSTATUS ntstatus = NT_STATUS_OK;
2117 TALLOC_CTX *ctx = talloc_tos();
2119 if (total_params < 13) {
2120 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2124 dptr_num = SVAL(params,0);
2125 maxentries = SVAL(params,2);
2126 info_level = SVAL(params,4);
2127 resume_key = IVAL(params,6);
2128 findnext_flags = SVAL(params,10);
2129 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2130 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2131 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2132 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2134 *mask = *directory = 0;
2136 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2138 total_params - 12, STR_TERMINATE, &ntstatus,
2139 &mask_contains_wcard);
2140 if (!NT_STATUS_IS_OK(ntstatus)) {
2141 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2142 complain (it thinks we're asking for the directory above the shared
2143 path or an invalid name). Catch this as the resume name is only compared, never used in
2144 a file access. JRA. */
2145 srvstr_pull_talloc(ctx, params, req->flags2,
2146 &resume_name, params+12,
2150 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2151 reply_nterror(req, ntstatus);
2156 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2157 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2158 resume_key = %d resume name = %s continue=%d level = %d\n",
2159 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2160 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2163 /* W2K3 seems to treat zero as 1. */
2167 switch (info_level) {
2168 case SMB_FIND_INFO_STANDARD:
2169 case SMB_FIND_EA_SIZE:
2170 case SMB_FIND_EA_LIST:
2171 case SMB_FIND_FILE_DIRECTORY_INFO:
2172 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2173 case SMB_FIND_FILE_NAMES_INFO:
2174 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2175 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2176 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2178 case SMB_FIND_FILE_UNIX:
2179 case SMB_FIND_FILE_UNIX_INFO2:
2180 if (!lp_unix_extensions()) {
2181 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2186 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2190 if (info_level == SMB_FIND_EA_LIST) {
2193 if (total_data < 4) {
2194 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2198 ea_size = IVAL(pdata,0);
2199 if (ea_size != total_data) {
2200 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2201 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2202 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2206 if (!lp_ea_support(SNUM(conn))) {
2207 reply_doserror(req, ERRDOS, ERReasnotsupported);
2211 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2212 reply_nterror(req, NT_STATUS_NO_MEMORY);
2216 /* Pull out the list of names. */
2217 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2219 talloc_destroy(ea_ctx);
2220 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2225 *ppdata = (char *)SMB_REALLOC(
2226 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2227 if(*ppdata == NULL) {
2228 talloc_destroy(ea_ctx);
2229 reply_nterror(req, NT_STATUS_NO_MEMORY);
2234 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2236 /* Realloc the params space */
2237 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2238 if(*pparams == NULL ) {
2239 talloc_destroy(ea_ctx);
2240 reply_nterror(req, NT_STATUS_NO_MEMORY);
2246 /* Check that the dptr is valid */
2247 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2248 talloc_destroy(ea_ctx);
2249 reply_doserror(req, ERRDOS, ERRnofiles);
2253 string_set(&conn->dirpath,dptr_path(dptr_num));
2255 /* Get the wildcard mask from the dptr */
2256 if((p = dptr_wcard(dptr_num))== NULL) {
2257 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2258 talloc_destroy(ea_ctx);
2259 reply_doserror(req, ERRDOS, ERRnofiles);
2264 pstrcpy(directory,conn->dirpath);
2266 /* Get the attr mask from the dptr */
2267 dirtype = dptr_attr(dptr_num);
2269 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2270 dptr_num, mask, dirtype,
2272 dptr_TellDir(conn->dirptr)));
2274 /* We don't need to check for VOL here as this is returned by
2275 a different TRANS2 call. */
2277 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2278 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2279 dont_descend = True;
2282 space_remaining = max_data_bytes;
2283 out_of_space = False;
2286 * Seek to the correct position. We no longer use the resume key but
2287 * depend on the last file name instead.
2290 if(*resume_name && !continue_bit) {
2293 long current_pos = 0;
2295 * Remember, name_to_8_3 is called by
2296 * get_lanman2_dir_entry(), so the resume name
2297 * could be mangled. Ensure we check the unmangled name.
2300 if (mangle_is_mangled(resume_name, conn->params)) {
2301 char *new_resume_name = NULL;
2302 mangle_lookup_name_from_8_3(talloc_tos(),
2306 if (new_resume_name) {
2307 pstrcpy(resume_name, new_resume_name);
2312 * Fix for NT redirector problem triggered by resume key indexes
2313 * changing between directory scans. We now return a resume key of 0
2314 * and instead look for the filename to continue from (also given
2315 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2316 * findfirst/findnext (as is usual) then the directory pointer
2317 * should already be at the correct place.
2320 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2321 } /* end if resume_name && !continue_bit */
2323 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2324 BOOL got_exact_match = False;
2326 /* this is a heuristic to avoid seeking the dirptr except when
2327 absolutely necessary. It allows for a filename of about 40 chars */
2328 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2329 out_of_space = True;
2332 finished = !get_lanman2_dir_entry(conn,
2334 mask,dirtype,info_level,
2335 requires_resume_key,dont_descend,
2337 space_remaining, &out_of_space,
2339 &last_entry_off, ea_list, ea_ctx);
2342 if (finished && out_of_space)
2345 if (!finished && !out_of_space)
2349 * As an optimisation if we know we aren't looking
2350 * for a wildcard name (ie. the name matches the wildcard exactly)
2351 * then we can finish on any (first) match.
2352 * This speeds up large directory searches. JRA.
2358 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2361 talloc_destroy(ea_ctx);
2363 /* Check if we can close the dirptr */
2364 if(close_after_request || (finished && close_if_end)) {
2365 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2366 dptr_close(&dptr_num); /* This frees up the saved mask */
2369 /* Set up the return parameter block */
2370 SSVAL(params,0,numentries);
2371 SSVAL(params,2,finished);
2372 SSVAL(params,4,0); /* Never an EA error */
2373 SSVAL(params,6,last_entry_off);
2375 send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata),
2378 if ((! *directory) && dptr_path(dptr_num))
2379 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2381 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2382 smb_fn_name(CVAL(req->inbuf,smb_com)),
2383 mask, directory, dirtype, numentries ) );
2388 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2390 E_md4hash(lp_servicename(SNUM(conn)),objid);
2394 /****************************************************************************
2395 Reply to a TRANS2_QFSINFO (query filesystem info).
2396 ****************************************************************************/
2398 static void call_trans2qfsinfo(connection_struct *conn,
2399 struct smb_request *req,
2400 char **pparams, int total_params,
2401 char **ppdata, int total_data,
2402 unsigned int max_data_bytes)
2404 char *pdata, *end_data;
2405 char *params = *pparams;
2409 const char *vname = volume_label(SNUM(conn));
2410 int snum = SNUM(conn);
2411 char *fstype = lp_fstype(SNUM(conn));
2414 if (total_params < 2) {
2415 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2419 info_level = SVAL(params,0);
2421 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2423 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2424 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2425 reply_doserror(req, ERRSRV, ERRinvdevice);
2429 *ppdata = (char *)SMB_REALLOC(
2430 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2431 if (*ppdata == NULL ) {
2432 reply_nterror(req, NT_STATUS_NO_MEMORY);
2437 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2438 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2440 switch (info_level) {
2441 case SMB_INFO_ALLOCATION:
2443 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2445 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2446 reply_unixerror(req, ERRHRD, ERRgeneral);
2450 block_size = lp_block_size(snum);
2451 if (bsize < block_size) {
2452 SMB_BIG_UINT factor = block_size/bsize;
2457 if (bsize > block_size) {
2458 SMB_BIG_UINT factor = bsize/block_size;
2463 bytes_per_sector = 512;
2464 sectors_per_unit = bsize/bytes_per_sector;
2466 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2467 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2468 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2470 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2471 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2472 SIVAL(pdata,l1_cUnit,dsize);
2473 SIVAL(pdata,l1_cUnitAvail,dfree);
2474 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2478 case SMB_INFO_VOLUME:
2479 /* Return volume name */
2481 * Add volume serial number - hash of a combination of
2482 * the called hostname and the service name.
2484 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2486 * Win2k3 and previous mess this up by sending a name length
2487 * one byte short. I believe only older clients (OS/2 Win9x) use
2488 * this call so try fixing this by adding a terminating null to
2489 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2493 pdata+l2_vol_szVolLabel, vname,
2494 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2495 STR_NOALIGN|STR_TERMINATE);
2496 SCVAL(pdata,l2_vol_cch,len);
2497 data_len = l2_vol_szVolLabel + len;
2498 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2499 (unsigned)st.st_ctime, len, vname));
2502 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2503 case SMB_FS_ATTRIBUTE_INFORMATION:
2506 #if defined(HAVE_SYS_QUOTAS)
2507 quota_flag = FILE_VOLUME_QUOTAS;
2510 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2511 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2512 FILE_SUPPORTS_OBJECT_IDS|
2513 FILE_UNICODE_ON_DISK|
2514 quota_flag); /* FS ATTRIBUTES */
2516 SIVAL(pdata,4,255); /* Max filename component length */
2517 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2518 and will think we can't do long filenames */
2519 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2520 PTR_DIFF(end_data, pdata+12),
2523 data_len = 12 + len;
2526 case SMB_QUERY_FS_LABEL_INFO:
2527 case SMB_FS_LABEL_INFORMATION:
2528 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2529 PTR_DIFF(end_data, pdata+4), 0);
2534 case SMB_QUERY_FS_VOLUME_INFO:
2535 case SMB_FS_VOLUME_INFORMATION:
2538 * Add volume serial number - hash of a combination of
2539 * the called hostname and the service name.
2541 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2542 (str_checksum(get_local_machine_name())<<16));
2544 /* Max label len is 32 characters. */
2545 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2546 PTR_DIFF(end_data, pdata+18),
2548 SIVAL(pdata,12,len);
2551 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2552 (int)strlen(vname),vname, lp_servicename(snum)));
2555 case SMB_QUERY_FS_SIZE_INFO:
2556 case SMB_FS_SIZE_INFORMATION:
2558 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2560 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2561 reply_unixerror(req, ERRHRD, ERRgeneral);
2564 block_size = lp_block_size(snum);
2565 if (bsize < block_size) {
2566 SMB_BIG_UINT factor = block_size/bsize;
2571 if (bsize > block_size) {
2572 SMB_BIG_UINT factor = bsize/block_size;
2577 bytes_per_sector = 512;
2578 sectors_per_unit = bsize/bytes_per_sector;
2579 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2580 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2581 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2582 SBIG_UINT(pdata,0,dsize);
2583 SBIG_UINT(pdata,8,dfree);
2584 SIVAL(pdata,16,sectors_per_unit);
2585 SIVAL(pdata,20,bytes_per_sector);
2589 case SMB_FS_FULL_SIZE_INFORMATION:
2591 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2593 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2594 reply_unixerror(req, ERRHRD, ERRgeneral);
2597 block_size = lp_block_size(snum);
2598 if (bsize < block_size) {
2599 SMB_BIG_UINT factor = block_size/bsize;
2604 if (bsize > block_size) {
2605 SMB_BIG_UINT factor = bsize/block_size;
2610 bytes_per_sector = 512;
2611 sectors_per_unit = bsize/bytes_per_sector;
2612 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2613 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2614 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2615 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2616 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2617 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2618 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2619 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2623 case SMB_QUERY_FS_DEVICE_INFO:
2624 case SMB_FS_DEVICE_INFORMATION:
2626 SIVAL(pdata,0,0); /* dev type */
2627 SIVAL(pdata,4,0); /* characteristics */
2630 #ifdef HAVE_SYS_QUOTAS
2631 case SMB_FS_QUOTA_INFORMATION:
2633 * what we have to send --metze:
2635 * Unknown1: 24 NULL bytes
2636 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2637 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2638 * Quota Flags: 2 byte :
2639 * Unknown3: 6 NULL bytes
2643 * details for Quota Flags:
2645 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2646 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2647 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2648 * 0x0001 Enable Quotas: enable quota for this fs
2652 /* we need to fake up a fsp here,
2653 * because its not send in this call
2656 SMB_NTQUOTA_STRUCT quotas;
2659 ZERO_STRUCT(quotas);
2665 if (current_user.ut.uid != 0) {
2666 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2667 lp_servicename(SNUM(conn)),conn->user));
2668 reply_doserror(req, ERRDOS, ERRnoaccess);
2672 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2673 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2674 reply_doserror(req, ERRSRV, ERRerror);
2680 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2682 /* Unknown1 24 NULL bytes*/
2683 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2684 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2685 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2687 /* Default Soft Quota 8 bytes */
2688 SBIG_UINT(pdata,24,quotas.softlim);
2690 /* Default Hard Quota 8 bytes */
2691 SBIG_UINT(pdata,32,quotas.hardlim);
2693 /* Quota flag 2 bytes */
2694 SSVAL(pdata,40,quotas.qflags);
2696 /* Unknown3 6 NULL bytes */
2702 #endif /* HAVE_SYS_QUOTAS */
2703 case SMB_FS_OBJECTID_INFORMATION:
2705 unsigned char objid[16];
2706 memcpy(pdata,create_volume_objectid(conn, objid),16);
2712 * Query the version and capabilities of the CIFS UNIX extensions
2716 case SMB_QUERY_CIFS_UNIX_INFO:
2717 if (!lp_unix_extensions()) {
2718 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2722 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2723 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2724 /* We have POSIX ACLs, pathname and locking capability. */
2725 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2726 CIFS_UNIX_POSIX_ACLS_CAP|
2727 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2728 CIFS_UNIX_FCNTL_LOCKS_CAP|
2729 CIFS_UNIX_EXTATTR_CAP|
2730 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2731 /* Ensure we don't do this on signed or sealed data. */
2732 (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2736 case SMB_QUERY_POSIX_FS_INFO:
2739 vfs_statvfs_struct svfs;
2741 if (!lp_unix_extensions()) {
2742 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2746 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2750 SIVAL(pdata,0,svfs.OptimalTransferSize);
2751 SIVAL(pdata,4,svfs.BlockSize);
2752 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2753 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2754 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2755 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2756 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2757 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2758 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2760 } else if (rc == EOPNOTSUPP) {
2761 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2763 #endif /* EOPNOTSUPP */
2765 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2766 reply_doserror(req, ERRSRV, ERRerror);
2772 case SMB_QUERY_POSIX_WHOAMI:
2778 if (!lp_unix_extensions()) {
2779 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2783 if (max_data_bytes < 40) {
2784 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2788 /* We ARE guest if global_sid_Builtin_Guests is
2789 * in our list of SIDs.
2791 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2792 current_user.nt_user_token)) {
2793 flags |= SMB_WHOAMI_GUEST;
2796 /* We are NOT guest if global_sid_Authenticated_Users
2797 * is in our list of SIDs.
2799 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2800 current_user.nt_user_token)) {
2801 flags &= ~SMB_WHOAMI_GUEST;
2804 /* NOTE: 8 bytes for UID/GID, irrespective of native
2805 * platform size. This matches
2806 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2808 data_len = 4 /* flags */
2815 + 4 /* pad/reserved */
2816 + (current_user.ut.ngroups * 8)
2818 + (current_user.nt_user_token->num_sids *
2822 SIVAL(pdata, 0, flags);
2823 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2824 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2825 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2828 if (data_len >= max_data_bytes) {
2829 /* Potential overflow, skip the GIDs and SIDs. */
2831 SIVAL(pdata, 24, 0); /* num_groups */
2832 SIVAL(pdata, 28, 0); /* num_sids */
2833 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2834 SIVAL(pdata, 36, 0); /* reserved */
2840 SIVAL(pdata, 24, current_user.ut.ngroups);
2842 current_user.nt_user_token->num_sids);
2844 /* We walk the SID list twice, but this call is fairly
2845 * infrequent, and I don't expect that it's performance
2846 * sensitive -- jpeach
2848 for (i = 0, sid_bytes = 0;
2849 i < current_user.nt_user_token->num_sids; ++i) {
2851 sid_size(¤t_user.nt_user_token->user_sids[i]);
2854 /* SID list byte count */
2855 SIVAL(pdata, 32, sid_bytes);
2857 /* 4 bytes pad/reserved - must be zero */
2858 SIVAL(pdata, 36, 0);
2862 for (i = 0; i < current_user.ut.ngroups; ++i) {
2863 SBIG_UINT(pdata, data_len,
2864 (SMB_BIG_UINT)current_user.ut.groups[i]);
2870 i < current_user.nt_user_token->num_sids; ++i) {
2872 sid_size(¤t_user.nt_user_token->user_sids[i]);
2874 sid_linearize(pdata + data_len, sid_len,
2875 ¤t_user.nt_user_token->user_sids[i]);
2876 data_len += sid_len;
2882 case SMB_MAC_QUERY_FS_INFO:
2884 * Thursby MAC extension... ONLY on NTFS filesystems
2885 * once we do streams then we don't need this
2887 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2889 SIVAL(pdata,84,0x100); /* Don't support mac... */
2894 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2899 send_trans2_replies(req, params, 0, pdata, data_len,
2902 DEBUG( 4, ( "%s info_level = %d\n",
2903 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2908 /****************************************************************************
2909 Reply to a TRANS2_SETFSINFO (set filesystem info).
2910 ****************************************************************************/
2912 static void call_trans2setfsinfo(connection_struct *conn,
2913 struct smb_request *req,
2914 char **pparams, int total_params,
2915 char **ppdata, int total_data,
2916 unsigned int max_data_bytes)
2918 char *pdata = *ppdata;
2919 char *params = *pparams;
2922 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2925 if (total_params < 4) {
2926 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2928 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2932 info_level = SVAL(params,2);
2934 switch(info_level) {
2935 case SMB_SET_CIFS_UNIX_INFO:
2937 uint16 client_unix_major;
2938 uint16 client_unix_minor;
2939 uint32 client_unix_cap_low;
2940 uint32 client_unix_cap_high;
2942 if (!lp_unix_extensions()) {
2944 NT_STATUS_INVALID_LEVEL);
2948 /* There should be 12 bytes of capabilities set. */
2949 if (total_data < 8) {
2952 NT_STATUS_INVALID_PARAMETER);
2955 client_unix_major = SVAL(pdata,0);
2956 client_unix_minor = SVAL(pdata,2);
2957 client_unix_cap_low = IVAL(pdata,4);
2958 client_unix_cap_high = IVAL(pdata,8);
2959 /* Just print these values for now. */
2960 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2961 cap_low = 0x%x, cap_high = 0x%x\n",
2962 (unsigned int)client_unix_major,
2963 (unsigned int)client_unix_minor,
2964 (unsigned int)client_unix_cap_low,
2965 (unsigned int)client_unix_cap_high ));
2967 /* Here is where we must switch to posix pathname processing... */
2968 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2969 lp_set_posix_pathnames();
2970 mangle_change_to_posix();
2973 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2974 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2975 /* Client that knows how to do posix locks,
2976 * but not posix open/mkdir operations. Set a
2977 * default type for read/write checks. */
2979 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2984 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2987 size_t param_len = 0;
2988 size_t data_len = total_data;
2990 if (!lp_unix_extensions()) {
2992 req, NT_STATUS_INVALID_LEVEL);
2996 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2998 status = srv_request_encryption_setup(conn,
2999 (unsigned char **)ppdata,
3001 (unsigned char **)pparams,
3005 if (!NT_STATUS_IS_OK(status)) {
3008 * MORE_PROCESSING_REQUIRED, this used
3009 * to have special handling here.
3011 reply_nterror(req, status);
3015 send_trans2_replies(req,
3016 *pparams, param_len,
3020 if (NT_STATUS_IS_OK(status)) {
3021 /* Server-side transport encryption is now *on*. */
3022 status = srv_encryption_start(conn);
3023 if (!NT_STATUS_IS_OK(status)) {
3024 exit_server_cleanly("Failure in setting up encrypted transport");
3029 case SMB_FS_QUOTA_INFORMATION:
3031 files_struct *fsp = NULL;
3032 SMB_NTQUOTA_STRUCT quotas;
3034 ZERO_STRUCT(quotas);
3037 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3038 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3039 lp_servicename(SNUM(conn)),conn->user));
3040 reply_doserror(req, ERRSRV, ERRaccess);
3044 /* note: normaly there're 48 bytes,
3045 * but we didn't use the last 6 bytes for now
3048 fsp = file_fsp(SVAL(params,0));
3049 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3050 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3052 req, NT_STATUS_INVALID_HANDLE);
3056 if (total_data < 42) {
3057 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3061 NT_STATUS_INVALID_PARAMETER);
3065 /* unknown_1 24 NULL bytes in pdata*/
3067 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3068 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3069 #ifdef LARGE_SMB_OFF_T
3070 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3071 #else /* LARGE_SMB_OFF_T */
3072 if ((IVAL(pdata,28) != 0)&&
3073 ((quotas.softlim != 0xFFFFFFFF)||
3074 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3075 /* more than 32 bits? */
3078 NT_STATUS_INVALID_PARAMETER);
3081 #endif /* LARGE_SMB_OFF_T */
3083 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3084 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3085 #ifdef LARGE_SMB_OFF_T
3086 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3087 #else /* LARGE_SMB_OFF_T */
3088 if ((IVAL(pdata,36) != 0)&&
3089 ((quotas.hardlim != 0xFFFFFFFF)||
3090 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3091 /* more than 32 bits? */
3094 NT_STATUS_INVALID_PARAMETER);
3097 #endif /* LARGE_SMB_OFF_T */
3099 /* quota_flags 2 bytes **/
3100 quotas.qflags = SVAL(pdata,40);
3102 /* unknown_2 6 NULL bytes follow*/
3104 /* now set the quotas */
3105 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3106 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3107 reply_doserror(req, ERRSRV, ERRerror);
3114 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3116 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3122 * sending this reply works fine,
3123 * but I'm not sure it's the same
3124 * like windows do...
3127 reply_outbuf(req, 10, 0);
3130 #if defined(HAVE_POSIX_ACLS)
3131 /****************************************************************************
3132 Utility function to count the number of entries in a POSIX acl.
3133 ****************************************************************************/
3135 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3137 unsigned int ace_count = 0;
3138 int entry_id = SMB_ACL_FIRST_ENTRY;
3139 SMB_ACL_ENTRY_T entry;
3141 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3143 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3144 entry_id = SMB_ACL_NEXT_ENTRY;
3151 /****************************************************************************
3152 Utility function to marshall a POSIX acl into wire format.
3153 ****************************************************************************/
3155 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3157 int entry_id = SMB_ACL_FIRST_ENTRY;
3158 SMB_ACL_ENTRY_T entry;
3160 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3161 SMB_ACL_TAG_T tagtype;
3162 SMB_ACL_PERMSET_T permset;
3163 unsigned char perms = 0;
3164 unsigned int own_grp;
3167 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3168 entry_id = SMB_ACL_NEXT_ENTRY;
3171 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3172 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3176 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3177 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3181 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3182 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3183 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3185 SCVAL(pdata,1,perms);
3188 case SMB_ACL_USER_OBJ:
3189 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3190 own_grp = (unsigned int)pst->st_uid;
3191 SIVAL(pdata,2,own_grp);
3196 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3198 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3201 own_grp = (unsigned int)*puid;
3202 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3203 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3204 SIVAL(pdata,2,own_grp);
3208 case SMB_ACL_GROUP_OBJ:
3209 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3210 own_grp = (unsigned int)pst->st_gid;
3211 SIVAL(pdata,2,own_grp);
3216 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3218 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3221 own_grp = (unsigned int)*pgid;
3222 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3223 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3224 SIVAL(pdata,2,own_grp);
3229 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3230 SIVAL(pdata,2,0xFFFFFFFF);
3231 SIVAL(pdata,6,0xFFFFFFFF);
3234 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3235 SIVAL(pdata,2,0xFFFFFFFF);
3236 SIVAL(pdata,6,0xFFFFFFFF);
3239 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3242 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3249 /****************************************************************************
3250 Store the FILE_UNIX_BASIC info.
3251 ****************************************************************************/
3253 static char *store_file_unix_basic(connection_struct *conn,
3256 const SMB_STRUCT_STAT *psbuf)
3258 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3259 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3261 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3264 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3267 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3268 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3269 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3272 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3276 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3280 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3283 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3287 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3291 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3294 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3298 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3305 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3306 * the chflags(2) (or equivalent) flags.
3308 * XXX: this really should be behind the VFS interface. To do this, we would
3309 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3310 * Each VFS module could then implement it's own mapping as appropriate for the
3311 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3313 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3317 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3321 { UF_IMMUTABLE, EXT_IMMUTABLE },
3325 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3329 { UF_HIDDEN, EXT_HIDDEN },
3332 /* Do not remove. We need to guarantee that this array has at least one
3333 * entry to build on HP-UX.
3339 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3340 uint32 *smb_fflags, uint32 *smb_fmask)
3342 #ifdef HAVE_STAT_ST_FLAGS
3345 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3346 *smb_fmask |= info2_flags_map[i].smb_fflag;
3347 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3348 *smb_fflags |= info2_flags_map[i].smb_fflag;
3351 #endif /* HAVE_STAT_ST_FLAGS */
3354 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3355 const uint32 smb_fflags,
3356 const uint32 smb_fmask,
3359 #ifdef HAVE_STAT_ST_FLAGS
3360 uint32 max_fmask = 0;
3363 *stat_fflags = psbuf->st_flags;
3365 /* For each flags requested in smb_fmask, check the state of the
3366 * corresponding flag in smb_fflags and set or clear the matching
3370 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3371 max_fmask |= info2_flags_map[i].smb_fflag;
3372 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3373 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3374 *stat_fflags |= info2_flags_map[i].stat_fflag;
3376 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3381 /* If smb_fmask is asking to set any bits that are not supported by
3382 * our flag mappings, we should fail.
3384 if ((smb_fmask & max_fmask) != smb_fmask) {
3391 #endif /* HAVE_STAT_ST_FLAGS */
3395 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3396 * of file flags and birth (create) time.
3398 static char *store_file_unix_basic_info2(connection_struct *conn,
3401 const SMB_STRUCT_STAT *psbuf)
3403 uint32 file_flags = 0;
3404 uint32 flags_mask = 0;
3406 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3408 /* Create (birth) time 64 bit */
3409 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3412 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3413 SIVAL(pdata, 0, file_flags); /* flags */
3414 SIVAL(pdata, 4, flags_mask); /* mask */
3420 /****************************************************************************
3421 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3422 ****************************************************************************/
3424 static void call_trans2qpipeinfo(connection_struct *conn,
3425 struct smb_request *req,
3426 unsigned int tran_call,
3427 char **pparams, int total_params,
3428 char **ppdata, int total_data,
3429 unsigned int max_data_bytes)
3431 char *params = *pparams;
3432 char *pdata = *ppdata;
3433 unsigned int data_size = 0;
3434 unsigned int param_size = 2;
3436 smb_np_struct *p_pipe = NULL;
3439 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3443 if (total_params < 4) {
3444 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3448 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3449 if (p_pipe == NULL) {
3450 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3454 info_level = SVAL(params,2);
3456 *pparams = (char *)SMB_REALLOC(*pparams,2);
3457 if (*pparams == NULL) {
3458 reply_nterror(req, NT_STATUS_NO_MEMORY);
3463 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3464 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3465 if (*ppdata == NULL ) {
3466 reply_nterror(req, NT_STATUS_NO_MEMORY);
3471 switch (info_level) {
3472 case SMB_FILE_STANDARD_INFORMATION:
3474 SOFF_T(pdata,0,4096LL);
3481 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3485 send_trans2_replies(req, params, param_size, *ppdata, data_size,
3491 /****************************************************************************
3492 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3493 file name or file id).
3494 ****************************************************************************/
3496 static void call_trans2qfilepathinfo(connection_struct *conn,
3497 struct smb_request *req,
3498 unsigned int tran_call,
3499 char **pparams, int total_params,
3500 char **ppdata, int total_data,
3501 unsigned int max_data_bytes)
3503 char *params = *pparams;
3504 char *pdata = *ppdata;
3505 char *dstart, *dend;
3509 SMB_OFF_T file_size=0;
3510 SMB_BIG_UINT allocation_size=0;
3511 unsigned int data_size = 0;
3512 unsigned int param_size = 2;
3513 SMB_STRUCT_STAT sbuf;
3520 BOOL delete_pending = False;
3522 time_t create_time, mtime, atime;
3523 struct timespec create_time_ts, mtime_ts, atime_ts;
3524 files_struct *fsp = NULL;
3525 struct file_id fileid;
3526 TALLOC_CTX *data_ctx = NULL;
3527 struct ea_list *ea_list = NULL;
3528 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3529 char *lock_data = NULL;
3530 TALLOC_CTX *ctx = talloc_tos();
3533 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3539 if (tran_call == TRANSACT2_QFILEINFO) {
3540 if (total_params < 4) {
3541 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3546 call_trans2qpipeinfo(conn, req, tran_call,
3547 pparams, total_params,
3553 fsp = file_fsp(SVAL(params,0));
3554 info_level = SVAL(params,2);
3556 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3558 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3559 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3563 /* Initial check for valid fsp ptr. */
3564 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
3568 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3570 reply_nterror(req, NT_STATUS_NO_MEMORY);
3574 if(fsp->fake_file_handle) {
3576 * This is actually for the QUOTA_FAKE_FILE --metze
3579 /* We know this name is ok, it's already passed the checks. */
3581 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3583 * This is actually a QFILEINFO on a directory
3584 * handle (returned from an NT SMB). NT5.0 seems
3585 * to do this call. JRA.
3588 if (INFO_LEVEL_IS_UNIX(info_level)) {
3589 /* Always do lstat for UNIX calls. */
3590 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3591 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3592 reply_unixerror(req,ERRDOS,ERRbadpath);
3595 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3596 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3597 reply_unixerror(req, ERRDOS, ERRbadpath);
3601 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3602 delete_pending = get_delete_on_close_flag(fileid);
3605 * Original code - this is an open file.
3607 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3611 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3612 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3613 reply_unixerror(req, ERRDOS, ERRbadfid);
3616 pos = fsp->fh->position_information;
3617 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3618 delete_pending = get_delete_on_close_flag(fileid);
3619 access_mask = fsp->access_mask;
3623 NTSTATUS status = NT_STATUS_OK;
3626 if (total_params < 7) {
3627 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3631 info_level = SVAL(params,0);
3633 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3635 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3636 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3640 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3642 STR_TERMINATE, &status);
3643 if (!NT_STATUS_IS_OK(status)) {
3644 reply_nterror(req, status);
3648 status = resolve_dfspath(ctx,
3650 req->flags2 & FLAGS2_DFS_PATHNAMES,
3653 if (!NT_STATUS_IS_OK(status)) {
3654 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3655 reply_botherror(req,
3656 NT_STATUS_PATH_NOT_COVERED,
3657 ERRSRV, ERRbadpath);
3659 reply_nterror(req, status);
3663 status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);
3664 if (!NT_STATUS_IS_OK(status)) {
3665 reply_nterror(req, status);
3668 status = check_name(conn, fname);
3669 if (!NT_STATUS_IS_OK(status)) {
3670 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3671 reply_nterror(req, status);
3675 if (INFO_LEVEL_IS_UNIX(info_level)) {
3676 /* Always do lstat for UNIX calls. */
3677 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3678 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3679 reply_unixerror(req, ERRDOS, ERRbadpath);
3682 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3683 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3684 reply_unixerror(req, ERRDOS, ERRbadpath);
3688 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3689 delete_pending = get_delete_on_close_flag(fileid);
3690 if (delete_pending) {
3691 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3696 nlink = sbuf.st_nlink;
3698 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3699 /* NTFS does not seem to count ".." */
3703 if ((nlink > 0) && delete_pending) {
3707 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3708 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3712 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3713 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3715 p = strrchr_m(fname,'/');
3721 mode = dos_mode(conn,fname,&sbuf);
3723 mode = FILE_ATTRIBUTE_NORMAL;
3725 fullpathname = fname;
3727 file_size = get_file_size(sbuf);
3729 /* Pull out any data sent here before we realloc. */
3730 switch (info_level) {
3731 case SMB_INFO_QUERY_EAS_FROM_LIST:
3733 /* Pull any EA list from the data portion. */
3736 if (total_data < 4) {
3738 req, NT_STATUS_INVALID_PARAMETER);
3741 ea_size = IVAL(pdata,0);
3743 if (total_data > 0 && ea_size != total_data) {
3744 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3745 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3747 req, NT_STATUS_INVALID_PARAMETER);
3751 if (!lp_ea_support(SNUM(conn))) {
3752 reply_doserror(req, ERRDOS,
3753 ERReasnotsupported);
3757 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3758 reply_nterror(req, NT_STATUS_NO_MEMORY);
3762 /* Pull out the list of names. */
3763 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3765 talloc_destroy(data_ctx);
3767 req, NT_STATUS_INVALID_PARAMETER);
3773 case SMB_QUERY_POSIX_LOCK:
3775 if (fsp == NULL || fsp->fh->fd == -1) {
3776 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3780 if (total_data != POSIX_LOCK_DATA_SIZE) {
3782 req, NT_STATUS_INVALID_PARAMETER);
3786 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3787 reply_nterror(req, NT_STATUS_NO_MEMORY);
3791 /* Copy the lock range data. */
3792 lock_data = (char *)TALLOC_MEMDUP(
3793 data_ctx, pdata, total_data);
3795 talloc_destroy(data_ctx);
3796 reply_nterror(req, NT_STATUS_NO_MEMORY);
3804 *pparams = (char *)SMB_REALLOC(*pparams,2);
3805 if (*pparams == NULL) {
3806 talloc_destroy(data_ctx);
3807 reply_nterror(req, NT_STATUS_NO_MEMORY);
3812 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3813 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3814 if (*ppdata == NULL ) {
3815 talloc_destroy(data_ctx);
3816 reply_nterror(req, NT_STATUS_NO_MEMORY);
3821 dend = dstart + data_size - 1;
3823 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3824 mtime_ts = get_mtimespec(&sbuf);
3825 atime_ts = get_atimespec(&sbuf);
3827 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3830 if (!null_timespec(fsp->pending_modtime)) {
3831 /* the pending modtime overrides the current modtime */
3832 mtime_ts = fsp->pending_modtime;
3836 /* Do we have this path open ? */
3837 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3838 fsp1 = file_find_di_first(fileid);
3839 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3840 /* the pending modtime overrides the current modtime */
3841 mtime_ts = fsp1->pending_modtime;
3843 if (fsp1 && fsp1->initial_allocation_size) {
3844 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3848 if (lp_dos_filetime_resolution(SNUM(conn))) {
3849 dos_filetime_timespec(&create_time_ts);
3850 dos_filetime_timespec(&mtime_ts);
3851 dos_filetime_timespec(&atime_ts);
3854 create_time = convert_timespec_to_time_t(create_time_ts);
3855 mtime = convert_timespec_to_time_t(mtime_ts);
3856 atime = convert_timespec_to_time_t(atime_ts);
3858 /* NT expects the name to be in an exact form of the *full*
3859 filename. See the trans2 torture test */
3860 if (strequal(base_name,".")) {
3861 pstrcpy(dos_fname, "\\");
3863 pstr_sprintf(dos_fname, "\\%s", fname);
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(data_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)) {
3916 talloc_destroy(data_ctx);
3918 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3922 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3923 talloc_destroy(data_ctx);
3927 case SMB_INFO_QUERY_ALL_EAS:
3929 /* We have data_size bytes to put EA's into. */
3930 size_t total_ea_len = 0;
3932 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3934 data_ctx = talloc_init("ea_ctx");
3936 reply_nterror(req, NT_STATUS_NO_MEMORY);
3940 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3941 if (!ea_list || (total_ea_len > data_size)) {
3942 talloc_destroy(data_ctx);
3944 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3948 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3949 talloc_destroy(data_ctx);
3953 case SMB_FILE_BASIC_INFORMATION:
3954 case SMB_QUERY_FILE_BASIC_INFO:
3956 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3957 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3958 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3960 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3964 put_long_date_timespec(pdata,create_time_ts);
3965 put_long_date_timespec(pdata+8,atime_ts);
3966 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3967 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3968 SIVAL(pdata,32,mode);
3970 DEBUG(5,("SMB_QFBI - "));
3971 DEBUG(5,("create: %s ", ctime(&create_time)));
3972 DEBUG(5,("access: %s ", ctime(&atime)));
3973 DEBUG(5,("write: %s ", ctime(&mtime)));
3974 DEBUG(5,("change: %s ", ctime(&mtime)));
3975 DEBUG(5,("mode: %x\n", mode));
3978 case SMB_FILE_STANDARD_INFORMATION:
3979 case SMB_QUERY_FILE_STANDARD_INFO:
3981 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3983 SOFF_T(pdata,0,allocation_size);
3984 SOFF_T(pdata,8,file_size);
3985 SIVAL(pdata,16,nlink);
3986 SCVAL(pdata,20,delete_pending?1:0);
3987 SCVAL(pdata,21,(mode&aDIR)?1:0);
3988 SSVAL(pdata,22,0); /* Padding. */
3991 case SMB_FILE_EA_INFORMATION:
3992 case SMB_QUERY_FILE_EA_INFO:
3994 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3995 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3997 SIVAL(pdata,0,ea_size);
4001 /* Get the 8.3 name - used if NT SMB was negotiated. */
4002 case SMB_QUERY_FILE_ALT_NAME_INFO:
4003 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4005 char mangled_name[13];
4006 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4007 if (!name_to_8_3(base_name,mangled_name,
4008 True,conn->params)) {
4011 NT_STATUS_NO_MEMORY);
4013 len = srvstr_push(dstart, req->flags2,
4014 pdata+4, mangled_name,
4015 PTR_DIFF(dend, pdata+4),
4017 data_size = 4 + len;
4022 case SMB_QUERY_FILE_NAME_INFO:
4024 this must be *exactly* right for ACLs on mapped drives to work
4026 len = srvstr_push(dstart, req->flags2,
4028 PTR_DIFF(dend, pdata+4),
4030 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4031 data_size = 4 + len;
4035 case SMB_FILE_ALLOCATION_INFORMATION:
4036 case SMB_QUERY_FILE_ALLOCATION_INFO:
4037 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4039 SOFF_T(pdata,0,allocation_size);
4042 case SMB_FILE_END_OF_FILE_INFORMATION:
4043 case SMB_QUERY_FILE_END_OF_FILEINFO:
4044 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4046 SOFF_T(pdata,0,file_size);
4049 case SMB_QUERY_FILE_ALL_INFO:
4050 case SMB_FILE_ALL_INFORMATION:
4052 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4053 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4054 put_long_date_timespec(pdata,create_time_ts);
4055 put_long_date_timespec(pdata+8,atime_ts);
4056 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4057 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4058 SIVAL(pdata,32,mode);
4059 SIVAL(pdata,36,0); /* padding. */
4061 SOFF_T(pdata,0,allocation_size);
4062 SOFF_T(pdata,8,file_size);
4063 SIVAL(pdata,16,nlink);
4064 SCVAL(pdata,20,delete_pending);
4065 SCVAL(pdata,21,(mode&aDIR)?1:0);
4068 SIVAL(pdata,0,ea_size);
4069 pdata += 4; /* EA info */
4070 len = srvstr_push(dstart, req->flags2,
4072 PTR_DIFF(dend, pdata+4),
4076 data_size = PTR_DIFF(pdata,(*ppdata));
4079 case SMB_FILE_INTERNAL_INFORMATION:
4080 /* This should be an index number - looks like
4083 I think this causes us to fail the IFSKIT
4084 BasicFileInformationTest. -tpot */
4086 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4087 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4088 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4092 case SMB_FILE_ACCESS_INFORMATION:
4093 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4094 SIVAL(pdata,0,access_mask);
4098 case SMB_FILE_NAME_INFORMATION:
4099 /* Pathname with leading '\'. */
4102 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4103 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4104 SIVAL(pdata,0,byte_len);
4105 data_size = 4 + byte_len;
4109 case SMB_FILE_DISPOSITION_INFORMATION:
4110 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4112 SCVAL(pdata,0,delete_pending);
4115 case SMB_FILE_POSITION_INFORMATION:
4116 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4118 SOFF_T(pdata,0,pos);
4121 case SMB_FILE_MODE_INFORMATION:
4122 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4123 SIVAL(pdata,0,mode);
4127 case SMB_FILE_ALIGNMENT_INFORMATION:
4128 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4129 SIVAL(pdata,0,0); /* No alignment needed. */
4135 * NT4 server just returns "invalid query" to this - if we try to answer
4136 * it then NTws gets a BSOD! (tridge).
4137 * W2K seems to want this. JRA.
4139 case SMB_QUERY_FILE_STREAM_INFO:
4141 case SMB_FILE_STREAM_INFORMATION:
4142 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4146 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4147 SIVAL(pdata,0,0); /* ??? */
4148 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4149 SOFF_T(pdata,8,file_size);
4150 SOFF_T(pdata,16,allocation_size);
4151 data_size = 24 + byte_len;
4155 case SMB_QUERY_COMPRESSION_INFO:
4156 case SMB_FILE_COMPRESSION_INFORMATION:
4157 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4158 SOFF_T(pdata,0,file_size);
4159 SIVAL(pdata,8,0); /* ??? */
4160 SIVAL(pdata,12,0); /* ??? */
4164 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4165 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4166 put_long_date_timespec(pdata,create_time_ts);
4167 put_long_date_timespec(pdata+8,atime_ts);
4168 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4169 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4170 SOFF_T(pdata,32,allocation_size);
4171 SOFF_T(pdata,40,file_size);
4172 SIVAL(pdata,48,mode);
4173 SIVAL(pdata,52,0); /* ??? */
4177 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4178 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4179 SIVAL(pdata,0,mode);
4185 * CIFS UNIX Extensions.
4188 case SMB_QUERY_FILE_UNIX_BASIC:
4190 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4191 data_size = PTR_DIFF(pdata,(*ppdata));
4195 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4197 for (i=0; i<100; i++)
4198 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4204 case SMB_QUERY_FILE_UNIX_INFO2:
4206 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4207 data_size = PTR_DIFF(pdata,(*ppdata));
4211 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4213 for (i=0; i<100; i++)
4214 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4220 case SMB_QUERY_FILE_UNIX_LINK:
4224 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4226 if(!S_ISLNK(sbuf.st_mode)) {
4227 reply_unixerror(req, ERRSRV,
4232 reply_unixerror(req, ERRDOS, ERRbadlink);
4235 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
4237 reply_unixerror(req, ERRDOS,
4242 len = srvstr_push(dstart, req->flags2,
4244 PTR_DIFF(dend, pdata),
4247 data_size = PTR_DIFF(pdata,(*ppdata));
4252 #if defined(HAVE_POSIX_ACLS)
4253 case SMB_QUERY_POSIX_ACL:
4255 SMB_ACL_T file_acl = NULL;
4256 SMB_ACL_T def_acl = NULL;
4257 uint16 num_file_acls = 0;
4258 uint16 num_def_acls = 0;
4260 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4261 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4263 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4266 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4267 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4271 NT_STATUS_NOT_IMPLEMENTED);
4275 if (S_ISDIR(sbuf.st_mode)) {
4276 if (fsp && fsp->is_directory) {
4277 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4279 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4281 def_acl = free_empty_sys_acl(conn, def_acl);
4284 num_file_acls = count_acl_entries(conn, file_acl);
4285 num_def_acls = count_acl_entries(conn, def_acl);
4287 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4288 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4290 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4291 SMB_POSIX_ACL_HEADER_SIZE) ));
4293 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4296 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4300 NT_STATUS_BUFFER_TOO_SMALL);
4304 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4305 SSVAL(pdata,2,num_file_acls);
4306 SSVAL(pdata,4,num_def_acls);
4307 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4309 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4312 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4315 req, NT_STATUS_INTERNAL_ERROR);
4318 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4320 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4323 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4327 NT_STATUS_INTERNAL_ERROR);
4332 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4335 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4337 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4343 case SMB_QUERY_POSIX_LOCK:
4345 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4347 SMB_BIG_UINT offset;
4349 enum brl_type lock_type;
4351 if (total_data != POSIX_LOCK_DATA_SIZE) {
4353 req, NT_STATUS_INVALID_PARAMETER);
4357 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4358 case POSIX_LOCK_TYPE_READ:
4359 lock_type = READ_LOCK;
4361 case POSIX_LOCK_TYPE_WRITE:
4362 lock_type = WRITE_LOCK;
4364 case POSIX_LOCK_TYPE_UNLOCK:
4366 /* There's no point in asking for an unlock... */
4367 talloc_destroy(data_ctx);
4370 NT_STATUS_INVALID_PARAMETER);
4374 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4375 #if defined(HAVE_LONGLONG)
4376 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4377 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4378 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4379 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4380 #else /* HAVE_LONGLONG */
4381 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4382 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4383 #endif /* HAVE_LONGLONG */
4385 status = query_lock(fsp,
4392 if (ERROR_WAS_LOCK_DENIED(status)) {
4393 /* Here we need to report who has it locked... */
4394 data_size = POSIX_LOCK_DATA_SIZE;
4396 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4397 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4398 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4399 #if defined(HAVE_LONGLONG)
4400 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4401 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4402 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4403 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4404 #else /* HAVE_LONGLONG */
4405 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4406 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4407 #endif /* HAVE_LONGLONG */
4409 } else if (NT_STATUS_IS_OK(status)) {
4410 /* For success we just return a copy of what we sent
4411 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4412 data_size = POSIX_LOCK_DATA_SIZE;
4413 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4414 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4416 reply_nterror(req, status);
4423 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4427 send_trans2_replies(req, params, param_size, *ppdata, data_size,
4433 /****************************************************************************
4434 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4436 ****************************************************************************/
4438 NTSTATUS hardlink_internals(connection_struct *conn,
4439 const char *oldname_in,
4440 const char *newname_in)
4442 SMB_STRUCT_STAT sbuf1, sbuf2;
4443 char *last_component_oldname = NULL;
4444 char *last_component_newname = NULL;
4445 char *oldname = NULL;
4446 char *newname = NULL;
4447 NTSTATUS status = NT_STATUS_OK;
4452 status = unix_convert(conn, oldname_in, False, &oldname,
4453 &last_component_oldname, &sbuf1);
4454 if (!NT_STATUS_IS_OK(status)) {
4458 status = check_name(conn, oldname);
4459 if (!NT_STATUS_IS_OK(status)) {
4463 /* source must already exist. */
4464 if (!VALID_STAT(sbuf1)) {
4465 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4468 status = unix_convert(conn, newname_in, False, &newname,
4469 &last_component_newname, &sbuf2);
4470 if (!NT_STATUS_IS_OK(status)) {
4474 status = check_name(conn, newname);
4475 if (!NT_STATUS_IS_OK(status)) {
4479 /* Disallow if newname already exists. */
4480 if (VALID_STAT(sbuf2)) {
4481 return NT_STATUS_OBJECT_NAME_COLLISION;
4484 /* No links from a directory. */
4485 if (S_ISDIR(sbuf1.st_mode)) {
4486 return NT_STATUS_FILE_IS_A_DIRECTORY;
4489 /* Ensure this is within the share. */
4490 status = check_reduced_name(conn, oldname);
4491 if (!NT_STATUS_IS_OK(status)) {
4495 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4497 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4498 status = map_nt_error_from_unix(errno);
4499 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4500 nt_errstr(status), newname, oldname));
4506 /****************************************************************************
4507 Deal with setting the time from any of the setfilepathinfo functions.
4508 ****************************************************************************/
4510 static NTSTATUS smb_set_file_time(connection_struct *conn,
4513 const SMB_STRUCT_STAT *psbuf,
4514 struct timespec ts[2])
4517 FILE_NOTIFY_CHANGE_LAST_ACCESS
4518 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4521 if (!VALID_STAT(*psbuf)) {
4522 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4525 /* get some defaults (no modifications) if any info is zero or -1. */
4526 if (null_timespec(ts[0])) {
4527 ts[0] = get_atimespec(psbuf);
4528 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4531 if (null_timespec(ts[1])) {
4532 ts[1] = get_mtimespec(psbuf);
4533 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4536 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4537 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4540 * Try and set the times of this file if
4541 * they are different from the current values.
4545 struct timespec mts = get_mtimespec(psbuf);
4546 struct timespec ats = get_atimespec(psbuf);
4547 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4548 return NT_STATUS_OK;
4554 * This was a setfileinfo on an open file.
4555 * NT does this a lot. We also need to
4556 * set the time here, as it can be read by
4557 * FindFirst/FindNext and with the patch for bug #2045
4558 * in smbd/fileio.c it ensures that this timestamp is
4559 * kept sticky even after a write. We save the request
4560 * away and will set it on file close and after a write. JRA.
4563 if (!null_timespec(ts[1])) {
4564 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4565 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4566 fsp_set_pending_modtime(fsp, ts[1]);
4570 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4572 if(file_ntimes(conn, fname, ts)!=0) {
4573 return map_nt_error_from_unix(errno);
4576 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4578 return NT_STATUS_OK;
4581 /****************************************************************************
4582 Deal with setting the dosmode from any of the setfilepathinfo functions.
4583 ****************************************************************************/
4585 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4587 SMB_STRUCT_STAT *psbuf,
4590 if (!VALID_STAT(*psbuf)) {
4591 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4595 if (S_ISDIR(psbuf->st_mode)) {
4602 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4604 /* check the mode isn't different, before changing it */
4605 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4607 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4608 fname, (unsigned int)dosmode ));
4610 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4611 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4612 fname, strerror(errno)));
4613 return map_nt_error_from_unix(errno);
4616 return NT_STATUS_OK;
4619 /****************************************************************************
4620 Deal with setting the size from any of the setfilepathinfo functions.
4621 ****************************************************************************/
4623 static NTSTATUS smb_set_file_size(connection_struct *conn,
4624 struct smb_request *req,
4627 SMB_STRUCT_STAT *psbuf,
4630 NTSTATUS status = NT_STATUS_OK;
4631 files_struct *new_fsp = NULL;
4633 if (!VALID_STAT(*psbuf)) {
4634 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4637 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4639 if (size == get_file_size(*psbuf)) {
4640 return NT_STATUS_OK;
4643 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4644 fname, (double)size ));
4646 if (fsp && fsp->fh->fd != -1) {
4647 /* Handle based call. */
4648 if (vfs_set_filelen(fsp, size) == -1) {
4649 return map_nt_error_from_unix(errno);
4651 return NT_STATUS_OK;
4654 status = open_file_ntcreate(conn, req, fname, psbuf,
4656 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4659 FILE_ATTRIBUTE_NORMAL,
4660 FORCE_OPLOCK_BREAK_TO_NONE,
4663 if (!NT_STATUS_IS_OK(status)) {
4664 /* NB. We check for open_was_deferred in the caller. */
4668 if (vfs_set_filelen(new_fsp, size) == -1) {
4669 status = map_nt_error_from_unix(errno);
4670 close_file(new_fsp,NORMAL_CLOSE);
4674 close_file(new_fsp,NORMAL_CLOSE);
4675 return NT_STATUS_OK;
4678 /****************************************************************************
4679 Deal with SMB_INFO_SET_EA.
4680 ****************************************************************************/
4682 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4688 struct ea_list *ea_list = NULL;
4689 TALLOC_CTX *ctx = NULL;
4690 NTSTATUS status = NT_STATUS_OK;
4692 if (total_data < 10) {
4694 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4695 length. They seem to have no effect. Bug #3212. JRA */
4697 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4698 /* We're done. We only get EA info in this call. */
4699 return NT_STATUS_OK;
4702 return NT_STATUS_INVALID_PARAMETER;
4705 if (IVAL(pdata,0) > total_data) {
4706 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4707 IVAL(pdata,0), (unsigned int)total_data));
4708 return NT_STATUS_INVALID_PARAMETER;
4711 ctx = talloc_init("SMB_INFO_SET_EA");
4713 return NT_STATUS_NO_MEMORY;
4715 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4717 talloc_destroy(ctx);
4718 return NT_STATUS_INVALID_PARAMETER;
4720 status = set_ea(conn, fsp, fname, ea_list);
4721 talloc_destroy(ctx);
4726 /****************************************************************************
4727 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4728 ****************************************************************************/
4730 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4735 SMB_STRUCT_STAT *psbuf)
4737 NTSTATUS status = NT_STATUS_OK;
4738 BOOL delete_on_close;
4741 if (total_data < 1) {
4742 return NT_STATUS_INVALID_PARAMETER;
4746 return NT_STATUS_INVALID_HANDLE;
4749 delete_on_close = (CVAL(pdata,0) ? True : False);
4750 dosmode = dos_mode(conn, fname, psbuf);
4752 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4753 "delete_on_close = %u\n",
4755 (unsigned int)dosmode,
4756 (unsigned int)delete_on_close ));
4758 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4760 if (!NT_STATUS_IS_OK(status)) {
4764 /* The set is across all open files on this dev/inode pair. */
4765 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4766 return NT_STATUS_ACCESS_DENIED;
4768 return NT_STATUS_OK;
4771 /****************************************************************************
4772 Deal with SMB_FILE_POSITION_INFORMATION.
4773 ****************************************************************************/
4775 static NTSTATUS smb_file_position_information(connection_struct *conn,
4780 SMB_BIG_UINT position_information;
4782 if (total_data < 8) {
4783 return NT_STATUS_INVALID_PARAMETER;
4787 /* Ignore on pathname based set. */
4788 return NT_STATUS_OK;
4791 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4792 #ifdef LARGE_SMB_OFF_T
4793 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4794 #else /* LARGE_SMB_OFF_T */
4795 if (IVAL(pdata,4) != 0) {
4796 /* more than 32 bits? */
4797 return NT_STATUS_INVALID_PARAMETER;
4799 #endif /* LARGE_SMB_OFF_T */
4801 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4802 fsp->fsp_name, (double)position_information ));
4803 fsp->fh->position_information = position_information;
4804 return NT_STATUS_OK;
4807 /****************************************************************************
4808 Deal with SMB_FILE_MODE_INFORMATION.
4809 ****************************************************************************/
4811 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4817 if (total_data < 4) {
4818 return NT_STATUS_INVALID_PARAMETER;
4820 mode = IVAL(pdata,0);
4821 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4822 return NT_STATUS_INVALID_PARAMETER;
4824 return NT_STATUS_OK;
4827 /****************************************************************************
4828 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4829 ****************************************************************************/
4831 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4832 struct smb_request *req,
4837 char *link_target = NULL;
4838 const char *newname = fname;
4839 NTSTATUS status = NT_STATUS_OK;
4840 TALLOC_CTX *ctx = talloc_tos();
4842 /* Set a symbolic link. */
4843 /* Don't allow this if follow links is false. */
4845 if (total_data == 0) {
4846 return NT_STATUS_INVALID_PARAMETER;
4849 if (!lp_symlinks(SNUM(conn))) {
4850 return NT_STATUS_ACCESS_DENIED;
4853 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
4854 total_data, STR_TERMINATE);
4857 return NT_STATUS_INVALID_PARAMETER;
4860 /* !widelinks forces the target path to be within the share. */
4861 /* This means we can interpret the target as a pathname. */
4862 if (!lp_widelinks(SNUM(conn))) {
4864 char *last_dirp = NULL;
4866 if (*link_target == '/') {
4867 /* No absolute paths allowed. */
4868 return NT_STATUS_ACCESS_DENIED;
4870 pstrcpy(rel_name, newname);
4871 last_dirp = strrchr_m(rel_name, '/');
4873 last_dirp[1] = '\0';
4875 pstrcpy(rel_name, "./");
4877 pstrcat(rel_name, link_target);
4879 status = check_name(conn, rel_name);
4880 if (!NT_STATUS_IS_OK(status)) {
4885 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4886 newname, link_target ));
4888 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4889 return map_nt_error_from_unix(errno);
4892 return NT_STATUS_OK;
4895 /****************************************************************************
4896 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4897 ****************************************************************************/
4899 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4900 struct smb_request *req,
4901 const char *pdata, int total_data,
4904 char *oldname = NULL;
4905 TALLOC_CTX *ctx = talloc_tos();
4906 NTSTATUS status = NT_STATUS_OK;
4908 /* Set a hard link. */
4909 if (total_data == 0) {
4910 return NT_STATUS_INVALID_PARAMETER;
4913 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
4914 total_data, STR_TERMINATE, &status);
4915 if (!NT_STATUS_IS_OK(status)) {
4919 status = resolve_dfspath(ctx, conn,
4920 req->flags2 & FLAGS2_DFS_PATHNAMES,
4923 if (!NT_STATUS_IS_OK(status)) {
4927 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4930 return hardlink_internals(conn, oldname, fname);
4933 /****************************************************************************
4934 Deal with SMB_FILE_RENAME_INFORMATION.
4935 ****************************************************************************/
4937 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4938 struct smb_request *req,
4947 char *newname = NULL;
4949 BOOL dest_has_wcard = False;
4950 NTSTATUS status = NT_STATUS_OK;
4952 TALLOC_CTX *ctx = talloc_tos();
4954 if (total_data < 13) {
4955 return NT_STATUS_INVALID_PARAMETER;
4958 overwrite = (CVAL(pdata,0) ? True : False);
4959 root_fid = IVAL(pdata,4);
4960 len = IVAL(pdata,8);
4962 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4963 return NT_STATUS_INVALID_PARAMETER;
4966 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
4969 if (!NT_STATUS_IS_OK(status)) {
4973 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4976 status = resolve_dfspath_wcard(ctx, conn,
4977 req->flags2 & FLAGS2_DFS_PATHNAMES,
4981 if (!NT_STATUS_IS_OK(status)) {
4985 /* Check the new name has no '/' characters. */
4986 if (strchr_m(newname, '/')) {
4987 return NT_STATUS_NOT_SUPPORTED;
4990 /* Create the base directory. */
4991 pstrcpy(base_name, fname);
4992 p = strrchr_m(base_name, '/');
4996 pstrcpy(base_name, "./");
4998 /* Append the new name. */
4999 pstrcat(base_name, newname);
5002 SMB_STRUCT_STAT sbuf;
5003 char *newname_last_component = NULL;
5007 status = unix_convert(conn, newname, False,
5009 &newname_last_component,
5012 /* If an error we expect this to be
5013 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5015 if (!NT_STATUS_IS_OK(status)
5016 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5021 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5022 fsp->fnum, fsp->fsp_name, base_name ));
5023 status = rename_internals_fsp(conn, fsp, base_name,
5024 newname_last_component, 0,
5027 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5028 fname, base_name ));
5029 status = rename_internals(conn, req, fname, base_name, 0,
5030 overwrite, False, dest_has_wcard);
5036 /****************************************************************************
5037 Deal with SMB_SET_POSIX_ACL.
5038 ****************************************************************************/
5040 #if defined(HAVE_POSIX_ACLS)
5041 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5046 SMB_STRUCT_STAT *psbuf)
5048 uint16 posix_acl_version;
5049 uint16 num_file_acls;
5050 uint16 num_def_acls;
5051 BOOL valid_file_acls = True;
5052 BOOL valid_def_acls = True;
5054 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5055 return NT_STATUS_INVALID_PARAMETER;
5057 posix_acl_version = SVAL(pdata,0);
5058 num_file_acls = SVAL(pdata,2);
5059 num_def_acls = SVAL(pdata,4);
5061 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5062 valid_file_acls = False;
5066 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5067 valid_def_acls = False;
5071 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5072 return NT_STATUS_INVALID_PARAMETER;
5075 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5076 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5077 return NT_STATUS_INVALID_PARAMETER;
5080 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5081 fname ? fname : fsp->fsp_name,
5082 (unsigned int)num_file_acls,
5083 (unsigned int)num_def_acls));
5085 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5086 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5087 return map_nt_error_from_unix(errno);
5090 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5091 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5092 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5093 return map_nt_error_from_unix(errno);
5095 return NT_STATUS_OK;
5099 /****************************************************************************
5100 Deal with SMB_SET_POSIX_LOCK.
5101 ****************************************************************************/
5103 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5111 SMB_BIG_UINT offset;
5113 BOOL blocking_lock = False;
5114 enum brl_type lock_type;
5115 NTSTATUS status = NT_STATUS_OK;
5117 if (fsp == NULL || fsp->fh->fd == -1) {
5118 return NT_STATUS_INVALID_HANDLE;
5121 if (total_data != POSIX_LOCK_DATA_SIZE) {
5122 return NT_STATUS_INVALID_PARAMETER;
5125 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5126 case POSIX_LOCK_TYPE_READ:
5127 lock_type = READ_LOCK;
5129 case POSIX_LOCK_TYPE_WRITE:
5130 /* Return the right POSIX-mappable error code for files opened read-only. */
5131 if (!fsp->can_write) {
5132 return NT_STATUS_INVALID_HANDLE;
5134 lock_type = WRITE_LOCK;
5136 case POSIX_LOCK_TYPE_UNLOCK:
5137 lock_type = UNLOCK_LOCK;
5140 return NT_STATUS_INVALID_PARAMETER;
5143 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5144 blocking_lock = False;
5145 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5146 blocking_lock = True;
5148 return NT_STATUS_INVALID_PARAMETER;
5151 if (!lp_blocking_locks(SNUM(conn))) {
5152 blocking_lock = False;
5155 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5156 #if defined(HAVE_LONGLONG)
5157 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5158 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5159 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5160 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5161 #else /* HAVE_LONGLONG */
5162 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5163 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5164 #endif /* HAVE_LONGLONG */
5166 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5167 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5169 (unsigned int)lock_type,
5170 (unsigned int)lock_pid,
5174 if (lock_type == UNLOCK_LOCK) {
5175 status = do_unlock(smbd_messaging_context(),
5182 uint32 block_smbpid;
5184 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5195 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5197 * A blocking lock was requested. Package up
5198 * this smb into a queued request and push it
5199 * onto the blocking lock queue.
5201 if(push_blocking_lock_request(br_lck,
5202 (char *)inbuf, length,
5204 -1, /* infinite timeout. */
5212 TALLOC_FREE(br_lck);
5216 TALLOC_FREE(br_lck);
5222 /****************************************************************************
5223 Deal with SMB_INFO_STANDARD.
5224 ****************************************************************************/
5226 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5231 const SMB_STRUCT_STAT *psbuf)
5233 struct timespec ts[2];
5235 if (total_data < 12) {
5236 return NT_STATUS_INVALID_PARAMETER;
5240 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5242 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5244 DEBUG(10,("smb_set_info_standard: file %s\n",
5245 fname ? fname : fsp->fsp_name ));
5247 return smb_set_file_time(conn,
5254 /****************************************************************************
5255 Deal with SMB_SET_FILE_BASIC_INFO.
5256 ****************************************************************************/
5258 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5263 SMB_STRUCT_STAT *psbuf)
5265 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5266 struct timespec write_time;
5267 struct timespec changed_time;
5269 struct timespec ts[2];
5270 NTSTATUS status = NT_STATUS_OK;
5272 if (total_data < 36) {
5273 return NT_STATUS_INVALID_PARAMETER;
5276 /* Set the attributes */
5277 dosmode = IVAL(pdata,32);
5278 status = smb_set_file_dosmode(conn,
5282 if (!NT_STATUS_IS_OK(status)) {
5286 /* Ignore create time at offset pdata. */
5289 ts[0] = interpret_long_date(pdata+8);
5291 write_time = interpret_long_date(pdata+16);
5292 changed_time = interpret_long_date(pdata+24);
5295 ts[1] = timespec_min(&write_time, &changed_time);
5297 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5301 /* Prefer a defined time to an undefined one. */
5302 if (null_timespec(ts[1])) {
5303 ts[1] = null_timespec(write_time) ? changed_time : write_time;
5306 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5307 fname ? fname : fsp->fsp_name ));
5309 return smb_set_file_time(conn,
5316 /****************************************************************************
5317 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5318 ****************************************************************************/
5320 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5321 struct smb_request *req,
5326 SMB_STRUCT_STAT *psbuf)
5328 SMB_BIG_UINT allocation_size = 0;
5329 NTSTATUS status = NT_STATUS_OK;
5330 files_struct *new_fsp = NULL;
5332 if (!VALID_STAT(*psbuf)) {
5333 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5336 if (total_data < 8) {
5337 return NT_STATUS_INVALID_PARAMETER;
5340 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5341 #ifdef LARGE_SMB_OFF_T
5342 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5343 #else /* LARGE_SMB_OFF_T */
5344 if (IVAL(pdata,4) != 0) {
5345 /* more than 32 bits? */
5346 return NT_STATUS_INVALID_PARAMETER;
5348 #endif /* LARGE_SMB_OFF_T */
5350 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5351 fname, (double)allocation_size ));
5353 if (allocation_size) {
5354 allocation_size = smb_roundup(conn, allocation_size);
5357 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5358 fname, (double)allocation_size ));
5360 if (fsp && fsp->fh->fd != -1) {
5361 /* Open file handle. */
5362 /* Only change if needed. */
5363 if (allocation_size != get_file_size(*psbuf)) {
5364 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5365 return map_nt_error_from_unix(errno);
5368 /* But always update the time. */
5369 if (null_timespec(fsp->pending_modtime)) {
5371 * This is equivalent to a write. Ensure it's seen immediately
5372 * if there are no pending writes.
5374 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
5376 return NT_STATUS_OK;
5379 /* Pathname or stat or directory file. */
5381 status = open_file_ntcreate(conn, req, fname, psbuf,
5383 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5386 FILE_ATTRIBUTE_NORMAL,
5387 FORCE_OPLOCK_BREAK_TO_NONE,
5390 if (!NT_STATUS_IS_OK(status)) {
5391 /* NB. We check for open_was_deferred in the caller. */
5395 /* Only change if needed. */
5396 if (allocation_size != get_file_size(*psbuf)) {
5397 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5398 status = map_nt_error_from_unix(errno);
5399 close_file(new_fsp,NORMAL_CLOSE);
5404 /* Changing the allocation size should set the last mod time. */
5405 /* Don't need to call set_filetime as this will be flushed on
5408 fsp_set_pending_modtime(new_fsp, timespec_current());
5410 close_file(new_fsp,NORMAL_CLOSE);
5411 return NT_STATUS_OK;
5414 /****************************************************************************
5415 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5416 ****************************************************************************/
5418 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5419 struct smb_request *req,
5424 SMB_STRUCT_STAT *psbuf)
5428 if (total_data < 8) {
5429 return NT_STATUS_INVALID_PARAMETER;
5432 size = IVAL(pdata,0);
5433 #ifdef LARGE_SMB_OFF_T
5434 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5435 #else /* LARGE_SMB_OFF_T */
5436 if (IVAL(pdata,4) != 0) {
5437 /* more than 32 bits? */
5438 return NT_STATUS_INVALID_PARAMETER;
5440 #endif /* LARGE_SMB_OFF_T */
5441 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5442 "file %s to %.0f\n", fname, (double)size ));
5444 return smb_set_file_size(conn, req,
5451 /****************************************************************************
5452 Allow a UNIX info mknod.
5453 ****************************************************************************/
5455 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5459 SMB_STRUCT_STAT *psbuf)
5461 uint32 file_type = IVAL(pdata,56);
5462 #if defined(HAVE_MAKEDEV)
5463 uint32 dev_major = IVAL(pdata,60);
5464 uint32 dev_minor = IVAL(pdata,68);
5466 SMB_DEV_T dev = (SMB_DEV_T)0;
5467 uint32 raw_unixmode = IVAL(pdata,84);
5471 if (total_data < 100) {
5472 return NT_STATUS_INVALID_PARAMETER;
5475 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5476 if (!NT_STATUS_IS_OK(status)) {
5480 #if defined(HAVE_MAKEDEV)
5481 dev = makedev(dev_major, dev_minor);
5484 switch (file_type) {
5485 #if defined(S_IFIFO)
5486 case UNIX_TYPE_FIFO:
5487 unixmode |= S_IFIFO;
5490 #if defined(S_IFSOCK)
5491 case UNIX_TYPE_SOCKET:
5492 unixmode |= S_IFSOCK;
5495 #if defined(S_IFCHR)
5496 case UNIX_TYPE_CHARDEV:
5497 unixmode |= S_IFCHR;
5500 #if defined(S_IFBLK)
5501 case UNIX_TYPE_BLKDEV:
5502 unixmode |= S_IFBLK;
5506 return NT_STATUS_INVALID_PARAMETER;
5509 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5510 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5512 /* Ok - do the mknod. */
5513 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5514 return map_nt_error_from_unix(errno);
5517 /* If any of the other "set" calls fail we
5518 * don't want to end up with a half-constructed mknod.
5521 if (lp_inherit_perms(SNUM(conn))) {
5523 conn, parent_dirname(fname),
5527 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5528 status = map_nt_error_from_unix(errno);
5529 SMB_VFS_UNLINK(conn,fname);
5532 return NT_STATUS_OK;
5535 /****************************************************************************
5536 Deal with SMB_SET_FILE_UNIX_BASIC.
5537 ****************************************************************************/
5539 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5540 struct smb_request *req,
5545 SMB_STRUCT_STAT *psbuf)
5547 struct timespec ts[2];
5548 uint32 raw_unixmode;
5551 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5552 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5553 NTSTATUS status = NT_STATUS_OK;
5554 BOOL delete_on_fail = False;
5555 enum perm_type ptype;
5557 if (total_data < 100) {
5558 return NT_STATUS_INVALID_PARAMETER;
5561 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5562 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5563 size=IVAL(pdata,0); /* first 8 Bytes are size */
5564 #ifdef LARGE_SMB_OFF_T
5565 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5566 #else /* LARGE_SMB_OFF_T */
5567 if (IVAL(pdata,4) != 0) {
5568 /* more than 32 bits? */
5569 return NT_STATUS_INVALID_PARAMETER;
5571 #endif /* LARGE_SMB_OFF_T */
5574 ts[0] = interpret_long_date(pdata+24); /* access_time */
5575 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5576 set_owner = (uid_t)IVAL(pdata,40);
5577 set_grp = (gid_t)IVAL(pdata,48);
5578 raw_unixmode = IVAL(pdata,84);
5580 if (VALID_STAT(*psbuf)) {
5581 if (S_ISDIR(psbuf->st_mode)) {
5582 ptype = PERM_EXISTING_DIR;
5584 ptype = PERM_EXISTING_FILE;
5587 ptype = PERM_NEW_FILE;
5590 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5591 if (!NT_STATUS_IS_OK(status)) {
5595 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5596 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5597 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5599 if (!VALID_STAT(*psbuf)) {
5601 * The only valid use of this is to create character and block
5602 * devices, and named pipes. This is deprecated (IMHO) and
5603 * a new info level should be used for mknod. JRA.
5606 status = smb_unix_mknod(conn,
5611 if (!NT_STATUS_IS_OK(status)) {
5615 /* Ensure we don't try and change anything else. */
5616 raw_unixmode = SMB_MODE_NO_CHANGE;
5617 size = get_file_size(*psbuf);
5618 ts[0] = get_atimespec(psbuf);
5619 ts[1] = get_mtimespec(psbuf);
5621 * We continue here as we might want to change the
5624 delete_on_fail = True;
5628 /* Horrible backwards compatibility hack as an old server bug
5629 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5633 size = get_file_size(*psbuf);
5638 * Deal with the UNIX specific mode set.
5641 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5642 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5643 (unsigned int)unixmode, fname ));
5644 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5645 return map_nt_error_from_unix(errno);
5650 * Deal with the UNIX specific uid set.
5653 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5656 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5657 (unsigned int)set_owner, fname ));
5659 if (S_ISLNK(psbuf->st_mode)) {
5660 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5662 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5666 status = map_nt_error_from_unix(errno);
5667 if (delete_on_fail) {
5668 SMB_VFS_UNLINK(conn,fname);
5675 * Deal with the UNIX specific gid set.
5678 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5679 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5680 (unsigned int)set_owner, fname ));
5681 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5682 status = map_nt_error_from_unix(errno);
5683 if (delete_on_fail) {
5684 SMB_VFS_UNLINK(conn,fname);
5690 /* Deal with any size changes. */
5692 status = smb_set_file_size(conn, req,
5697 if (!NT_STATUS_IS_OK(status)) {
5701 /* Deal with any time changes. */
5703 return smb_set_file_time(conn,
5710 /****************************************************************************
5711 Deal with SMB_SET_FILE_UNIX_INFO2.
5712 ****************************************************************************/
5714 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5715 struct smb_request *req,
5720 SMB_STRUCT_STAT *psbuf)
5726 if (total_data < 116) {
5727 return NT_STATUS_INVALID_PARAMETER;
5730 /* Start by setting all the fields that are common between UNIX_BASIC
5733 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5735 if (!NT_STATUS_IS_OK(status)) {
5739 smb_fflags = IVAL(pdata, 108);
5740 smb_fmask = IVAL(pdata, 112);
5742 /* NB: We should only attempt to alter the file flags if the client
5743 * sends a non-zero mask.
5745 if (smb_fmask != 0) {
5746 int stat_fflags = 0;
5748 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5750 /* Client asked to alter a flag we don't understand. */
5751 return NT_STATUS_INVALID_PARAMETER;
5754 if (fsp && fsp->fh->fd != -1) {
5755 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5756 return NT_STATUS_NOT_SUPPORTED;
5758 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5759 return map_nt_error_from_unix(errno);
5764 /* XXX: need to add support for changing the create_time here. You
5765 * can do this for paths on Darwin with setattrlist(2). The right way
5766 * to hook this up is probably by extending the VFS utimes interface.
5769 return NT_STATUS_OK;
5772 /****************************************************************************
5773 Create a directory with POSIX semantics.
5774 ****************************************************************************/
5776 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5777 struct smb_request *req,
5781 SMB_STRUCT_STAT *psbuf,
5782 int *pdata_return_size)
5784 NTSTATUS status = NT_STATUS_OK;
5785 uint32 raw_unixmode = 0;
5786 uint32 mod_unixmode = 0;
5787 mode_t unixmode = (mode_t)0;
5788 files_struct *fsp = NULL;
5789 uint16 info_level_return = 0;
5791 char *pdata = *ppdata;
5793 if (total_data < 18) {
5794 return NT_STATUS_INVALID_PARAMETER;
5797 raw_unixmode = IVAL(pdata,8);
5798 /* Next 4 bytes are not yet defined. */
5800 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5801 if (!NT_STATUS_IS_OK(status)) {
5805 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5807 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5808 fname, (unsigned int)unixmode ));
5810 status = open_directory(conn, req,
5813 FILE_READ_ATTRIBUTES, /* Just a stat open */
5814 FILE_SHARE_NONE, /* Ignored for stat opens */
5821 if (NT_STATUS_IS_OK(status)) {
5822 close_file(fsp, NORMAL_CLOSE);
5825 info_level_return = SVAL(pdata,16);
5827 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5828 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5829 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5830 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5832 *pdata_return_size = 12;
5835 /* Realloc the data size */
5836 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5837 if (*ppdata == NULL) {
5838 *pdata_return_size = 0;
5839 return NT_STATUS_NO_MEMORY;
5843 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5844 SSVAL(pdata,2,0); /* No fnum. */
5845 SIVAL(pdata,4,info); /* Was directory created. */
5847 switch (info_level_return) {
5848 case SMB_QUERY_FILE_UNIX_BASIC:
5849 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5850 SSVAL(pdata,10,0); /* Padding. */
5851 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5853 case SMB_QUERY_FILE_UNIX_INFO2:
5854 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5855 SSVAL(pdata,10,0); /* Padding. */
5856 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5859 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5860 SSVAL(pdata,10,0); /* Padding. */
5867 /****************************************************************************
5868 Open/Create a file with POSIX semantics.
5869 ****************************************************************************/
5871 static NTSTATUS smb_posix_open(connection_struct *conn,
5872 struct smb_request *req,
5876 SMB_STRUCT_STAT *psbuf,
5877 int *pdata_return_size)
5879 BOOL extended_oplock_granted = False;
5880 char *pdata = *ppdata;
5882 uint32 wire_open_mode = 0;
5883 uint32 raw_unixmode = 0;
5884 uint32 mod_unixmode = 0;
5885 uint32 create_disp = 0;
5886 uint32 access_mask = 0;
5887 uint32 create_options = 0;
5888 NTSTATUS status = NT_STATUS_OK;
5889 mode_t unixmode = (mode_t)0;
5890 files_struct *fsp = NULL;
5891 int oplock_request = 0;
5893 uint16 info_level_return = 0;
5895 if (total_data < 18) {
5896 return NT_STATUS_INVALID_PARAMETER;
5899 flags = IVAL(pdata,0);
5900 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5901 if (oplock_request) {
5902 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5905 wire_open_mode = IVAL(pdata,4);
5907 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5908 return smb_posix_mkdir(conn, req,
5916 switch (wire_open_mode & SMB_ACCMODE) {
5918 access_mask = FILE_READ_DATA;
5921 access_mask = FILE_WRITE_DATA;
5924 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5927 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5928 (unsigned int)wire_open_mode ));
5929 return NT_STATUS_INVALID_PARAMETER;
5932 wire_open_mode &= ~SMB_ACCMODE;
5934 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5935 create_disp = FILE_CREATE;
5936 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5937 create_disp = FILE_OVERWRITE_IF;
5938 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5939 create_disp = FILE_OPEN_IF;
5941 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5942 (unsigned int)wire_open_mode ));
5943 return NT_STATUS_INVALID_PARAMETER;
5946 raw_unixmode = IVAL(pdata,8);
5947 /* Next 4 bytes are not yet defined. */
5949 status = unix_perms_from_wire(conn,
5952 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5955 if (!NT_STATUS_IS_OK(status)) {
5959 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5961 if (wire_open_mode & SMB_O_SYNC) {
5962 create_options |= FILE_WRITE_THROUGH;
5964 if (wire_open_mode & SMB_O_APPEND) {
5965 access_mask |= FILE_APPEND_DATA;
5967 if (wire_open_mode & SMB_O_DIRECT) {
5968 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5971 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5973 (unsigned int)wire_open_mode,
5974 (unsigned int)unixmode ));
5976 status = open_file_ntcreate(conn, req,
5980 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5982 0, /* no create options yet. */
5988 if (!NT_STATUS_IS_OK(status)) {
5992 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5993 extended_oplock_granted = True;
5996 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5997 extended_oplock_granted = True;
6000 info_level_return = SVAL(pdata,16);
6002 /* Allocate the correct return size. */
6004 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6005 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6006 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6007 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6009 *pdata_return_size = 12;
6012 /* Realloc the data size */
6013 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6014 if (*ppdata == NULL) {
6015 close_file(fsp,ERROR_CLOSE);
6016 *pdata_return_size = 0;
6017 return NT_STATUS_NO_MEMORY;
6021 if (extended_oplock_granted) {
6022 if (flags & REQUEST_BATCH_OPLOCK) {
6023 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6025 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6027 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6028 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6030 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6033 SSVAL(pdata,2,fsp->fnum);
6034 SIVAL(pdata,4,info); /* Was file created etc. */
6036 switch (info_level_return) {
6037 case SMB_QUERY_FILE_UNIX_BASIC:
6038 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6039 SSVAL(pdata,10,0); /* padding. */
6040 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6042 case SMB_QUERY_FILE_UNIX_INFO2:
6043 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6044 SSVAL(pdata,10,0); /* padding. */
6045 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6048 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6049 SSVAL(pdata,10,0); /* padding. */
6052 return NT_STATUS_OK;
6055 /****************************************************************************
6056 Delete a file with POSIX semantics.
6057 ****************************************************************************/
6059 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6060 struct smb_request *req,
6064 SMB_STRUCT_STAT *psbuf)
6066 NTSTATUS status = NT_STATUS_OK;
6067 files_struct *fsp = NULL;
6072 struct share_mode_lock *lck = NULL;
6074 if (total_data < 2) {
6075 return NT_STATUS_INVALID_PARAMETER;
6078 flags = SVAL(pdata,0);
6080 if (!VALID_STAT(*psbuf)) {
6081 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6084 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6085 !VALID_STAT_OF_DIR(*psbuf)) {
6086 return NT_STATUS_NOT_A_DIRECTORY;
6089 DEBUG(10,("smb_posix_unlink: %s %s\n",
6090 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6093 if (VALID_STAT_OF_DIR(*psbuf)) {
6094 status = open_directory(conn, req,
6098 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6101 FILE_FLAG_POSIX_SEMANTICS|0777,
6106 status = open_file_ntcreate(conn, req,
6110 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6113 FILE_FLAG_POSIX_SEMANTICS|0777,
6114 0, /* No oplock, but break existing ones. */
6119 if (!NT_STATUS_IS_OK(status)) {
6124 * Don't lie to client. If we can't really delete due to
6125 * non-POSIX opens return SHARING_VIOLATION.
6128 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
6130 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6131 "lock for file %s\n", fsp->fsp_name));
6132 close_file(fsp, NORMAL_CLOSE);
6133 return NT_STATUS_INVALID_PARAMETER;
6137 * See if others still have the file open. If this is the case, then
6138 * don't delete. If all opens are POSIX delete we can set the delete
6139 * on close disposition.
6141 for (i=0; i<lck->num_share_modes; i++) {
6142 struct share_mode_entry *e = &lck->share_modes[i];
6143 if (is_valid_share_mode_entry(e)) {
6144 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6147 /* Fail with sharing violation. */
6148 close_file(fsp, NORMAL_CLOSE);
6150 return NT_STATUS_SHARING_VIOLATION;
6155 * Set the delete on close.
6157 status = smb_set_file_disposition_info(conn,
6164 if (!NT_STATUS_IS_OK(status)) {
6165 close_file(fsp, NORMAL_CLOSE);
6170 return close_file(fsp, NORMAL_CLOSE);
6173 /****************************************************************************
6174 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6175 ****************************************************************************/
6177 static void call_trans2setfilepathinfo(connection_struct *conn,
6178 struct smb_request *req,
6179 unsigned int tran_call,
6180 char **pparams, int total_params,
6181 char **ppdata, int total_data,
6182 unsigned int max_data_bytes)
6184 char *params = *pparams;
6185 char *pdata = *ppdata;
6187 SMB_STRUCT_STAT sbuf;
6189 files_struct *fsp = NULL;
6190 NTSTATUS status = NT_STATUS_OK;
6191 int data_return_size = 0;
6192 TALLOC_CTX *ctx = talloc_tos();
6195 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6201 if (tran_call == TRANSACT2_SETFILEINFO) {
6202 if (total_params < 4) {
6203 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6207 fsp = file_fsp(SVAL(params,0));
6208 /* Basic check for non-null fsp. */
6209 if (!check_fsp_open(conn, req, fsp, ¤t_user)) {
6212 info_level = SVAL(params,2);
6214 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6216 reply_nterror(req, NT_STATUS_NO_MEMORY);
6220 if(fsp->is_directory || fsp->fh->fd == -1) {
6222 * This is actually a SETFILEINFO on a directory
6223 * handle (returned from an NT SMB). NT5.0 seems
6224 * to do this call. JRA.
6226 if (INFO_LEVEL_IS_UNIX(info_level)) {
6227 /* Always do lstat for UNIX calls. */
6228 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6229 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6230 reply_unixerror(req,ERRDOS,ERRbadpath);
6234 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6235 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6236 reply_unixerror(req,ERRDOS,ERRbadpath);
6240 } else if (fsp->print_file) {
6242 * Doing a DELETE_ON_CLOSE should cancel a print job.
6244 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6245 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6247 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6250 send_trans2_replies(req, params, 2,
6255 reply_unixerror(req, ERRDOS, ERRbadpath);
6260 * Original code - this is an open file.
6262 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6266 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6267 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6268 reply_unixerror(req, ERRDOS, ERRbadfid);
6274 if (total_params < 7) {
6275 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6279 info_level = SVAL(params,0);
6280 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6281 total_params - 6, STR_TERMINATE,
6283 if (!NT_STATUS_IS_OK(status)) {
6284 reply_nterror(req, status);
6288 status = resolve_dfspath(ctx, conn,
6289 req->flags2 & FLAGS2_DFS_PATHNAMES,
6292 if (!NT_STATUS_IS_OK(status)) {
6293 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6294 reply_botherror(req,
6295 NT_STATUS_PATH_NOT_COVERED,
6296 ERRSRV, ERRbadpath);
6299 reply_nterror(req, status);
6303 status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);
6304 if (!NT_STATUS_IS_OK(status)) {
6305 reply_nterror(req, status);
6309 status = check_name(conn, fname);
6310 if (!NT_STATUS_IS_OK(status)) {
6311 reply_nterror(req, status);
6315 if (INFO_LEVEL_IS_UNIX(info_level)) {
6317 * For CIFS UNIX extensions the target name may not exist.
6320 /* Always do lstat for UNIX calls. */
6321 SMB_VFS_LSTAT(conn,fname,&sbuf);
6323 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6324 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6325 reply_unixerror(req, ERRDOS, ERRbadpath);
6330 if (!CAN_WRITE(conn)) {
6331 reply_doserror(req, ERRSRV, ERRaccess);
6335 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6336 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6340 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6341 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6343 /* Realloc the parameter size */
6344 *pparams = (char *)SMB_REALLOC(*pparams,2);
6345 if (*pparams == NULL) {
6346 reply_nterror(req, NT_STATUS_NO_MEMORY);
6353 if (fsp && !null_timespec(fsp->pending_modtime)) {
6354 /* the pending modtime overrides the current modtime */
6355 set_mtimespec(&sbuf, fsp->pending_modtime);
6358 switch (info_level) {
6360 case SMB_INFO_STANDARD:
6362 status = smb_set_info_standard(conn,
6371 case SMB_INFO_SET_EA:
6373 status = smb_info_set_ea(conn,
6381 case SMB_SET_FILE_BASIC_INFO:
6382 case SMB_FILE_BASIC_INFORMATION:
6384 status = smb_set_file_basic_info(conn,
6393 case SMB_FILE_ALLOCATION_INFORMATION:
6394 case SMB_SET_FILE_ALLOCATION_INFO:
6396 status = smb_set_file_allocation_info(conn, req,
6405 case SMB_FILE_END_OF_FILE_INFORMATION:
6406 case SMB_SET_FILE_END_OF_FILE_INFO:
6408 status = smb_set_file_end_of_file_info(conn, req,
6417 case SMB_FILE_DISPOSITION_INFORMATION:
6418 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6421 /* JRA - We used to just ignore this on a path ?
6422 * Shouldn't this be invalid level on a pathname
6425 if (tran_call != TRANSACT2_SETFILEINFO) {
6426 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6429 status = smb_set_file_disposition_info(conn,
6438 case SMB_FILE_POSITION_INFORMATION:
6440 status = smb_file_position_information(conn,
6447 /* From tridge Samba4 :
6448 * MODE_INFORMATION in setfileinfo (I have no
6449 * idea what "mode information" on a file is - it takes a value of 0,
6450 * 2, 4 or 6. What could it be?).
6453 case SMB_FILE_MODE_INFORMATION:
6455 status = smb_file_mode_information(conn,
6462 * CIFS UNIX extensions.
6465 case SMB_SET_FILE_UNIX_BASIC:
6467 status = smb_set_file_unix_basic(conn, req,
6476 case SMB_SET_FILE_UNIX_INFO2:
6478 status = smb_set_file_unix_info2(conn, req,
6487 case SMB_SET_FILE_UNIX_LINK:
6489 if (tran_call != TRANSACT2_SETPATHINFO) {
6490 /* We must have a pathname for this. */
6491 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6494 status = smb_set_file_unix_link(conn, req, pdata,
6499 case SMB_SET_FILE_UNIX_HLINK:
6501 if (tran_call != TRANSACT2_SETPATHINFO) {
6502 /* We must have a pathname for this. */
6503 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6506 status = smb_set_file_unix_hlink(conn, req,
6512 case SMB_FILE_RENAME_INFORMATION:
6514 status = smb_file_rename_information(conn, req,
6520 #if defined(HAVE_POSIX_ACLS)
6521 case SMB_SET_POSIX_ACL:
6523 status = smb_set_posix_acl(conn,
6533 case SMB_SET_POSIX_LOCK:
6535 if (tran_call != TRANSACT2_SETFILEINFO) {
6536 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6539 status = smb_set_posix_lock(conn, req->inbuf,
6540 smb_len(req->inbuf) + 4,
6541 pdata, total_data, fsp);
6545 case SMB_POSIX_PATH_OPEN:
6547 if (tran_call != TRANSACT2_SETPATHINFO) {
6548 /* We must have a pathname for this. */
6549 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6553 status = smb_posix_open(conn, req,
6562 case SMB_POSIX_PATH_UNLINK:
6564 if (tran_call != TRANSACT2_SETPATHINFO) {
6565 /* We must have a pathname for this. */
6566 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6570 status = smb_posix_unlink(conn, req,
6579 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6584 if (!NT_STATUS_IS_OK(status)) {
6585 if (open_was_deferred(req->mid)) {
6586 /* We have re-scheduled this call. */
6589 if (blocking_lock_was_deferred(req->mid)) {
6590 /* We have re-scheduled this call. */
6593 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6594 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6595 ERRSRV, ERRbadpath);
6598 if (info_level == SMB_POSIX_PATH_OPEN) {
6599 reply_openerror(req, status);
6603 reply_nterror(req, status);
6608 send_trans2_replies(req, params, 2, *ppdata, data_return_size,
6614 /****************************************************************************
6615 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6616 ****************************************************************************/
6618 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6619 char **pparams, int total_params,
6620 char **ppdata, int total_data,
6621 unsigned int max_data_bytes)
6623 char *params = *pparams;
6624 char *pdata = *ppdata;
6625 char *directory = NULL;
6626 SMB_STRUCT_STAT sbuf;
6627 NTSTATUS status = NT_STATUS_OK;
6628 struct ea_list *ea_list = NULL;
6629 TALLOC_CTX *ctx = talloc_tos();
6631 if (!CAN_WRITE(conn)) {
6632 reply_doserror(req, ERRSRV, ERRaccess);
6636 if (total_params < 5) {
6637 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6641 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
6642 total_params - 4, STR_TERMINATE,
6644 if (!NT_STATUS_IS_OK(status)) {
6645 reply_nterror(req, status);
6649 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6651 status = unix_convert(conn, directory, False, &directory, NULL, &sbuf);
6652 if (!NT_STATUS_IS_OK(status)) {
6653 reply_nterror(req, status);
6657 status = check_name(conn, directory);
6658 if (!NT_STATUS_IS_OK(status)) {
6659 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6660 reply_nterror(req, status);
6664 /* Any data in this call is an EA list. */
6665 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6666 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6671 * OS/2 workplace shell seems to send SET_EA requests of "null"
6672 * length (4 bytes containing IVAL 4).
6673 * They seem to have no effect. Bug #3212. JRA.
6676 if (total_data != 4) {
6677 if (total_data < 10) {
6678 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6682 if (IVAL(pdata,0) > total_data) {
6683 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6684 IVAL(pdata,0), (unsigned int)total_data));
6685 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6689 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6692 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6695 } else if (IVAL(pdata,0) != 4) {
6696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6700 status = create_directory(conn, directory);
6702 if (!NT_STATUS_IS_OK(status)) {
6703 reply_nterror(req, status);
6707 /* Try and set any given EA. */
6709 status = set_ea(conn, NULL, directory, ea_list);
6710 if (!NT_STATUS_IS_OK(status)) {
6711 reply_nterror(req, status);
6716 /* Realloc the parameter and data sizes */
6717 *pparams = (char *)SMB_REALLOC(*pparams,2);
6718 if(*pparams == NULL) {
6719 reply_nterror(req, NT_STATUS_NO_MEMORY);
6726 send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
6731 /****************************************************************************
6732 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6733 We don't actually do this - we just send a null response.
6734 ****************************************************************************/
6736 static void call_trans2findnotifyfirst(connection_struct *conn,
6737 struct smb_request *req,
6738 char **pparams, int total_params,
6739 char **ppdata, int total_data,
6740 unsigned int max_data_bytes)
6742 static uint16 fnf_handle = 257;
6743 char *params = *pparams;
6746 if (total_params < 6) {
6747 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6751 info_level = SVAL(params,4);
6752 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6754 switch (info_level) {
6759 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6763 /* Realloc the parameter and data sizes */
6764 *pparams = (char *)SMB_REALLOC(*pparams,6);
6765 if (*pparams == NULL) {
6766 reply_nterror(req, NT_STATUS_NO_MEMORY);
6771 SSVAL(params,0,fnf_handle);
6772 SSVAL(params,2,0); /* No changes */
6773 SSVAL(params,4,0); /* No EA errors */
6780 send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
6785 /****************************************************************************
6786 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6787 changes). Currently this does nothing.
6788 ****************************************************************************/
6790 static void call_trans2findnotifynext(connection_struct *conn,
6791 struct smb_request *req,
6792 char **pparams, int total_params,
6793 char **ppdata, int total_data,
6794 unsigned int max_data_bytes)
6796 char *params = *pparams;
6798 DEBUG(3,("call_trans2findnotifynext\n"));
6800 /* Realloc the parameter and data sizes */
6801 *pparams = (char *)SMB_REALLOC(*pparams,4);
6802 if (*pparams == NULL) {
6803 reply_nterror(req, NT_STATUS_NO_MEMORY);
6808 SSVAL(params,0,0); /* No changes */
6809 SSVAL(params,2,0); /* No EA errors */
6811 send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes);
6816 /****************************************************************************
6817 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6818 ****************************************************************************/
6820 static void call_trans2getdfsreferral(connection_struct *conn,
6821 struct smb_request *req,
6822 char **pparams, int total_params,
6823 char **ppdata, int total_data,
6824 unsigned int max_data_bytes)
6826 char *params = *pparams;
6827 char *pathname = NULL;
6829 int max_referral_level;
6830 NTSTATUS status = NT_STATUS_OK;
6831 TALLOC_CTX *ctx = talloc_tos();
6833 DEBUG(10,("call_trans2getdfsreferral\n"));
6835 if (total_params < 3) {
6836 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6840 max_referral_level = SVAL(params,0);
6842 if(!lp_host_msdfs()) {
6843 reply_doserror(req, ERRDOS, ERRbadfunc);
6847 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
6848 total_params - 2, STR_TERMINATE);
6850 reply_nterror(req, NT_STATUS_NOT_FOUND);
6853 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6854 ppdata,&status)) < 0) {
6855 reply_nterror(req, status);
6859 SSVAL(req->inbuf, smb_flg2,
6860 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6861 send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes);
6866 #define LMCAT_SPL 0x53
6867 #define LMFUNC_GETJOBID 0x60
6869 /****************************************************************************
6870 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6871 ****************************************************************************/
6873 static void call_trans2ioctl(connection_struct *conn,
6874 struct smb_request *req,
6875 char **pparams, int total_params,
6876 char **ppdata, int total_data,
6877 unsigned int max_data_bytes)
6879 char *pdata = *ppdata;
6880 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6882 /* check for an invalid fid before proceeding */
6885 reply_doserror(req, ERRDOS, ERRbadfid);
6889 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6890 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6891 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6892 if (*ppdata == NULL) {
6893 reply_nterror(req, NT_STATUS_NO_MEMORY);
6898 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6899 CAN ACCEPT THIS IN UNICODE. JRA. */
6901 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6902 srvstr_push(pdata, req->flags2, pdata + 2,
6903 global_myname(), 15,
6904 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6905 srvstr_push(pdata, req->flags2, pdata+18,
6906 lp_servicename(SNUM(conn)), 13,
6907 STR_ASCII|STR_TERMINATE); /* Service name */
6908 send_trans2_replies(req, *pparams, 0, *ppdata, 32,
6913 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6914 reply_doserror(req, ERRSRV, ERRerror);
6917 /****************************************************************************
6918 Reply to a SMBfindclose (stop trans2 directory search).
6919 ****************************************************************************/
6921 void reply_findclose(connection_struct *conn, struct smb_request *req)
6925 START_PROFILE(SMBfindclose);
6928 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6929 END_PROFILE(SMBfindclose);
6933 dptr_num = SVALS(req->inbuf,smb_vwv0);
6935 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6937 dptr_close(&dptr_num);
6939 reply_outbuf(req, 0, 0);
6941 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6943 END_PROFILE(SMBfindclose);
6947 /****************************************************************************
6948 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6949 ****************************************************************************/
6951 void reply_findnclose(connection_struct *conn, struct smb_request *req)
6955 START_PROFILE(SMBfindnclose);
6958 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6959 END_PROFILE(SMBfindnclose);
6963 dptr_num = SVAL(req->inbuf,smb_vwv0);
6965 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6967 /* We never give out valid handles for a
6968 findnotifyfirst - so any dptr_num is ok here.
6971 reply_outbuf(req, 0, 0);
6973 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6975 END_PROFILE(SMBfindnclose);
6979 static void handle_trans2(connection_struct *conn, struct smb_request *req,
6980 struct trans_state *state)
6982 if (Protocol >= PROTOCOL_NT1) {
6983 req->flags2 |= 0x40; /* IS_LONG_NAME */
6984 SSVAL(req->inbuf,smb_flg2,req->flags2);
6987 /* Now we must call the relevant TRANS2 function */
6988 switch(state->call) {
6989 case TRANSACT2_OPEN:
6991 START_PROFILE(Trans2_open);
6992 call_trans2open(conn, req,
6993 &state->param, state->total_param,
6994 &state->data, state->total_data,
6995 state->max_data_return);
6996 END_PROFILE(Trans2_open);
7000 case TRANSACT2_FINDFIRST:
7002 START_PROFILE(Trans2_findfirst);
7003 call_trans2findfirst(conn, req,
7004 &state->param, state->total_param,
7005 &state->data, state->total_data,
7006 state->max_data_return);
7007 END_PROFILE(Trans2_findfirst);
7011 case TRANSACT2_FINDNEXT:
7013 START_PROFILE(Trans2_findnext);
7014 call_trans2findnext(conn, req,
7015 &state->param, state->total_param,
7016 &state->data, state->total_data,
7017 state->max_data_return);
7018 END_PROFILE(Trans2_findnext);
7022 case TRANSACT2_QFSINFO:
7024 START_PROFILE(Trans2_qfsinfo);
7025 call_trans2qfsinfo(conn, req,
7026 &state->param, state->total_param,
7027 &state->data, state->total_data,
7028 state->max_data_return);
7029 END_PROFILE(Trans2_qfsinfo);
7033 case TRANSACT2_SETFSINFO:
7035 START_PROFILE(Trans2_setfsinfo);
7036 call_trans2setfsinfo(conn, req,
7037 &state->param, state->total_param,
7038 &state->data, state->total_data,
7039 state->max_data_return);
7040 END_PROFILE(Trans2_setfsinfo);
7044 case TRANSACT2_QPATHINFO:
7045 case TRANSACT2_QFILEINFO:
7047 START_PROFILE(Trans2_qpathinfo);
7048 call_trans2qfilepathinfo(conn, req, state->call,
7049 &state->param, state->total_param,
7050 &state->data, state->total_data,
7051 state->max_data_return);
7052 END_PROFILE(Trans2_qpathinfo);
7056 case TRANSACT2_SETPATHINFO:
7057 case TRANSACT2_SETFILEINFO:
7059 START_PROFILE(Trans2_setpathinfo);
7060 call_trans2setfilepathinfo(conn, req, state->call,
7061 &state->param, state->total_param,
7062 &state->data, state->total_data,
7063 state->max_data_return);
7064 END_PROFILE(Trans2_setpathinfo);
7068 case TRANSACT2_FINDNOTIFYFIRST:
7070 START_PROFILE(Trans2_findnotifyfirst);
7071 call_trans2findnotifyfirst(conn, req,
7072 &state->param, state->total_param,
7073 &state->data, state->total_data,
7074 state->max_data_return);
7075 END_PROFILE(Trans2_findnotifyfirst);
7079 case TRANSACT2_FINDNOTIFYNEXT:
7081 START_PROFILE(Trans2_findnotifynext);
7082 call_trans2findnotifynext(conn, req,
7083 &state->param, state->total_param,
7084 &state->data, state->total_data,
7085 state->max_data_return);
7086 END_PROFILE(Trans2_findnotifynext);
7090 case TRANSACT2_MKDIR:
7092 START_PROFILE(Trans2_mkdir);
7093 call_trans2mkdir(conn, req,
7094 &state->param, state->total_param,
7095 &state->data, state->total_data,
7096 state->max_data_return);
7097 END_PROFILE(Trans2_mkdir);
7101 case TRANSACT2_GET_DFS_REFERRAL:
7103 START_PROFILE(Trans2_get_dfs_referral);
7104 call_trans2getdfsreferral(conn, req,
7105 &state->param, state->total_param,
7106 &state->data, state->total_data,
7107 state->max_data_return);
7108 END_PROFILE(Trans2_get_dfs_referral);
7112 case TRANSACT2_IOCTL:
7114 START_PROFILE(Trans2_ioctl);
7115 call_trans2ioctl(conn, req,
7116 &state->param, state->total_param,
7117 &state->data, state->total_data,
7118 state->max_data_return);
7119 END_PROFILE(Trans2_ioctl);
7124 /* Error in request */
7125 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7126 reply_doserror(req, ERRSRV,ERRerror);
7130 /****************************************************************************
7131 Reply to a SMBtrans2.
7132 ****************************************************************************/
7134 void reply_trans2(connection_struct *conn, struct smb_request *req)
7140 unsigned int tran_call;
7142 struct trans_state *state;
7145 START_PROFILE(SMBtrans2);
7147 if (req->wct < 14) {
7148 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7149 END_PROFILE(SMBtrans2);
7153 dsoff = SVAL(req->inbuf, smb_dsoff);
7154 dscnt = SVAL(req->inbuf, smb_dscnt);
7155 psoff = SVAL(req->inbuf, smb_psoff);
7156 pscnt = SVAL(req->inbuf, smb_pscnt);
7157 tran_call = SVAL(req->inbuf, smb_setup0);
7158 size = smb_len(req->inbuf) + 4;
7160 result = allow_new_trans(conn->pending_trans, req->mid);
7161 if (!NT_STATUS_IS_OK(result)) {
7162 DEBUG(2, ("Got invalid trans2 request: %s\n",
7163 nt_errstr(result)));
7164 reply_nterror(req, result);
7165 END_PROFILE(SMBtrans2);
7169 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
7170 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
7171 && (tran_call != TRANSACT2_QFILEINFO)) {
7172 reply_doserror(req, ERRSRV, ERRaccess);
7173 END_PROFILE(SMBtrans2);
7177 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7178 DEBUG(0, ("talloc failed\n"));
7179 reply_nterror(req, NT_STATUS_NO_MEMORY);
7180 END_PROFILE(SMBtrans2);
7184 state->cmd = SMBtrans2;
7186 state->mid = req->mid;
7187 state->vuid = req->vuid;
7188 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7189 state->setup = NULL;
7190 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7191 state->param = NULL;
7192 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7194 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7195 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7196 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7197 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7198 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7200 state->call = tran_call;
7202 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7203 is so as a sanity check */
7204 if (state->setup_count != 1) {
7206 * Need to have rc=0 for ioctl to get job id for OS/2.
7207 * Network printing will fail if function is not successful.
7208 * Similar function in reply.c will be used if protocol
7209 * is LANMAN1.0 instead of LM1.2X002.
7210 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7211 * outbuf doesn't have to be set(only job id is used).
7213 if ( (state->setup_count == 4)
7214 && (tran_call == TRANSACT2_IOCTL)
7215 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7216 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7217 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7219 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7220 DEBUG(2,("Transaction is %d\n",tran_call));
7222 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7223 END_PROFILE(SMBtrans2);
7228 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7231 if (state->total_data) {
7232 /* Can't use talloc here, the core routines do realloc on the
7233 * params and data. */
7234 state->data = (char *)SMB_MALLOC(state->total_data);
7235 if (state->data == NULL) {
7236 DEBUG(0,("reply_trans2: data malloc fail for %u "
7237 "bytes !\n", (unsigned int)state->total_data));
7239 reply_nterror(req, NT_STATUS_NO_MEMORY);
7240 END_PROFILE(SMBtrans2);
7243 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7245 if ((smb_base(req->inbuf)+dsoff+dscnt
7246 > (char *)req->inbuf + size) ||
7247 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7250 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7253 if (state->total_param) {
7254 /* Can't use talloc here, the core routines do realloc on the
7255 * params and data. */
7256 state->param = (char *)SMB_MALLOC(state->total_param);
7257 if (state->param == NULL) {
7258 DEBUG(0,("reply_trans: param malloc fail for %u "
7259 "bytes !\n", (unsigned int)state->total_param));
7260 SAFE_FREE(state->data);
7262 reply_nterror(req, NT_STATUS_NO_MEMORY);
7263 END_PROFILE(SMBtrans2);
7266 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7268 if ((smb_base(req->inbuf)+psoff+pscnt
7269 > (char *)req->inbuf + size) ||
7270 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7273 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7276 state->received_data = dscnt;
7277 state->received_param = pscnt;
7279 if ((state->received_param == state->total_param) &&
7280 (state->received_data == state->total_data)) {
7282 handle_trans2(conn, req, state);
7284 SAFE_FREE(state->data);
7285 SAFE_FREE(state->param);
7287 END_PROFILE(SMBtrans2);
7291 DLIST_ADD(conn->pending_trans, state);
7293 /* We need to send an interim response then receive the rest
7294 of the parameter/data bytes */
7295 reply_outbuf(req, 0, 0);
7296 show_msg((char *)req->outbuf);
7297 END_PROFILE(SMBtrans2);
7302 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7303 SAFE_FREE(state->data);
7304 SAFE_FREE(state->param);
7306 END_PROFILE(SMBtrans2);
7307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7311 /****************************************************************************
7312 Reply to a SMBtranss2
7313 ****************************************************************************/
7315 void reply_transs2(connection_struct *conn, struct smb_request *req)
7317 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7318 struct trans_state *state;
7321 START_PROFILE(SMBtranss2);
7323 show_msg((char *)req->inbuf);
7326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7327 END_PROFILE(SMBtranss2);
7331 size = smb_len(req->inbuf)+4;
7333 for (state = conn->pending_trans; state != NULL;
7334 state = state->next) {
7335 if (state->mid == req->mid) {
7340 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7341 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7342 END_PROFILE(SMBtranss2);
7346 /* Revise state->total_param and state->total_data in case they have
7347 changed downwards */
7349 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7350 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7351 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7352 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7354 pcnt = SVAL(req->inbuf, smb_spscnt);
7355 poff = SVAL(req->inbuf, smb_spsoff);
7356 pdisp = SVAL(req->inbuf, smb_spsdisp);
7358 dcnt = SVAL(req->inbuf, smb_sdscnt);
7359 doff = SVAL(req->inbuf, smb_sdsoff);
7360 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7362 state->received_param += pcnt;
7363 state->received_data += dcnt;
7365 if ((state->received_data > state->total_data) ||
7366 (state->received_param > state->total_param))
7370 if (pdisp+pcnt > state->total_param)
7372 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7374 if (pdisp > state->total_param)
7376 if ((smb_base(req->inbuf) + poff + pcnt
7377 > (char *)req->inbuf + size) ||
7378 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7380 if (state->param + pdisp < state->param)
7383 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7388 if (ddisp+dcnt > state->total_data)
7390 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7392 if (ddisp > state->total_data)
7394 if ((smb_base(req->inbuf) + doff + dcnt
7395 > (char *)req->inbuf + size) ||
7396 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7398 if (state->data + ddisp < state->data)
7401 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7405 if ((state->received_param < state->total_param) ||
7406 (state->received_data < state->total_data)) {
7407 END_PROFILE(SMBtranss2);
7412 * construct_reply_common will copy smb_com from inbuf to
7413 * outbuf. SMBtranss2 is wrong here.
7415 SCVAL(req->inbuf,smb_com,SMBtrans2);
7417 handle_trans2(conn, req, state);
7419 DLIST_REMOVE(conn->pending_trans, state);
7420 SAFE_FREE(state->data);
7421 SAFE_FREE(state->param);
7424 END_PROFILE(SMBtranss2);
7429 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7430 DLIST_REMOVE(conn->pending_trans, state);
7431 SAFE_FREE(state->data);
7432 SAFE_FREE(state->param);
7434 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7435 END_PROFILE(SMBtranss2);