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;
802 * Ensure we have enough parameters to perform the operation.
805 if (total_params < 29) {
806 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
810 flags = SVAL(params, 0);
811 deny_mode = SVAL(params, 2);
812 open_attr = SVAL(params,6);
813 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
814 if (oplock_request) {
815 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
819 return_additional_info = BITSETW(params,0);
820 open_sattr = SVAL(params, 4);
821 open_time = make_unix_date3(params+8);
823 open_ofun = SVAL(params,12);
824 open_size = IVAL(params,14);
828 reply_doserror(req, ERRSRV, ERRaccess);
832 srvstr_get_path(params, req->flags2, fname, pname,
833 sizeof(fname), total_params - 28, STR_TERMINATE,
835 if (!NT_STATUS_IS_OK(status)) {
836 reply_nterror(req, status);
840 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
841 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
842 (unsigned int)open_ofun, open_size));
844 /* XXXX we need to handle passed times, sattr and flags */
846 status = unix_convert(conn, fname, False, NULL, &sbuf);
847 if (!NT_STATUS_IS_OK(status)) {
848 reply_nterror(req, status);
852 status = check_name(conn, fname);
853 if (!NT_STATUS_IS_OK(status)) {
854 reply_nterror(req, status);
858 if (open_ofun == 0) {
859 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
863 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
868 reply_doserror(req, ERRDOS, ERRbadaccess);
872 /* Any data in this call is an EA list. */
873 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
874 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
878 if (total_data != 4) {
879 if (total_data < 10) {
880 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
884 if (IVAL(pdata,0) > total_data) {
885 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
886 IVAL(pdata,0), (unsigned int)total_data));
887 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
891 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
894 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
897 } else if (IVAL(pdata,0) != 4) {
898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
902 status = open_file_ntcreate(conn, req, fname, &sbuf,
911 if (!NT_STATUS_IS_OK(status)) {
912 if (open_was_deferred(req->mid)) {
913 /* We have re-scheduled this call. */
916 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
918 * We hit an existing file, and if we're returning DOS
919 * error codes OBJECT_NAME_COLLISION would map to
920 * ERRDOS/183, we need to return ERRDOS/80, see bug
923 reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION,
924 ERRDOS, ERRfilexists);
927 reply_nterror(req, status);
931 size = get_file_size(sbuf);
932 fattr = dos_mode(conn,fname,&sbuf);
933 mtime = sbuf.st_mtime;
936 close_file(fsp,ERROR_CLOSE);
937 reply_doserror(req, ERRDOS,ERRnoaccess);
941 /* Save the requested allocation size. */
942 /* Allocate space for the file if a size hint is supplied */
943 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
944 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
945 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
946 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
947 if (fsp->is_directory) {
948 close_file(fsp,ERROR_CLOSE);
949 /* Can't set allocation size on a directory. */
950 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
953 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
954 close_file(fsp,ERROR_CLOSE);
955 reply_nterror(req, NT_STATUS_DISK_FULL);
959 /* Adjust size here to return the right size in the reply.
960 Windows does it this way. */
961 size = fsp->initial_allocation_size;
963 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
967 if (ea_list && smb_action == FILE_WAS_CREATED) {
968 status = set_ea(conn, fsp, fname, ea_list);
969 if (!NT_STATUS_IS_OK(status)) {
970 close_file(fsp,ERROR_CLOSE);
971 reply_nterror(req, status);
976 /* Realloc the size of parameters and data we will return */
977 *pparams = (char *)SMB_REALLOC(*pparams, 30);
978 if(*pparams == NULL ) {
979 reply_nterror(req, NT_STATUS_NO_MEMORY);
984 SSVAL(params,0,fsp->fnum);
985 SSVAL(params,2,fattr);
986 srv_put_dos_date2(params,4, mtime);
987 SIVAL(params,8, (uint32)size);
988 SSVAL(params,12,deny_mode);
989 SSVAL(params,14,0); /* open_type - file or directory. */
990 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
992 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
993 smb_action |= EXTENDED_OPLOCK_GRANTED;
996 SSVAL(params,18,smb_action);
999 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1001 SIVAL(params,20,inode);
1002 SSVAL(params,24,0); /* Padding. */
1004 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
1005 SIVAL(params, 26, ea_size);
1007 SIVAL(params, 26, 0);
1010 /* Send the required number of replies */
1011 send_trans2_replies(req, params, 30, *ppdata, 0, max_data_bytes);
1014 /*********************************************************
1015 Routine to check if a given string matches exactly.
1016 as a special case a mask of "." does NOT match. That
1017 is required for correct wildcard semantics
1018 Case can be significant or not.
1019 **********************************************************/
1021 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
1023 if (mask[0] == '.' && mask[1] == 0)
1025 if (conn->case_sensitive)
1026 return strcmp(str,mask)==0;
1027 if (StrCaseCmp(str,mask) != 0) {
1030 if (dptr_has_wild(conn->dirptr)) {
1036 /****************************************************************************
1037 Return the filetype for UNIX extensions.
1038 ****************************************************************************/
1040 static uint32 unix_filetype(mode_t mode)
1043 return UNIX_TYPE_FILE;
1044 else if(S_ISDIR(mode))
1045 return UNIX_TYPE_DIR;
1047 else if(S_ISLNK(mode))
1048 return UNIX_TYPE_SYMLINK;
1051 else if(S_ISCHR(mode))
1052 return UNIX_TYPE_CHARDEV;
1055 else if(S_ISBLK(mode))
1056 return UNIX_TYPE_BLKDEV;
1059 else if(S_ISFIFO(mode))
1060 return UNIX_TYPE_FIFO;
1063 else if(S_ISSOCK(mode))
1064 return UNIX_TYPE_SOCKET;
1067 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1068 return UNIX_TYPE_UNKNOWN;
1071 /****************************************************************************
1072 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1073 ****************************************************************************/
1075 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1077 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1078 SMB_STRUCT_STAT *psbuf,
1080 enum perm_type ptype,
1085 if (perms == SMB_MODE_NO_CHANGE) {
1086 if (!VALID_STAT(*psbuf)) {
1087 return NT_STATUS_INVALID_PARAMETER;
1089 *ret_perms = psbuf->st_mode;
1090 return NT_STATUS_OK;
1094 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1095 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1096 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1097 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1098 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1099 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1100 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1101 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1102 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1104 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1107 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1110 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1115 /* Apply mode mask */
1116 ret &= lp_create_mask(SNUM(conn));
1117 /* Add in force bits */
1118 ret |= lp_force_create_mode(SNUM(conn));
1121 ret &= lp_dir_mask(SNUM(conn));
1122 /* Add in force bits */
1123 ret |= lp_force_dir_mode(SNUM(conn));
1125 case PERM_EXISTING_FILE:
1126 /* Apply mode mask */
1127 ret &= lp_security_mask(SNUM(conn));
1128 /* Add in force bits */
1129 ret |= lp_force_security_mode(SNUM(conn));
1131 case PERM_EXISTING_DIR:
1132 /* Apply mode mask */
1133 ret &= lp_dir_security_mask(SNUM(conn));
1134 /* Add in force bits */
1135 ret |= lp_force_dir_security_mode(SNUM(conn));
1140 return NT_STATUS_OK;
1143 /****************************************************************************
1144 Get a level dependent lanman2 dir entry.
1145 ****************************************************************************/
1147 static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
1148 char *path_mask,uint32 dirtype,int info_level,
1149 int requires_resume_key,
1150 BOOL dont_descend,char **ppdata,
1151 char *base_data, char *end_data,
1152 int space_remaining,
1153 BOOL *out_of_space, BOOL *got_exact_match,
1154 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1158 SMB_STRUCT_STAT sbuf;
1162 char *p, *q, *pdata = *ppdata;
1166 SMB_OFF_T file_size = 0;
1167 SMB_BIG_UINT allocation_size = 0;
1169 struct timespec mdate_ts, adate_ts, create_date_ts;
1170 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1172 char *last_entry_ptr;
1174 uint32 nt_extmode; /* Used for NT connections instead of mode */
1175 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1176 BOOL check_mangled_names = lp_manglednames(conn->params);
1179 *out_of_space = False;
1180 *got_exact_match = False;
1182 ZERO_STRUCT(mdate_ts);
1183 ZERO_STRUCT(adate_ts);
1184 ZERO_STRUCT(create_date_ts);
1189 p = strrchr_m(path_mask,'/');
1192 pstrcpy(mask,"*.*");
1196 pstrcpy(mask, path_mask);
1201 BOOL ms_dfs_link = False;
1203 /* Needed if we run out of space */
1204 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1205 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1208 * Due to bugs in NT client redirectors we are not using
1209 * resume keys any more - set them to zero.
1210 * Check out the related comments in findfirst/findnext.
1216 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1217 (long)conn->dirptr,curr_dirpos));
1224 * fname may get mangled, dname is never mangled.
1225 * Whenever we're accessing the filesystem we use
1226 * pathreal which is composed from dname.
1229 pstrcpy(fname,dname);
1231 /* This will mangle fname if it's an illegal name. */
1232 mangle_map(fname,False,True,conn->params);
1234 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1235 got_match = mask_match(fname, mask, conn->case_sensitive);
1238 if(!got_match && check_mangled_names &&
1239 !mangle_is_8_3(fname, False, conn->params)) {
1240 pstring mangled_name;
1243 * It turns out that NT matches wildcards against
1244 * both long *and* short names. This may explain some
1245 * of the wildcard wierdness from old DOS clients
1246 * that some people have been seeing.... JRA.
1249 pstrcpy(mangled_name, fname);
1251 /* Force the mangling into 8.3. */
1252 mangle_map( mangled_name, True, False, conn->params);
1253 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1254 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1259 BOOL isdots = (strequal(dname,"..") || strequal(dname,"."));
1260 if (dont_descend && !isdots) {
1264 pstrcpy(pathreal,conn->dirpath);
1266 pstrcat(pathreal,"/");
1268 pstrcat(pathreal,dname);
1270 if (INFO_LEVEL_IS_UNIX(info_level)) {
1271 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1272 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1273 pathreal,strerror(errno)));
1276 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1277 pstring link_target;
1279 /* Needed to show the msdfs symlinks as
1282 if(lp_host_msdfs() &&
1283 lp_msdfs_root(SNUM(conn)) &&
1284 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1285 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1288 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1292 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1293 pathreal,strerror(errno)));
1299 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1301 mode = dos_mode(conn,pathreal,&sbuf);
1304 if (!dir_check_ftype(conn,mode,dirtype)) {
1305 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1309 if (!(mode & aDIR)) {
1310 file_size = get_file_size(sbuf);
1312 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1314 mdate_ts = get_mtimespec(&sbuf);
1315 adate_ts = get_atimespec(&sbuf);
1316 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1318 if (lp_dos_filetime_resolution(SNUM(conn))) {
1319 dos_filetime_timespec(&create_date_ts);
1320 dos_filetime_timespec(&mdate_ts);
1321 dos_filetime_timespec(&adate_ts);
1324 create_date = convert_timespec_to_time_t(create_date_ts);
1325 mdate = convert_timespec_to_time_t(mdate_ts);
1326 adate = convert_timespec_to_time_t(adate_ts);
1328 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1332 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1339 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1341 switch (info_level) {
1342 case SMB_FIND_INFO_STANDARD:
1343 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1344 if(requires_resume_key) {
1348 srv_put_dos_date2(p,0,create_date);
1349 srv_put_dos_date2(p,4,adate);
1350 srv_put_dos_date2(p,8,mdate);
1351 SIVAL(p,12,(uint32)file_size);
1352 SIVAL(p,16,(uint32)allocation_size);
1356 p += align_string(pdata, p, 0);
1357 len = srvstr_push(base_data, flags2, p,
1358 fname, PTR_DIFF(end_data, p),
1360 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1362 SCVAL(nameptr, -1, len - 2);
1364 SCVAL(nameptr, -1, 0);
1368 SCVAL(nameptr, -1, len - 1);
1370 SCVAL(nameptr, -1, 0);
1376 case SMB_FIND_EA_SIZE:
1377 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1378 if(requires_resume_key) {
1382 srv_put_dos_date2(p,0,create_date);
1383 srv_put_dos_date2(p,4,adate);
1384 srv_put_dos_date2(p,8,mdate);
1385 SIVAL(p,12,(uint32)file_size);
1386 SIVAL(p,16,(uint32)allocation_size);
1389 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1390 SIVAL(p,22,ea_size); /* Extended attributes */
1394 len = srvstr_push(base_data, flags2,
1395 p, fname, PTR_DIFF(end_data, p),
1396 STR_TERMINATE | STR_NOALIGN);
1397 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1410 SCVAL(nameptr,0,len);
1412 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1415 case SMB_FIND_EA_LIST:
1417 struct ea_list *file_list = NULL;
1420 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1424 if(requires_resume_key) {
1428 srv_put_dos_date2(p,0,create_date);
1429 srv_put_dos_date2(p,4,adate);
1430 srv_put_dos_date2(p,8,mdate);
1431 SIVAL(p,12,(uint32)file_size);
1432 SIVAL(p,16,(uint32)allocation_size);
1434 p += 22; /* p now points to the EA area. */
1436 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1437 name_list = ea_list_union(name_list, file_list, &ea_len);
1439 /* We need to determine if this entry will fit in the space available. */
1440 /* Max string size is 255 bytes. */
1441 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1442 /* Move the dirptr back to prev_dirpos */
1443 dptr_SeekDir(conn->dirptr, prev_dirpos);
1444 *out_of_space = True;
1445 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1446 return False; /* Not finished - just out of space */
1449 /* Push the ea_data followed by the name. */
1450 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1452 len = srvstr_push(base_data, flags2,
1453 p + 1, fname, PTR_DIFF(end_data, p),
1454 STR_TERMINATE | STR_NOALIGN);
1455 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1468 SCVAL(nameptr,0,len);
1470 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1474 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1475 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1476 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1478 SIVAL(p,0,reskey); p += 4;
1479 put_long_date_timespec(p,create_date_ts); p += 8;
1480 put_long_date_timespec(p,adate_ts); p += 8;
1481 put_long_date_timespec(p,mdate_ts); p += 8;
1482 put_long_date_timespec(p,mdate_ts); p += 8;
1483 SOFF_T(p,0,file_size); p += 8;
1484 SOFF_T(p,0,allocation_size); p += 8;
1485 SIVAL(p,0,nt_extmode); p += 4;
1486 q = p; p += 4; /* q is placeholder for name length. */
1488 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1489 SIVAL(p,0,ea_size); /* Extended attributes */
1492 /* Clear the short name buffer. This is
1493 * IMPORTANT as not doing so will trigger
1494 * a Win2k client bug. JRA.
1496 if (!was_8_3 && check_mangled_names) {
1497 pstring mangled_name;
1498 pstrcpy(mangled_name, fname);
1499 mangle_map(mangled_name,True,True,
1501 mangled_name[12] = 0;
1502 len = srvstr_push(base_data, flags2,
1503 p+2, mangled_name, 24,
1504 STR_UPPER|STR_UNICODE);
1506 memset(p + 2 + len,'\0',24 - len);
1513 len = srvstr_push(base_data, flags2, p,
1514 fname, PTR_DIFF(end_data, p),
1515 STR_TERMINATE_ASCII);
1518 SIVAL(p,0,0); /* Ensure any padding is null. */
1519 len = PTR_DIFF(p, pdata);
1520 len = (len + 3) & ~3;
1525 case SMB_FIND_FILE_DIRECTORY_INFO:
1526 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1528 SIVAL(p,0,reskey); p += 4;
1529 put_long_date_timespec(p,create_date_ts); p += 8;
1530 put_long_date_timespec(p,adate_ts); p += 8;
1531 put_long_date_timespec(p,mdate_ts); p += 8;
1532 put_long_date_timespec(p,mdate_ts); p += 8;
1533 SOFF_T(p,0,file_size); p += 8;
1534 SOFF_T(p,0,allocation_size); p += 8;
1535 SIVAL(p,0,nt_extmode); p += 4;
1536 len = srvstr_push(base_data, flags2,
1537 p + 4, fname, PTR_DIFF(end_data, p),
1538 STR_TERMINATE_ASCII);
1541 SIVAL(p,0,0); /* Ensure any padding is null. */
1542 len = PTR_DIFF(p, pdata);
1543 len = (len + 3) & ~3;
1548 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1549 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1551 SIVAL(p,0,reskey); p += 4;
1552 put_long_date_timespec(p,create_date_ts); p += 8;
1553 put_long_date_timespec(p,adate_ts); p += 8;
1554 put_long_date_timespec(p,mdate_ts); p += 8;
1555 put_long_date_timespec(p,mdate_ts); p += 8;
1556 SOFF_T(p,0,file_size); p += 8;
1557 SOFF_T(p,0,allocation_size); p += 8;
1558 SIVAL(p,0,nt_extmode); p += 4;
1559 q = p; p += 4; /* q is placeholder for name length. */
1561 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1562 SIVAL(p,0,ea_size); /* Extended attributes */
1565 len = srvstr_push(base_data, flags2, p,
1566 fname, PTR_DIFF(end_data, p),
1567 STR_TERMINATE_ASCII);
1571 SIVAL(p,0,0); /* Ensure any padding is null. */
1572 len = PTR_DIFF(p, pdata);
1573 len = (len + 3) & ~3;
1578 case SMB_FIND_FILE_NAMES_INFO:
1579 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1581 SIVAL(p,0,reskey); p += 4;
1583 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1584 acl on a dir (tridge) */
1585 len = srvstr_push(base_data, flags2, p,
1586 fname, PTR_DIFF(end_data, p),
1587 STR_TERMINATE_ASCII);
1590 SIVAL(p,0,0); /* Ensure any padding is null. */
1591 len = PTR_DIFF(p, pdata);
1592 len = (len + 3) & ~3;
1597 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1598 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1600 SIVAL(p,0,reskey); p += 4;
1601 put_long_date_timespec(p,create_date_ts); p += 8;
1602 put_long_date_timespec(p,adate_ts); p += 8;
1603 put_long_date_timespec(p,mdate_ts); p += 8;
1604 put_long_date_timespec(p,mdate_ts); p += 8;
1605 SOFF_T(p,0,file_size); p += 8;
1606 SOFF_T(p,0,allocation_size); p += 8;
1607 SIVAL(p,0,nt_extmode); p += 4;
1608 q = p; p += 4; /* q is placeholder for name length. */
1610 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1611 SIVAL(p,0,ea_size); /* Extended attributes */
1614 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1615 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1616 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1617 len = srvstr_push(base_data, flags2, p,
1618 fname, PTR_DIFF(end_data, p),
1619 STR_TERMINATE_ASCII);
1622 SIVAL(p,0,0); /* Ensure any padding is null. */
1623 len = PTR_DIFF(p, pdata);
1624 len = (len + 3) & ~3;
1629 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1630 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1631 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1633 SIVAL(p,0,reskey); p += 4;
1634 put_long_date_timespec(p,create_date_ts); p += 8;
1635 put_long_date_timespec(p,adate_ts); p += 8;
1636 put_long_date_timespec(p,mdate_ts); p += 8;
1637 put_long_date_timespec(p,mdate_ts); p += 8;
1638 SOFF_T(p,0,file_size); p += 8;
1639 SOFF_T(p,0,allocation_size); p += 8;
1640 SIVAL(p,0,nt_extmode); p += 4;
1641 q = p; p += 4; /* q is placeholder for name length */
1643 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1644 SIVAL(p,0,ea_size); /* Extended attributes */
1647 /* Clear the short name buffer. This is
1648 * IMPORTANT as not doing so will trigger
1649 * a Win2k client bug. JRA.
1651 if (!was_8_3 && check_mangled_names) {
1652 pstring mangled_name;
1653 pstrcpy(mangled_name, fname);
1654 mangle_map(mangled_name,True,True,
1656 mangled_name[12] = 0;
1657 len = srvstr_push(base_data, flags2,
1658 p+2, mangled_name, 24,
1659 STR_UPPER|STR_UNICODE);
1662 memset(p + 2 + len,'\0',24 - len);
1669 SSVAL(p,0,0); p += 2; /* Reserved ? */
1670 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1671 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1672 len = srvstr_push(base_data, flags2, p,
1673 fname, PTR_DIFF(end_data, p),
1674 STR_TERMINATE_ASCII);
1677 SIVAL(p,0,0); /* Ensure any padding is null. */
1678 len = PTR_DIFF(p, pdata);
1679 len = (len + 3) & ~3;
1684 /* CIFS UNIX Extension. */
1686 case SMB_FIND_FILE_UNIX:
1687 case SMB_FIND_FILE_UNIX_INFO2:
1689 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1691 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1693 if (info_level == SMB_FIND_FILE_UNIX) {
1694 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1695 p = store_file_unix_basic(conn, p,
1697 len = srvstr_push(base_data, flags2, p,
1698 fname, PTR_DIFF(end_data, p),
1701 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1702 p = store_file_unix_basic_info2(conn, p,
1706 len = srvstr_push(base_data, flags2, p, fname,
1707 PTR_DIFF(end_data, p), 0);
1708 SIVAL(nameptr, 0, len);
1712 SIVAL(p,0,0); /* Ensure any padding is null. */
1714 len = PTR_DIFF(p, pdata);
1715 len = (len + 3) & ~3;
1716 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1718 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1727 if (PTR_DIFF(p,pdata) > space_remaining) {
1728 /* Move the dirptr back to prev_dirpos */
1729 dptr_SeekDir(conn->dirptr, prev_dirpos);
1730 *out_of_space = True;
1731 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1732 return False; /* Not finished - just out of space */
1735 /* Setup the last entry pointer, as an offset from base_data */
1736 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1737 /* Advance the data pointer to the next slot */
1743 /****************************************************************************
1744 Reply to a TRANS2_FINDFIRST.
1745 ****************************************************************************/
1747 static void call_trans2findfirst(connection_struct *conn,
1748 struct smb_request *req,
1749 char **pparams, int total_params,
1750 char **ppdata, int total_data,
1751 unsigned int max_data_bytes)
1753 /* We must be careful here that we don't return more than the
1754 allowed number of data bytes. If this means returning fewer than
1755 maxentries then so be it. We assume that the redirector has
1756 enough room for the fixed number of parameter bytes it has
1758 char *params = *pparams;
1759 char *pdata = *ppdata;
1763 uint16 findfirst_flags;
1764 BOOL close_after_first;
1766 BOOL requires_resume_key;
1771 int last_entry_off=0;
1775 BOOL finished = False;
1776 BOOL dont_descend = False;
1777 BOOL out_of_space = False;
1778 int space_remaining;
1779 BOOL mask_contains_wcard = False;
1780 SMB_STRUCT_STAT sbuf;
1781 TALLOC_CTX *ea_ctx = NULL;
1782 struct ea_list *ea_list = NULL;
1783 NTSTATUS ntstatus = NT_STATUS_OK;
1785 if (total_params < 13) {
1786 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1790 dirtype = SVAL(params,0);
1791 maxentries = SVAL(params,2);
1792 findfirst_flags = SVAL(params,4);
1793 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1794 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1795 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1796 info_level = SVAL(params,6);
1798 *directory = *mask = 0;
1800 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1801 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1802 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1803 info_level, max_data_bytes));
1806 /* W2K3 seems to treat zero as 1. */
1810 switch (info_level) {
1811 case SMB_FIND_INFO_STANDARD:
1812 case SMB_FIND_EA_SIZE:
1813 case SMB_FIND_EA_LIST:
1814 case SMB_FIND_FILE_DIRECTORY_INFO:
1815 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1816 case SMB_FIND_FILE_NAMES_INFO:
1817 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1818 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1819 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1821 case SMB_FIND_FILE_UNIX:
1822 case SMB_FIND_FILE_UNIX_INFO2:
1823 if (!lp_unix_extensions()) {
1824 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1829 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1833 srvstr_get_path_wcard(params, req->flags2, directory,
1834 params+12, sizeof(directory), total_params - 12,
1835 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1836 if (!NT_STATUS_IS_OK(ntstatus)) {
1837 reply_nterror(req, ntstatus);
1841 ntstatus = resolve_dfspath_wcard(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1842 if (!NT_STATUS_IS_OK(ntstatus)) {
1843 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1844 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1845 ERRSRV, ERRbadpath);
1848 reply_nterror(req, ntstatus);
1852 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1853 if (!NT_STATUS_IS_OK(ntstatus)) {
1854 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 pstrcpy(directory,"./");
1878 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1880 if (info_level == SMB_FIND_EA_LIST) {
1883 if (total_data < 4) {
1884 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1888 ea_size = IVAL(pdata,0);
1889 if (ea_size != total_data) {
1890 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1891 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1892 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1896 if (!lp_ea_support(SNUM(conn))) {
1897 reply_doserror(req, ERRDOS, ERReasnotsupported);
1901 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1902 reply_nterror(req, NT_STATUS_NO_MEMORY);
1906 /* Pull out the list of names. */
1907 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1909 talloc_destroy(ea_ctx);
1910 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1915 *ppdata = (char *)SMB_REALLOC(
1916 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1917 if(*ppdata == NULL ) {
1918 talloc_destroy(ea_ctx);
1919 reply_nterror(req, NT_STATUS_NO_MEMORY);
1923 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1925 /* Realloc the params space */
1926 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1927 if (*pparams == NULL) {
1928 talloc_destroy(ea_ctx);
1929 reply_nterror(req, NT_STATUS_NO_MEMORY);
1934 /* Save the wildcard match and attribs we are using on this directory -
1935 needed as lanman2 assumes these are being saved between calls */
1937 ntstatus = dptr_create(conn,
1943 mask_contains_wcard,
1947 if (!NT_STATUS_IS_OK(ntstatus)) {
1948 talloc_destroy(ea_ctx);
1949 reply_nterror(req, ntstatus);
1953 dptr_num = dptr_dnum(conn->dirptr);
1954 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1956 /* We don't need to check for VOL here as this is returned by
1957 a different TRANS2 call. */
1959 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1960 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1961 dont_descend = True;
1964 space_remaining = max_data_bytes;
1965 out_of_space = False;
1967 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1968 BOOL got_exact_match = False;
1970 /* this is a heuristic to avoid seeking the dirptr except when
1971 absolutely necessary. It allows for a filename of about 40 chars */
1972 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1973 out_of_space = True;
1976 finished = !get_lanman2_dir_entry(conn,
1978 mask,dirtype,info_level,
1979 requires_resume_key,dont_descend,
1981 space_remaining, &out_of_space,
1983 &last_entry_off, ea_list, ea_ctx);
1986 if (finished && out_of_space)
1989 if (!finished && !out_of_space)
1993 * As an optimisation if we know we aren't looking
1994 * for a wildcard name (ie. the name matches the wildcard exactly)
1995 * then we can finish on any (first) match.
1996 * This speeds up large directory searches. JRA.
2002 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2005 talloc_destroy(ea_ctx);
2007 /* Check if we can close the dirptr */
2008 if(close_after_first || (finished && close_if_end)) {
2009 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2010 dptr_close(&dptr_num);
2014 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2015 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2016 * the protocol level is less than NT1. Tested with smbclient. JRA.
2017 * This should fix the OS/2 client bug #2335.
2020 if(numentries == 0) {
2021 dptr_close(&dptr_num);
2022 if (Protocol < PROTOCOL_NT1) {
2023 reply_doserror(req, ERRDOS, ERRnofiles);
2026 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2027 ERRDOS, ERRbadfile);
2032 /* At this point pdata points to numentries directory entries. */
2034 /* Set up the return parameter block */
2035 SSVAL(params,0,dptr_num);
2036 SSVAL(params,2,numentries);
2037 SSVAL(params,4,finished);
2038 SSVAL(params,6,0); /* Never an EA error */
2039 SSVAL(params,8,last_entry_off);
2041 send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
2044 if ((! *directory) && dptr_path(dptr_num))
2045 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2047 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2048 smb_fn_name(CVAL(req->inbuf,smb_com)),
2049 mask, directory, dirtype, numentries ) );
2052 * Force a name mangle here to ensure that the
2053 * mask as an 8.3 name is top of the mangled cache.
2054 * The reasons for this are subtle. Don't remove
2055 * this code unless you know what you are doing
2056 * (see PR#13758). JRA.
2059 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
2060 mangle_map(mask, True, True, conn->params);
2065 /****************************************************************************
2066 Reply to a TRANS2_FINDNEXT.
2067 ****************************************************************************/
2069 static void call_trans2findnext(connection_struct *conn,
2070 struct smb_request *req,
2071 char **pparams, int total_params,
2072 char **ppdata, int total_data,
2073 unsigned int max_data_bytes)
2075 /* We must be careful here that we don't return more than the
2076 allowed number of data bytes. If this means returning fewer than
2077 maxentries then so be it. We assume that the redirector has
2078 enough room for the fixed number of parameter bytes it has
2080 char *params = *pparams;
2081 char *pdata = *ppdata;
2087 uint16 findnext_flags;
2088 BOOL close_after_request;
2090 BOOL requires_resume_key;
2092 BOOL mask_contains_wcard = False;
2093 pstring resume_name;
2099 int i, last_entry_off=0;
2100 BOOL finished = False;
2101 BOOL dont_descend = False;
2102 BOOL out_of_space = False;
2103 int space_remaining;
2104 TALLOC_CTX *ea_ctx = NULL;
2105 struct ea_list *ea_list = NULL;
2106 NTSTATUS ntstatus = NT_STATUS_OK;
2108 if (total_params < 13) {
2109 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2113 dptr_num = SVAL(params,0);
2114 maxentries = SVAL(params,2);
2115 info_level = SVAL(params,4);
2116 resume_key = IVAL(params,6);
2117 findnext_flags = SVAL(params,10);
2118 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2119 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2120 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2121 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2123 *mask = *directory = *resume_name = 0;
2125 srvstr_get_path_wcard(params, req->flags2, resume_name,
2126 params+12, sizeof(resume_name),
2127 total_params - 12, STR_TERMINATE, &ntstatus,
2128 &mask_contains_wcard);
2129 if (!NT_STATUS_IS_OK(ntstatus)) {
2130 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2131 complain (it thinks we're asking for the directory above the shared
2132 path or an invalid name). Catch this as the resume name is only compared, never used in
2133 a file access. JRA. */
2134 srvstr_pull(params, req->flags2,
2135 resume_name, params+12,
2136 sizeof(resume_name), total_params - 12,
2139 if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2140 reply_nterror(req, ntstatus);
2145 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2146 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2147 resume_key = %d resume name = %s continue=%d level = %d\n",
2148 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2149 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2152 /* W2K3 seems to treat zero as 1. */
2156 switch (info_level) {
2157 case SMB_FIND_INFO_STANDARD:
2158 case SMB_FIND_EA_SIZE:
2159 case SMB_FIND_EA_LIST:
2160 case SMB_FIND_FILE_DIRECTORY_INFO:
2161 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2162 case SMB_FIND_FILE_NAMES_INFO:
2163 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2164 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2165 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2167 case SMB_FIND_FILE_UNIX:
2168 case SMB_FIND_FILE_UNIX_INFO2:
2169 if (!lp_unix_extensions()) {
2170 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2175 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2179 if (info_level == SMB_FIND_EA_LIST) {
2182 if (total_data < 4) {
2183 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2187 ea_size = IVAL(pdata,0);
2188 if (ea_size != total_data) {
2189 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2190 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2191 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2195 if (!lp_ea_support(SNUM(conn))) {
2196 reply_doserror(req, ERRDOS, ERReasnotsupported);
2200 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2201 reply_nterror(req, NT_STATUS_NO_MEMORY);
2205 /* Pull out the list of names. */
2206 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2208 talloc_destroy(ea_ctx);
2209 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2214 *ppdata = (char *)SMB_REALLOC(
2215 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2216 if(*ppdata == NULL) {
2217 talloc_destroy(ea_ctx);
2218 reply_nterror(req, NT_STATUS_NO_MEMORY);
2223 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2225 /* Realloc the params space */
2226 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2227 if(*pparams == NULL ) {
2228 talloc_destroy(ea_ctx);
2229 reply_nterror(req, NT_STATUS_NO_MEMORY);
2235 /* Check that the dptr is valid */
2236 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2237 talloc_destroy(ea_ctx);
2238 reply_doserror(req, ERRDOS, ERRnofiles);
2242 string_set(&conn->dirpath,dptr_path(dptr_num));
2244 /* Get the wildcard mask from the dptr */
2245 if((p = dptr_wcard(dptr_num))== NULL) {
2246 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2247 talloc_destroy(ea_ctx);
2248 reply_doserror(req, ERRDOS, ERRnofiles);
2253 pstrcpy(directory,conn->dirpath);
2255 /* Get the attr mask from the dptr */
2256 dirtype = dptr_attr(dptr_num);
2258 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2259 dptr_num, mask, dirtype,
2261 dptr_TellDir(conn->dirptr)));
2263 /* We don't need to check for VOL here as this is returned by
2264 a different TRANS2 call. */
2266 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2267 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2268 dont_descend = True;
2271 space_remaining = max_data_bytes;
2272 out_of_space = False;
2275 * Seek to the correct position. We no longer use the resume key but
2276 * depend on the last file name instead.
2279 if(*resume_name && !continue_bit) {
2282 long current_pos = 0;
2284 * Remember, mangle_map is called by
2285 * get_lanman2_dir_entry(), so the resume name
2286 * could be mangled. Ensure we check the unmangled name.
2289 if (mangle_is_mangled(resume_name, conn->params)) {
2290 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2295 * Fix for NT redirector problem triggered by resume key indexes
2296 * changing between directory scans. We now return a resume key of 0
2297 * and instead look for the filename to continue from (also given
2298 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2299 * findfirst/findnext (as is usual) then the directory pointer
2300 * should already be at the correct place.
2303 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2304 } /* end if resume_name && !continue_bit */
2306 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2307 BOOL got_exact_match = False;
2309 /* this is a heuristic to avoid seeking the dirptr except when
2310 absolutely necessary. It allows for a filename of about 40 chars */
2311 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2312 out_of_space = True;
2315 finished = !get_lanman2_dir_entry(conn,
2317 mask,dirtype,info_level,
2318 requires_resume_key,dont_descend,
2320 space_remaining, &out_of_space,
2322 &last_entry_off, ea_list, ea_ctx);
2325 if (finished && out_of_space)
2328 if (!finished && !out_of_space)
2332 * As an optimisation if we know we aren't looking
2333 * for a wildcard name (ie. the name matches the wildcard exactly)
2334 * then we can finish on any (first) match.
2335 * This speeds up large directory searches. JRA.
2341 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2344 talloc_destroy(ea_ctx);
2346 /* Check if we can close the dirptr */
2347 if(close_after_request || (finished && close_if_end)) {
2348 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2349 dptr_close(&dptr_num); /* This frees up the saved mask */
2352 /* Set up the return parameter block */
2353 SSVAL(params,0,numentries);
2354 SSVAL(params,2,finished);
2355 SSVAL(params,4,0); /* Never an EA error */
2356 SSVAL(params,6,last_entry_off);
2358 send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata),
2361 if ((! *directory) && dptr_path(dptr_num))
2362 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2364 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2365 smb_fn_name(CVAL(req->inbuf,smb_com)),
2366 mask, directory, dirtype, numentries ) );
2371 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2373 E_md4hash(lp_servicename(SNUM(conn)),objid);
2377 /****************************************************************************
2378 Reply to a TRANS2_QFSINFO (query filesystem info).
2379 ****************************************************************************/
2381 static void call_trans2qfsinfo(connection_struct *conn,
2382 struct smb_request *req,
2383 char **pparams, int total_params,
2384 char **ppdata, int total_data,
2385 unsigned int max_data_bytes)
2387 char *pdata, *end_data;
2388 char *params = *pparams;
2392 const char *vname = volume_label(SNUM(conn));
2393 int snum = SNUM(conn);
2394 char *fstype = lp_fstype(SNUM(conn));
2397 if (total_params < 2) {
2398 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2402 info_level = SVAL(params,0);
2404 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2406 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2407 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2408 reply_doserror(req, ERRSRV, ERRinvdevice);
2412 *ppdata = (char *)SMB_REALLOC(
2413 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2414 if (*ppdata == NULL ) {
2415 reply_nterror(req, NT_STATUS_NO_MEMORY);
2420 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2421 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2423 switch (info_level) {
2424 case SMB_INFO_ALLOCATION:
2426 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2428 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2429 reply_unixerror(req, ERRHRD, ERRgeneral);
2433 block_size = lp_block_size(snum);
2434 if (bsize < block_size) {
2435 SMB_BIG_UINT factor = block_size/bsize;
2440 if (bsize > block_size) {
2441 SMB_BIG_UINT factor = bsize/block_size;
2446 bytes_per_sector = 512;
2447 sectors_per_unit = bsize/bytes_per_sector;
2449 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2450 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2451 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2453 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2454 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2455 SIVAL(pdata,l1_cUnit,dsize);
2456 SIVAL(pdata,l1_cUnitAvail,dfree);
2457 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2461 case SMB_INFO_VOLUME:
2462 /* Return volume name */
2464 * Add volume serial number - hash of a combination of
2465 * the called hostname and the service name.
2467 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2469 * Win2k3 and previous mess this up by sending a name length
2470 * one byte short. I believe only older clients (OS/2 Win9x) use
2471 * this call so try fixing this by adding a terminating null to
2472 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2476 pdata+l2_vol_szVolLabel, vname,
2477 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2478 STR_NOALIGN|STR_TERMINATE);
2479 SCVAL(pdata,l2_vol_cch,len);
2480 data_len = l2_vol_szVolLabel + len;
2481 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2482 (unsigned)st.st_ctime, len, vname));
2485 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2486 case SMB_FS_ATTRIBUTE_INFORMATION:
2489 #if defined(HAVE_SYS_QUOTAS)
2490 quota_flag = FILE_VOLUME_QUOTAS;
2493 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2494 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2495 FILE_SUPPORTS_OBJECT_IDS|
2496 FILE_UNICODE_ON_DISK|
2497 quota_flag); /* FS ATTRIBUTES */
2499 SIVAL(pdata,4,255); /* Max filename component length */
2500 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2501 and will think we can't do long filenames */
2502 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2503 PTR_DIFF(end_data, pdata+12),
2506 data_len = 12 + len;
2509 case SMB_QUERY_FS_LABEL_INFO:
2510 case SMB_FS_LABEL_INFORMATION:
2511 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2512 PTR_DIFF(end_data, pdata+4), 0);
2517 case SMB_QUERY_FS_VOLUME_INFO:
2518 case SMB_FS_VOLUME_INFORMATION:
2521 * Add volume serial number - hash of a combination of
2522 * the called hostname and the service name.
2524 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2525 (str_checksum(get_local_machine_name())<<16));
2527 /* Max label len is 32 characters. */
2528 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2529 PTR_DIFF(end_data, pdata+18),
2531 SIVAL(pdata,12,len);
2534 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2535 (int)strlen(vname),vname, lp_servicename(snum)));
2538 case SMB_QUERY_FS_SIZE_INFO:
2539 case SMB_FS_SIZE_INFORMATION:
2541 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2543 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2544 reply_unixerror(req, ERRHRD, ERRgeneral);
2547 block_size = lp_block_size(snum);
2548 if (bsize < block_size) {
2549 SMB_BIG_UINT factor = block_size/bsize;
2554 if (bsize > block_size) {
2555 SMB_BIG_UINT factor = bsize/block_size;
2560 bytes_per_sector = 512;
2561 sectors_per_unit = bsize/bytes_per_sector;
2562 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2563 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2564 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2565 SBIG_UINT(pdata,0,dsize);
2566 SBIG_UINT(pdata,8,dfree);
2567 SIVAL(pdata,16,sectors_per_unit);
2568 SIVAL(pdata,20,bytes_per_sector);
2572 case SMB_FS_FULL_SIZE_INFORMATION:
2574 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2576 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2577 reply_unixerror(req, ERRHRD, ERRgeneral);
2580 block_size = lp_block_size(snum);
2581 if (bsize < block_size) {
2582 SMB_BIG_UINT factor = block_size/bsize;
2587 if (bsize > block_size) {
2588 SMB_BIG_UINT factor = bsize/block_size;
2593 bytes_per_sector = 512;
2594 sectors_per_unit = bsize/bytes_per_sector;
2595 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2596 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2597 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2598 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2599 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2600 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2601 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2602 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2606 case SMB_QUERY_FS_DEVICE_INFO:
2607 case SMB_FS_DEVICE_INFORMATION:
2609 SIVAL(pdata,0,0); /* dev type */
2610 SIVAL(pdata,4,0); /* characteristics */
2613 #ifdef HAVE_SYS_QUOTAS
2614 case SMB_FS_QUOTA_INFORMATION:
2616 * what we have to send --metze:
2618 * Unknown1: 24 NULL bytes
2619 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2620 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2621 * Quota Flags: 2 byte :
2622 * Unknown3: 6 NULL bytes
2626 * details for Quota Flags:
2628 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2629 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2630 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2631 * 0x0001 Enable Quotas: enable quota for this fs
2635 /* we need to fake up a fsp here,
2636 * because its not send in this call
2639 SMB_NTQUOTA_STRUCT quotas;
2642 ZERO_STRUCT(quotas);
2648 if (current_user.ut.uid != 0) {
2649 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2650 lp_servicename(SNUM(conn)),conn->user));
2651 reply_doserror(req, ERRDOS, ERRnoaccess);
2655 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2656 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2657 reply_doserror(req, ERRSRV, ERRerror);
2663 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2665 /* Unknown1 24 NULL bytes*/
2666 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2667 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2668 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2670 /* Default Soft Quota 8 bytes */
2671 SBIG_UINT(pdata,24,quotas.softlim);
2673 /* Default Hard Quota 8 bytes */
2674 SBIG_UINT(pdata,32,quotas.hardlim);
2676 /* Quota flag 2 bytes */
2677 SSVAL(pdata,40,quotas.qflags);
2679 /* Unknown3 6 NULL bytes */
2685 #endif /* HAVE_SYS_QUOTAS */
2686 case SMB_FS_OBJECTID_INFORMATION:
2688 unsigned char objid[16];
2689 memcpy(pdata,create_volume_objectid(conn, objid),16);
2695 * Query the version and capabilities of the CIFS UNIX extensions
2699 case SMB_QUERY_CIFS_UNIX_INFO:
2700 if (!lp_unix_extensions()) {
2701 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2705 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2706 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2707 /* We have POSIX ACLs, pathname and locking capability. */
2708 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2709 CIFS_UNIX_POSIX_ACLS_CAP|
2710 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2711 CIFS_UNIX_FCNTL_LOCKS_CAP|
2712 CIFS_UNIX_EXTATTR_CAP|
2713 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2714 /* Ensure we don't do this on signed or sealed data. */
2715 (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2719 case SMB_QUERY_POSIX_FS_INFO:
2722 vfs_statvfs_struct svfs;
2724 if (!lp_unix_extensions()) {
2725 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2729 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2733 SIVAL(pdata,0,svfs.OptimalTransferSize);
2734 SIVAL(pdata,4,svfs.BlockSize);
2735 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2736 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2737 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2738 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2739 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2740 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2741 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2743 } else if (rc == EOPNOTSUPP) {
2744 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2746 #endif /* EOPNOTSUPP */
2748 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2749 reply_doserror(req, ERRSRV, ERRerror);
2755 case SMB_QUERY_POSIX_WHOAMI:
2761 if (!lp_unix_extensions()) {
2762 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2766 if (max_data_bytes < 40) {
2767 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2771 /* We ARE guest if global_sid_Builtin_Guests is
2772 * in our list of SIDs.
2774 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2775 current_user.nt_user_token)) {
2776 flags |= SMB_WHOAMI_GUEST;
2779 /* We are NOT guest if global_sid_Authenticated_Users
2780 * is in our list of SIDs.
2782 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2783 current_user.nt_user_token)) {
2784 flags &= ~SMB_WHOAMI_GUEST;
2787 /* NOTE: 8 bytes for UID/GID, irrespective of native
2788 * platform size. This matches
2789 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2791 data_len = 4 /* flags */
2798 + 4 /* pad/reserved */
2799 + (current_user.ut.ngroups * 8)
2801 + (current_user.nt_user_token->num_sids *
2805 SIVAL(pdata, 0, flags);
2806 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2807 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2808 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2811 if (data_len >= max_data_bytes) {
2812 /* Potential overflow, skip the GIDs and SIDs. */
2814 SIVAL(pdata, 24, 0); /* num_groups */
2815 SIVAL(pdata, 28, 0); /* num_sids */
2816 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2817 SIVAL(pdata, 36, 0); /* reserved */
2823 SIVAL(pdata, 24, current_user.ut.ngroups);
2825 current_user.nt_user_token->num_sids);
2827 /* We walk the SID list twice, but this call is fairly
2828 * infrequent, and I don't expect that it's performance
2829 * sensitive -- jpeach
2831 for (i = 0, sid_bytes = 0;
2832 i < current_user.nt_user_token->num_sids; ++i) {
2834 sid_size(¤t_user.nt_user_token->user_sids[i]);
2837 /* SID list byte count */
2838 SIVAL(pdata, 32, sid_bytes);
2840 /* 4 bytes pad/reserved - must be zero */
2841 SIVAL(pdata, 36, 0);
2845 for (i = 0; i < current_user.ut.ngroups; ++i) {
2846 SBIG_UINT(pdata, data_len,
2847 (SMB_BIG_UINT)current_user.ut.groups[i]);
2853 i < current_user.nt_user_token->num_sids; ++i) {
2855 sid_size(¤t_user.nt_user_token->user_sids[i]);
2857 sid_linearize(pdata + data_len, sid_len,
2858 ¤t_user.nt_user_token->user_sids[i]);
2859 data_len += sid_len;
2865 case SMB_MAC_QUERY_FS_INFO:
2867 * Thursby MAC extension... ONLY on NTFS filesystems
2868 * once we do streams then we don't need this
2870 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2872 SIVAL(pdata,84,0x100); /* Don't support mac... */
2877 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2882 send_trans2_replies(req, params, 0, pdata, data_len,
2885 DEBUG( 4, ( "%s info_level = %d\n",
2886 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2891 /****************************************************************************
2892 Reply to a TRANS2_SETFSINFO (set filesystem info).
2893 ****************************************************************************/
2895 static void call_trans2setfsinfo(connection_struct *conn,
2896 struct smb_request *req,
2897 char **pparams, int total_params,
2898 char **ppdata, int total_data,
2899 unsigned int max_data_bytes)
2901 char *pdata = *ppdata;
2902 char *params = *pparams;
2905 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2908 if (total_params < 4) {
2909 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2915 info_level = SVAL(params,2);
2917 switch(info_level) {
2918 case SMB_SET_CIFS_UNIX_INFO:
2920 uint16 client_unix_major;
2921 uint16 client_unix_minor;
2922 uint32 client_unix_cap_low;
2923 uint32 client_unix_cap_high;
2925 if (!lp_unix_extensions()) {
2927 NT_STATUS_INVALID_LEVEL);
2931 /* There should be 12 bytes of capabilities set. */
2932 if (total_data < 8) {
2935 NT_STATUS_INVALID_PARAMETER);
2938 client_unix_major = SVAL(pdata,0);
2939 client_unix_minor = SVAL(pdata,2);
2940 client_unix_cap_low = IVAL(pdata,4);
2941 client_unix_cap_high = IVAL(pdata,8);
2942 /* Just print these values for now. */
2943 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2944 cap_low = 0x%x, cap_high = 0x%x\n",
2945 (unsigned int)client_unix_major,
2946 (unsigned int)client_unix_minor,
2947 (unsigned int)client_unix_cap_low,
2948 (unsigned int)client_unix_cap_high ));
2950 /* Here is where we must switch to posix pathname processing... */
2951 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2952 lp_set_posix_pathnames();
2953 mangle_change_to_posix();
2956 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2957 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2958 /* Client that knows how to do posix locks,
2959 * but not posix open/mkdir operations. Set a
2960 * default type for read/write checks. */
2962 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2967 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2970 size_t param_len = 0;
2971 size_t data_len = total_data;
2973 if (!lp_unix_extensions()) {
2975 req, NT_STATUS_INVALID_LEVEL);
2979 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2981 status = srv_request_encryption_setup(conn,
2982 (unsigned char **)ppdata,
2984 (unsigned char **)pparams,
2988 if (!NT_STATUS_IS_OK(status)) {
2991 * MORE_PROCESSING_REQUIRED, this used
2992 * to have special handling here.
2994 reply_nterror(req, status);
2998 send_trans2_replies(req,
2999 *pparams, param_len,
3003 if (NT_STATUS_IS_OK(status)) {
3004 /* Server-side transport encryption is now *on*. */
3005 status = srv_encryption_start(conn);
3006 if (!NT_STATUS_IS_OK(status)) {
3007 exit_server_cleanly("Failure in setting up encrypted transport");
3012 case SMB_FS_QUOTA_INFORMATION:
3014 files_struct *fsp = NULL;
3015 SMB_NTQUOTA_STRUCT quotas;
3017 ZERO_STRUCT(quotas);
3020 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3021 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3022 lp_servicename(SNUM(conn)),conn->user));
3023 reply_doserror(req, ERRSRV, ERRaccess);
3027 /* note: normaly there're 48 bytes,
3028 * but we didn't use the last 6 bytes for now
3031 fsp = file_fsp(SVAL(params,0));
3032 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3033 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3035 req, NT_STATUS_INVALID_HANDLE);
3039 if (total_data < 42) {
3040 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3044 NT_STATUS_INVALID_PARAMETER);
3048 /* unknown_1 24 NULL bytes in pdata*/
3050 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3051 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3052 #ifdef LARGE_SMB_OFF_T
3053 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3054 #else /* LARGE_SMB_OFF_T */
3055 if ((IVAL(pdata,28) != 0)&&
3056 ((quotas.softlim != 0xFFFFFFFF)||
3057 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3058 /* more than 32 bits? */
3061 NT_STATUS_INVALID_PARAMETER);
3064 #endif /* LARGE_SMB_OFF_T */
3066 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3067 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3068 #ifdef LARGE_SMB_OFF_T
3069 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3070 #else /* LARGE_SMB_OFF_T */
3071 if ((IVAL(pdata,36) != 0)&&
3072 ((quotas.hardlim != 0xFFFFFFFF)||
3073 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3074 /* more than 32 bits? */
3077 NT_STATUS_INVALID_PARAMETER);
3080 #endif /* LARGE_SMB_OFF_T */
3082 /* quota_flags 2 bytes **/
3083 quotas.qflags = SVAL(pdata,40);
3085 /* unknown_2 6 NULL bytes follow*/
3087 /* now set the quotas */
3088 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3089 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3090 reply_doserror(req, ERRSRV, ERRerror);
3097 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3099 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3105 * sending this reply works fine,
3106 * but I'm not sure it's the same
3107 * like windows do...
3110 reply_outbuf(req, 10, 0);
3113 #if defined(HAVE_POSIX_ACLS)
3114 /****************************************************************************
3115 Utility function to count the number of entries in a POSIX acl.
3116 ****************************************************************************/
3118 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3120 unsigned int ace_count = 0;
3121 int entry_id = SMB_ACL_FIRST_ENTRY;
3122 SMB_ACL_ENTRY_T entry;
3124 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3126 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3127 entry_id = SMB_ACL_NEXT_ENTRY;
3134 /****************************************************************************
3135 Utility function to marshall a POSIX acl into wire format.
3136 ****************************************************************************/
3138 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3140 int entry_id = SMB_ACL_FIRST_ENTRY;
3141 SMB_ACL_ENTRY_T entry;
3143 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3144 SMB_ACL_TAG_T tagtype;
3145 SMB_ACL_PERMSET_T permset;
3146 unsigned char perms = 0;
3147 unsigned int own_grp;
3150 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3151 entry_id = SMB_ACL_NEXT_ENTRY;
3154 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3155 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3159 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3160 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3164 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3165 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3166 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3168 SCVAL(pdata,1,perms);
3171 case SMB_ACL_USER_OBJ:
3172 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3173 own_grp = (unsigned int)pst->st_uid;
3174 SIVAL(pdata,2,own_grp);
3179 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3181 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3184 own_grp = (unsigned int)*puid;
3185 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3186 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3187 SIVAL(pdata,2,own_grp);
3191 case SMB_ACL_GROUP_OBJ:
3192 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3193 own_grp = (unsigned int)pst->st_gid;
3194 SIVAL(pdata,2,own_grp);
3199 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3201 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3204 own_grp = (unsigned int)*pgid;
3205 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3206 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3207 SIVAL(pdata,2,own_grp);
3212 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3213 SIVAL(pdata,2,0xFFFFFFFF);
3214 SIVAL(pdata,6,0xFFFFFFFF);
3217 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3218 SIVAL(pdata,2,0xFFFFFFFF);
3219 SIVAL(pdata,6,0xFFFFFFFF);
3222 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3225 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3232 /****************************************************************************
3233 Store the FILE_UNIX_BASIC info.
3234 ****************************************************************************/
3236 static char *store_file_unix_basic(connection_struct *conn,
3239 const SMB_STRUCT_STAT *psbuf)
3241 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3242 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3244 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3247 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3250 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3251 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3252 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3255 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3259 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3263 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3266 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3270 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3274 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3277 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3281 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3288 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3289 * the chflags(2) (or equivalent) flags.
3291 * XXX: this really should be behind the VFS interface. To do this, we would
3292 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3293 * Each VFS module could then implement it's own mapping as appropriate for the
3294 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3296 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3300 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3304 { UF_IMMUTABLE, EXT_IMMUTABLE },
3308 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3312 { UF_HIDDEN, EXT_HIDDEN },
3315 /* Do not remove. We need to guarantee that this array has at least one
3316 * entry to build on HP-UX.
3322 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3323 uint32 *smb_fflags, uint32 *smb_fmask)
3325 #ifdef HAVE_STAT_ST_FLAGS
3328 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3329 *smb_fmask |= info2_flags_map[i].smb_fflag;
3330 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3331 *smb_fflags |= info2_flags_map[i].smb_fflag;
3334 #endif /* HAVE_STAT_ST_FLAGS */
3337 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3338 const uint32 smb_fflags,
3339 const uint32 smb_fmask,
3342 #ifdef HAVE_STAT_ST_FLAGS
3343 uint32 max_fmask = 0;
3346 *stat_fflags = psbuf->st_flags;
3348 /* For each flags requested in smb_fmask, check the state of the
3349 * corresponding flag in smb_fflags and set or clear the matching
3353 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3354 max_fmask |= info2_flags_map[i].smb_fflag;
3355 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3356 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3357 *stat_fflags |= info2_flags_map[i].stat_fflag;
3359 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3364 /* If smb_fmask is asking to set any bits that are not supported by
3365 * our flag mappings, we should fail.
3367 if ((smb_fmask & max_fmask) != smb_fmask) {
3374 #endif /* HAVE_STAT_ST_FLAGS */
3378 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3379 * of file flags and birth (create) time.
3381 static char *store_file_unix_basic_info2(connection_struct *conn,
3384 const SMB_STRUCT_STAT *psbuf)
3386 uint32 file_flags = 0;
3387 uint32 flags_mask = 0;
3389 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3391 /* Create (birth) time 64 bit */
3392 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3395 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3396 SIVAL(pdata, 0, file_flags); /* flags */
3397 SIVAL(pdata, 4, flags_mask); /* mask */
3403 /****************************************************************************
3404 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3405 ****************************************************************************/
3407 static void call_trans2qpipeinfo(connection_struct *conn,
3408 struct smb_request *req,
3409 unsigned int tran_call,
3410 char **pparams, int total_params,
3411 char **ppdata, int total_data,
3412 unsigned int max_data_bytes)
3414 char *params = *pparams;
3415 char *pdata = *ppdata;
3416 unsigned int data_size = 0;
3417 unsigned int param_size = 2;
3419 smb_np_struct *p_pipe = NULL;
3422 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3426 if (total_params < 4) {
3427 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3431 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3432 if (p_pipe == NULL) {
3433 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3437 info_level = SVAL(params,2);
3439 *pparams = (char *)SMB_REALLOC(*pparams,2);
3440 if (*pparams == NULL) {
3441 reply_nterror(req, NT_STATUS_NO_MEMORY);
3446 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3447 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3448 if (*ppdata == NULL ) {
3449 reply_nterror(req, NT_STATUS_NO_MEMORY);
3454 switch (info_level) {
3455 case SMB_FILE_STANDARD_INFORMATION:
3457 SOFF_T(pdata,0,4096LL);
3464 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3468 send_trans2_replies(req, params, param_size, *ppdata, data_size,
3474 /****************************************************************************
3475 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3476 file name or file id).
3477 ****************************************************************************/
3479 static void call_trans2qfilepathinfo(connection_struct *conn,
3480 struct smb_request *req,
3481 unsigned int tran_call,
3482 char **pparams, int total_params,
3483 char **ppdata, int total_data,
3484 unsigned int max_data_bytes)
3486 char *params = *pparams;
3487 char *pdata = *ppdata;
3488 char *dstart, *dend;
3492 SMB_OFF_T file_size=0;
3493 SMB_BIG_UINT allocation_size=0;
3494 unsigned int data_size = 0;
3495 unsigned int param_size = 2;
3496 SMB_STRUCT_STAT sbuf;
3497 pstring fname, dos_fname;
3502 BOOL delete_pending = False;
3504 time_t create_time, mtime, atime;
3505 struct timespec create_time_ts, mtime_ts, atime_ts;
3506 files_struct *fsp = NULL;
3507 struct file_id fileid;
3508 TALLOC_CTX *data_ctx = NULL;
3509 struct ea_list *ea_list = NULL;
3510 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3511 char *lock_data = NULL;
3514 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3520 if (tran_call == TRANSACT2_QFILEINFO) {
3521 if (total_params < 4) {
3522 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3527 call_trans2qpipeinfo(conn, req, tran_call,
3528 pparams, total_params,
3534 fsp = file_fsp(SVAL(params,0));
3535 info_level = SVAL(params,2);
3537 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3539 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3540 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3544 if(fsp && (fsp->fake_file_handle)) {
3546 * This is actually for the QUOTA_FAKE_FILE --metze
3549 pstrcpy(fname, fsp->fsp_name);
3550 /* We know this name is ok, it's already passed the checks. */
3552 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3554 * This is actually a QFILEINFO on a directory
3555 * handle (returned from an NT SMB). NT5.0 seems
3556 * to do this call. JRA.
3558 /* We know this name is ok, it's already passed the checks. */
3559 pstrcpy(fname, fsp->fsp_name);
3561 if (INFO_LEVEL_IS_UNIX(info_level)) {
3562 /* Always do lstat for UNIX calls. */
3563 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3564 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3565 reply_unixerror(req,ERRDOS,ERRbadpath);
3568 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3569 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3570 reply_unixerror(req, ERRDOS, ERRbadpath);
3574 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3575 delete_pending = get_delete_on_close_flag(fileid);
3578 * Original code - this is an open file.
3580 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3584 pstrcpy(fname, fsp->fsp_name);
3585 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3586 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3587 reply_unixerror(req, ERRDOS, ERRbadfid);
3590 pos = fsp->fh->position_information;
3591 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3592 delete_pending = get_delete_on_close_flag(fileid);
3593 access_mask = fsp->access_mask;
3596 NTSTATUS status = NT_STATUS_OK;
3599 if (total_params < 7) {
3600 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3604 info_level = SVAL(params,0);
3606 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3608 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3609 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3613 srvstr_get_path(params, req->flags2, fname, ¶ms[6],
3614 sizeof(fname), total_params - 6,
3615 STR_TERMINATE, &status);
3616 if (!NT_STATUS_IS_OK(status)) {
3617 reply_nterror(req, status);
3621 status = resolve_dfspath(conn,
3622 req->flags2 & FLAGS2_DFS_PATHNAMES,
3624 if (!NT_STATUS_IS_OK(status)) {
3625 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3626 reply_botherror(req,
3627 NT_STATUS_PATH_NOT_COVERED,
3628 ERRSRV, ERRbadpath);
3630 reply_nterror(req, status);
3634 status = unix_convert(conn, fname, False, NULL, &sbuf);
3635 if (!NT_STATUS_IS_OK(status)) {
3636 reply_nterror(req, status);
3639 status = check_name(conn, fname);
3640 if (!NT_STATUS_IS_OK(status)) {
3641 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3642 reply_nterror(req, status);
3646 if (INFO_LEVEL_IS_UNIX(info_level)) {
3647 /* Always do lstat for UNIX calls. */
3648 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3649 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3650 reply_unixerror(req, ERRDOS, ERRbadpath);
3653 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3654 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3655 reply_unixerror(req, ERRDOS, ERRbadpath);
3659 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3660 delete_pending = get_delete_on_close_flag(fileid);
3661 if (delete_pending) {
3662 reply_nterror(req, NT_STATUS_DELETE_PENDING);
3667 nlink = sbuf.st_nlink;
3669 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3670 /* NTFS does not seem to count ".." */
3674 if ((nlink > 0) && delete_pending) {
3678 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3679 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3683 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3684 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3686 p = strrchr_m(fname,'/');
3692 mode = dos_mode(conn,fname,&sbuf);
3694 mode = FILE_ATTRIBUTE_NORMAL;
3696 fullpathname = fname;
3698 file_size = get_file_size(sbuf);
3700 /* Pull out any data sent here before we realloc. */
3701 switch (info_level) {
3702 case SMB_INFO_QUERY_EAS_FROM_LIST:
3704 /* Pull any EA list from the data portion. */
3707 if (total_data < 4) {
3709 req, NT_STATUS_INVALID_PARAMETER);
3712 ea_size = IVAL(pdata,0);
3714 if (total_data > 0 && ea_size != total_data) {
3715 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3716 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3718 req, NT_STATUS_INVALID_PARAMETER);
3722 if (!lp_ea_support(SNUM(conn))) {
3723 reply_doserror(req, ERRDOS,
3724 ERReasnotsupported);
3728 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3729 reply_nterror(req, NT_STATUS_NO_MEMORY);
3733 /* Pull out the list of names. */
3734 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3736 talloc_destroy(data_ctx);
3738 req, NT_STATUS_INVALID_PARAMETER);
3744 case SMB_QUERY_POSIX_LOCK:
3746 if (fsp == NULL || fsp->fh->fd == -1) {
3747 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3751 if (total_data != POSIX_LOCK_DATA_SIZE) {
3753 req, NT_STATUS_INVALID_PARAMETER);
3757 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3758 reply_nterror(req, NT_STATUS_NO_MEMORY);
3762 /* Copy the lock range data. */
3763 lock_data = (char *)TALLOC_MEMDUP(
3764 data_ctx, pdata, total_data);
3766 talloc_destroy(data_ctx);
3767 reply_nterror(req, NT_STATUS_NO_MEMORY);
3775 *pparams = (char *)SMB_REALLOC(*pparams,2);
3776 if (*pparams == NULL) {
3777 talloc_destroy(data_ctx);
3778 reply_nterror(req, NT_STATUS_NO_MEMORY);
3783 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3784 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3785 if (*ppdata == NULL ) {
3786 talloc_destroy(data_ctx);
3787 reply_nterror(req, NT_STATUS_NO_MEMORY);
3792 dend = dstart + data_size - 1;
3794 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3795 mtime_ts = get_mtimespec(&sbuf);
3796 atime_ts = get_atimespec(&sbuf);
3798 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3801 if (!null_timespec(fsp->pending_modtime)) {
3802 /* the pending modtime overrides the current modtime */
3803 mtime_ts = fsp->pending_modtime;
3807 /* Do we have this path open ? */
3808 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3809 fsp1 = file_find_di_first(fileid);
3810 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3811 /* the pending modtime overrides the current modtime */
3812 mtime_ts = fsp1->pending_modtime;
3814 if (fsp1 && fsp1->initial_allocation_size) {
3815 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3819 if (lp_dos_filetime_resolution(SNUM(conn))) {
3820 dos_filetime_timespec(&create_time_ts);
3821 dos_filetime_timespec(&mtime_ts);
3822 dos_filetime_timespec(&atime_ts);
3825 create_time = convert_timespec_to_time_t(create_time_ts);
3826 mtime = convert_timespec_to_time_t(mtime_ts);
3827 atime = convert_timespec_to_time_t(atime_ts);
3829 /* NT expects the name to be in an exact form of the *full*
3830 filename. See the trans2 torture test */
3831 if (strequal(base_name,".")) {
3832 pstrcpy(dos_fname, "\\");
3834 pstr_sprintf(dos_fname, "\\%s", fname);
3835 string_replace(dos_fname, '/', '\\');
3838 switch (info_level) {
3839 case SMB_INFO_STANDARD:
3840 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3842 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3843 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3844 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3845 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3846 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3847 SSVAL(pdata,l1_attrFile,mode);
3850 case SMB_INFO_QUERY_EA_SIZE:
3852 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3853 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3855 srv_put_dos_date2(pdata,0,create_time);
3856 srv_put_dos_date2(pdata,4,atime);
3857 srv_put_dos_date2(pdata,8,mtime); /* write time */
3858 SIVAL(pdata,12,(uint32)file_size);
3859 SIVAL(pdata,16,(uint32)allocation_size);
3860 SSVAL(pdata,20,mode);
3861 SIVAL(pdata,22,ea_size);
3865 case SMB_INFO_IS_NAME_VALID:
3866 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3867 if (tran_call == TRANSACT2_QFILEINFO) {
3868 /* os/2 needs this ? really ?*/
3869 reply_doserror(req, ERRDOS, ERRbadfunc);
3876 case SMB_INFO_QUERY_EAS_FROM_LIST:
3878 size_t total_ea_len = 0;
3879 struct ea_list *ea_file_list = NULL;
3881 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3883 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3884 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3886 if (!ea_list || (total_ea_len > data_size)) {
3887 talloc_destroy(data_ctx);
3889 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3893 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3894 talloc_destroy(data_ctx);
3898 case SMB_INFO_QUERY_ALL_EAS:
3900 /* We have data_size bytes to put EA's into. */
3901 size_t total_ea_len = 0;
3903 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3905 data_ctx = talloc_init("ea_ctx");
3907 reply_nterror(req, NT_STATUS_NO_MEMORY);
3911 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3912 if (!ea_list || (total_ea_len > data_size)) {
3913 talloc_destroy(data_ctx);
3915 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3919 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3920 talloc_destroy(data_ctx);
3924 case SMB_FILE_BASIC_INFORMATION:
3925 case SMB_QUERY_FILE_BASIC_INFO:
3927 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3928 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3929 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3931 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3935 put_long_date_timespec(pdata,create_time_ts);
3936 put_long_date_timespec(pdata+8,atime_ts);
3937 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3938 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3939 SIVAL(pdata,32,mode);
3941 DEBUG(5,("SMB_QFBI - "));
3942 DEBUG(5,("create: %s ", ctime(&create_time)));
3943 DEBUG(5,("access: %s ", ctime(&atime)));
3944 DEBUG(5,("write: %s ", ctime(&mtime)));
3945 DEBUG(5,("change: %s ", ctime(&mtime)));
3946 DEBUG(5,("mode: %x\n", mode));
3949 case SMB_FILE_STANDARD_INFORMATION:
3950 case SMB_QUERY_FILE_STANDARD_INFO:
3952 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3954 SOFF_T(pdata,0,allocation_size);
3955 SOFF_T(pdata,8,file_size);
3956 SIVAL(pdata,16,nlink);
3957 SCVAL(pdata,20,delete_pending?1:0);
3958 SCVAL(pdata,21,(mode&aDIR)?1:0);
3959 SSVAL(pdata,22,0); /* Padding. */
3962 case SMB_FILE_EA_INFORMATION:
3963 case SMB_QUERY_FILE_EA_INFO:
3965 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3966 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3968 SIVAL(pdata,0,ea_size);
3972 /* Get the 8.3 name - used if NT SMB was negotiated. */
3973 case SMB_QUERY_FILE_ALT_NAME_INFO:
3974 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3978 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3979 pstrcpy(short_name,base_name);
3980 /* Mangle if not already 8.3 */
3981 if(!mangle_is_8_3(short_name, True, conn->params)) {
3982 mangle_map(short_name,True,True,conn->params);
3984 len = srvstr_push(dstart, req->flags2,
3985 pdata+4, short_name,
3986 PTR_DIFF(dend, pdata+4),
3988 data_size = 4 + len;
3993 case SMB_QUERY_FILE_NAME_INFO:
3995 this must be *exactly* right for ACLs on mapped drives to work
3997 len = srvstr_push(dstart, req->flags2,
3999 PTR_DIFF(dend, pdata+4),
4001 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4002 data_size = 4 + len;
4006 case SMB_FILE_ALLOCATION_INFORMATION:
4007 case SMB_QUERY_FILE_ALLOCATION_INFO:
4008 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4010 SOFF_T(pdata,0,allocation_size);
4013 case SMB_FILE_END_OF_FILE_INFORMATION:
4014 case SMB_QUERY_FILE_END_OF_FILEINFO:
4015 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4017 SOFF_T(pdata,0,file_size);
4020 case SMB_QUERY_FILE_ALL_INFO:
4021 case SMB_FILE_ALL_INFORMATION:
4023 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4024 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4025 put_long_date_timespec(pdata,create_time_ts);
4026 put_long_date_timespec(pdata+8,atime_ts);
4027 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4028 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4029 SIVAL(pdata,32,mode);
4030 SIVAL(pdata,36,0); /* padding. */
4032 SOFF_T(pdata,0,allocation_size);
4033 SOFF_T(pdata,8,file_size);
4034 SIVAL(pdata,16,nlink);
4035 SCVAL(pdata,20,delete_pending);
4036 SCVAL(pdata,21,(mode&aDIR)?1:0);
4039 SIVAL(pdata,0,ea_size);
4040 pdata += 4; /* EA info */
4041 len = srvstr_push(dstart, req->flags2,
4043 PTR_DIFF(dend, pdata+4),
4047 data_size = PTR_DIFF(pdata,(*ppdata));
4050 case SMB_FILE_INTERNAL_INFORMATION:
4051 /* This should be an index number - looks like
4054 I think this causes us to fail the IFSKIT
4055 BasicFileInformationTest. -tpot */
4057 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4058 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4059 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4063 case SMB_FILE_ACCESS_INFORMATION:
4064 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4065 SIVAL(pdata,0,access_mask);
4069 case SMB_FILE_NAME_INFORMATION:
4070 /* Pathname with leading '\'. */
4073 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4074 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4075 SIVAL(pdata,0,byte_len);
4076 data_size = 4 + byte_len;
4080 case SMB_FILE_DISPOSITION_INFORMATION:
4081 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4083 SCVAL(pdata,0,delete_pending);
4086 case SMB_FILE_POSITION_INFORMATION:
4087 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4089 SOFF_T(pdata,0,pos);
4092 case SMB_FILE_MODE_INFORMATION:
4093 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4094 SIVAL(pdata,0,mode);
4098 case SMB_FILE_ALIGNMENT_INFORMATION:
4099 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4100 SIVAL(pdata,0,0); /* No alignment needed. */
4106 * NT4 server just returns "invalid query" to this - if we try to answer
4107 * it then NTws gets a BSOD! (tridge).
4108 * W2K seems to want this. JRA.
4110 case SMB_QUERY_FILE_STREAM_INFO:
4112 case SMB_FILE_STREAM_INFORMATION:
4113 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4117 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4118 SIVAL(pdata,0,0); /* ??? */
4119 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4120 SOFF_T(pdata,8,file_size);
4121 SOFF_T(pdata,16,allocation_size);
4122 data_size = 24 + byte_len;
4126 case SMB_QUERY_COMPRESSION_INFO:
4127 case SMB_FILE_COMPRESSION_INFORMATION:
4128 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4129 SOFF_T(pdata,0,file_size);
4130 SIVAL(pdata,8,0); /* ??? */
4131 SIVAL(pdata,12,0); /* ??? */
4135 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4136 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4137 put_long_date_timespec(pdata,create_time_ts);
4138 put_long_date_timespec(pdata+8,atime_ts);
4139 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4140 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4141 SOFF_T(pdata,32,allocation_size);
4142 SOFF_T(pdata,40,file_size);
4143 SIVAL(pdata,48,mode);
4144 SIVAL(pdata,52,0); /* ??? */
4148 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4149 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4150 SIVAL(pdata,0,mode);
4156 * CIFS UNIX Extensions.
4159 case SMB_QUERY_FILE_UNIX_BASIC:
4161 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4162 data_size = PTR_DIFF(pdata,(*ppdata));
4166 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4168 for (i=0; i<100; i++)
4169 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4175 case SMB_QUERY_FILE_UNIX_INFO2:
4177 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4178 data_size = PTR_DIFF(pdata,(*ppdata));
4182 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4184 for (i=0; i<100; i++)
4185 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4191 case SMB_QUERY_FILE_UNIX_LINK:
4195 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4197 if(!S_ISLNK(sbuf.st_mode)) {
4198 reply_unixerror(req, ERRSRV,
4203 reply_unixerror(req, ERRDOS, ERRbadlink);
4206 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
4208 reply_unixerror(req, ERRDOS,
4213 len = srvstr_push(dstart, req->flags2,
4215 PTR_DIFF(dend, pdata),
4218 data_size = PTR_DIFF(pdata,(*ppdata));
4223 #if defined(HAVE_POSIX_ACLS)
4224 case SMB_QUERY_POSIX_ACL:
4226 SMB_ACL_T file_acl = NULL;
4227 SMB_ACL_T def_acl = NULL;
4228 uint16 num_file_acls = 0;
4229 uint16 num_def_acls = 0;
4231 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4232 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4234 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4237 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4238 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4242 NT_STATUS_NOT_IMPLEMENTED);
4246 if (S_ISDIR(sbuf.st_mode)) {
4247 if (fsp && fsp->is_directory) {
4248 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4250 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4252 def_acl = free_empty_sys_acl(conn, def_acl);
4255 num_file_acls = count_acl_entries(conn, file_acl);
4256 num_def_acls = count_acl_entries(conn, def_acl);
4258 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4259 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4261 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4262 SMB_POSIX_ACL_HEADER_SIZE) ));
4264 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4267 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4271 NT_STATUS_BUFFER_TOO_SMALL);
4275 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4276 SSVAL(pdata,2,num_file_acls);
4277 SSVAL(pdata,4,num_def_acls);
4278 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4280 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4283 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4286 req, NT_STATUS_INTERNAL_ERROR);
4289 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4291 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4294 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4298 NT_STATUS_INTERNAL_ERROR);
4303 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4306 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4308 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4314 case SMB_QUERY_POSIX_LOCK:
4316 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4318 SMB_BIG_UINT offset;
4320 enum brl_type lock_type;
4322 if (total_data != POSIX_LOCK_DATA_SIZE) {
4324 req, NT_STATUS_INVALID_PARAMETER);
4328 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4329 case POSIX_LOCK_TYPE_READ:
4330 lock_type = READ_LOCK;
4332 case POSIX_LOCK_TYPE_WRITE:
4333 lock_type = WRITE_LOCK;
4335 case POSIX_LOCK_TYPE_UNLOCK:
4337 /* There's no point in asking for an unlock... */
4338 talloc_destroy(data_ctx);
4341 NT_STATUS_INVALID_PARAMETER);
4345 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4346 #if defined(HAVE_LONGLONG)
4347 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4348 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4349 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4350 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4351 #else /* HAVE_LONGLONG */
4352 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4353 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4354 #endif /* HAVE_LONGLONG */
4356 status = query_lock(fsp,
4363 if (ERROR_WAS_LOCK_DENIED(status)) {
4364 /* Here we need to report who has it locked... */
4365 data_size = POSIX_LOCK_DATA_SIZE;
4367 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4368 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4369 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4370 #if defined(HAVE_LONGLONG)
4371 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4372 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4373 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4374 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4375 #else /* HAVE_LONGLONG */
4376 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4377 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4378 #endif /* HAVE_LONGLONG */
4380 } else if (NT_STATUS_IS_OK(status)) {
4381 /* For success we just return a copy of what we sent
4382 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4383 data_size = POSIX_LOCK_DATA_SIZE;
4384 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4385 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4387 reply_nterror(req, status);
4394 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4398 send_trans2_replies(req, params, param_size, *ppdata, data_size,
4404 /****************************************************************************
4405 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4407 ****************************************************************************/
4409 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4411 SMB_STRUCT_STAT sbuf1, sbuf2;
4412 pstring last_component_oldname;
4413 pstring last_component_newname;
4414 NTSTATUS status = NT_STATUS_OK;
4419 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4420 if (!NT_STATUS_IS_OK(status)) {
4424 status = check_name(conn, oldname);
4425 if (!NT_STATUS_IS_OK(status)) {
4429 /* source must already exist. */
4430 if (!VALID_STAT(sbuf1)) {
4431 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4434 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4435 if (!NT_STATUS_IS_OK(status)) {
4439 status = check_name(conn, newname);
4440 if (!NT_STATUS_IS_OK(status)) {
4444 /* Disallow if newname already exists. */
4445 if (VALID_STAT(sbuf2)) {
4446 return NT_STATUS_OBJECT_NAME_COLLISION;
4449 /* No links from a directory. */
4450 if (S_ISDIR(sbuf1.st_mode)) {
4451 return NT_STATUS_FILE_IS_A_DIRECTORY;
4454 /* Ensure this is within the share. */
4455 status = check_reduced_name(conn, oldname);
4456 if (!NT_STATUS_IS_OK(status)) {
4460 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4462 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4463 status = map_nt_error_from_unix(errno);
4464 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4465 nt_errstr(status), newname, oldname));
4471 /****************************************************************************
4472 Deal with setting the time from any of the setfilepathinfo functions.
4473 ****************************************************************************/
4475 static NTSTATUS smb_set_file_time(connection_struct *conn,
4478 const SMB_STRUCT_STAT *psbuf,
4479 struct timespec ts[2])
4482 FILE_NOTIFY_CHANGE_LAST_ACCESS
4483 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4486 if (!VALID_STAT(*psbuf)) {
4487 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4490 /* get some defaults (no modifications) if any info is zero or -1. */
4491 if (null_timespec(ts[0])) {
4492 ts[0] = get_atimespec(psbuf);
4493 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4496 if (null_timespec(ts[1])) {
4497 ts[1] = get_mtimespec(psbuf);
4498 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4501 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4502 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4505 * Try and set the times of this file if
4506 * they are different from the current values.
4510 struct timespec mts = get_mtimespec(psbuf);
4511 struct timespec ats = get_atimespec(psbuf);
4512 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4513 return NT_STATUS_OK;
4519 * This was a setfileinfo on an open file.
4520 * NT does this a lot. We also need to
4521 * set the time here, as it can be read by
4522 * FindFirst/FindNext and with the patch for bug #2045
4523 * in smbd/fileio.c it ensures that this timestamp is
4524 * kept sticky even after a write. We save the request
4525 * away and will set it on file close and after a write. JRA.
4528 if (!null_timespec(ts[1])) {
4529 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4530 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4531 fsp_set_pending_modtime(fsp, ts[1]);
4535 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4537 if(file_ntimes(conn, fname, ts)!=0) {
4538 return map_nt_error_from_unix(errno);
4541 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4543 return NT_STATUS_OK;
4546 /****************************************************************************
4547 Deal with setting the dosmode from any of the setfilepathinfo functions.
4548 ****************************************************************************/
4550 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4552 SMB_STRUCT_STAT *psbuf,
4555 if (!VALID_STAT(*psbuf)) {
4556 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4560 if (S_ISDIR(psbuf->st_mode)) {
4567 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4569 /* check the mode isn't different, before changing it */
4570 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4572 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4573 fname, (unsigned int)dosmode ));
4575 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4576 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4577 fname, strerror(errno)));
4578 return map_nt_error_from_unix(errno);
4581 return NT_STATUS_OK;
4584 /****************************************************************************
4585 Deal with setting the size from any of the setfilepathinfo functions.
4586 ****************************************************************************/
4588 static NTSTATUS smb_set_file_size(connection_struct *conn,
4589 struct smb_request *req,
4592 SMB_STRUCT_STAT *psbuf,
4595 NTSTATUS status = NT_STATUS_OK;
4596 files_struct *new_fsp = NULL;
4598 if (!VALID_STAT(*psbuf)) {
4599 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4602 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4604 if (size == get_file_size(*psbuf)) {
4605 return NT_STATUS_OK;
4608 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4609 fname, (double)size ));
4611 if (fsp && fsp->fh->fd != -1) {
4612 /* Handle based call. */
4613 if (vfs_set_filelen(fsp, size) == -1) {
4614 return map_nt_error_from_unix(errno);
4616 return NT_STATUS_OK;
4619 status = open_file_ntcreate(conn, req, fname, psbuf,
4621 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4624 FILE_ATTRIBUTE_NORMAL,
4625 FORCE_OPLOCK_BREAK_TO_NONE,
4628 if (!NT_STATUS_IS_OK(status)) {
4629 /* NB. We check for open_was_deferred in the caller. */
4633 if (vfs_set_filelen(new_fsp, size) == -1) {
4634 status = map_nt_error_from_unix(errno);
4635 close_file(new_fsp,NORMAL_CLOSE);
4639 close_file(new_fsp,NORMAL_CLOSE);
4640 return NT_STATUS_OK;
4643 /****************************************************************************
4644 Deal with SMB_INFO_SET_EA.
4645 ****************************************************************************/
4647 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4653 struct ea_list *ea_list = NULL;
4654 TALLOC_CTX *ctx = NULL;
4655 NTSTATUS status = NT_STATUS_OK;
4657 if (total_data < 10) {
4659 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4660 length. They seem to have no effect. Bug #3212. JRA */
4662 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4663 /* We're done. We only get EA info in this call. */
4664 return NT_STATUS_OK;
4667 return NT_STATUS_INVALID_PARAMETER;
4670 if (IVAL(pdata,0) > total_data) {
4671 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4672 IVAL(pdata,0), (unsigned int)total_data));
4673 return NT_STATUS_INVALID_PARAMETER;
4676 ctx = talloc_init("SMB_INFO_SET_EA");
4678 return NT_STATUS_NO_MEMORY;
4680 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4682 talloc_destroy(ctx);
4683 return NT_STATUS_INVALID_PARAMETER;
4685 status = set_ea(conn, fsp, fname, ea_list);
4686 talloc_destroy(ctx);
4691 /****************************************************************************
4692 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4693 ****************************************************************************/
4695 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4700 SMB_STRUCT_STAT *psbuf)
4702 NTSTATUS status = NT_STATUS_OK;
4703 BOOL delete_on_close;
4706 if (total_data < 1) {
4707 return NT_STATUS_INVALID_PARAMETER;
4711 return NT_STATUS_INVALID_HANDLE;
4714 delete_on_close = (CVAL(pdata,0) ? True : False);
4715 dosmode = dos_mode(conn, fname, psbuf);
4717 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4718 "delete_on_close = %u\n",
4720 (unsigned int)dosmode,
4721 (unsigned int)delete_on_close ));
4723 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4725 if (!NT_STATUS_IS_OK(status)) {
4729 /* The set is across all open files on this dev/inode pair. */
4730 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4731 return NT_STATUS_ACCESS_DENIED;
4733 return NT_STATUS_OK;
4736 /****************************************************************************
4737 Deal with SMB_FILE_POSITION_INFORMATION.
4738 ****************************************************************************/
4740 static NTSTATUS smb_file_position_information(connection_struct *conn,
4745 SMB_BIG_UINT position_information;
4747 if (total_data < 8) {
4748 return NT_STATUS_INVALID_PARAMETER;
4752 /* Ignore on pathname based set. */
4753 return NT_STATUS_OK;
4756 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4757 #ifdef LARGE_SMB_OFF_T
4758 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4759 #else /* LARGE_SMB_OFF_T */
4760 if (IVAL(pdata,4) != 0) {
4761 /* more than 32 bits? */
4762 return NT_STATUS_INVALID_PARAMETER;
4764 #endif /* LARGE_SMB_OFF_T */
4766 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4767 fsp->fsp_name, (double)position_information ));
4768 fsp->fh->position_information = position_information;
4769 return NT_STATUS_OK;
4772 /****************************************************************************
4773 Deal with SMB_FILE_MODE_INFORMATION.
4774 ****************************************************************************/
4776 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4782 if (total_data < 4) {
4783 return NT_STATUS_INVALID_PARAMETER;
4785 mode = IVAL(pdata,0);
4786 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4787 return NT_STATUS_INVALID_PARAMETER;
4789 return NT_STATUS_OK;
4792 /****************************************************************************
4793 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4794 ****************************************************************************/
4796 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4797 struct smb_request *req,
4802 pstring link_target;
4803 const char *newname = fname;
4804 NTSTATUS status = NT_STATUS_OK;
4806 /* Set a symbolic link. */
4807 /* Don't allow this if follow links is false. */
4809 if (total_data == 0) {
4810 return NT_STATUS_INVALID_PARAMETER;
4813 if (!lp_symlinks(SNUM(conn))) {
4814 return NT_STATUS_ACCESS_DENIED;
4817 srvstr_pull(pdata, req->flags2, link_target, pdata,
4818 sizeof(link_target), total_data, STR_TERMINATE);
4820 /* !widelinks forces the target path to be within the share. */
4821 /* This means we can interpret the target as a pathname. */
4822 if (!lp_widelinks(SNUM(conn))) {
4824 char *last_dirp = NULL;
4826 if (*link_target == '/') {
4827 /* No absolute paths allowed. */
4828 return NT_STATUS_ACCESS_DENIED;
4830 pstrcpy(rel_name, newname);
4831 last_dirp = strrchr_m(rel_name, '/');
4833 last_dirp[1] = '\0';
4835 pstrcpy(rel_name, "./");
4837 pstrcat(rel_name, link_target);
4839 status = check_name(conn, rel_name);
4840 if (!NT_STATUS_IS_OK(status)) {
4845 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4846 newname, link_target ));
4848 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4849 return map_nt_error_from_unix(errno);
4852 return NT_STATUS_OK;
4855 /****************************************************************************
4856 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4857 ****************************************************************************/
4859 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4860 struct smb_request *req,
4861 const char *pdata, int total_data,
4865 NTSTATUS status = NT_STATUS_OK;
4867 /* Set a hard link. */
4868 if (total_data == 0) {
4869 return NT_STATUS_INVALID_PARAMETER;
4872 srvstr_get_path(pdata, req->flags2, oldname, pdata,
4873 sizeof(oldname), total_data, STR_TERMINATE, &status);
4874 if (!NT_STATUS_IS_OK(status)) {
4878 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
4880 if (!NT_STATUS_IS_OK(status)) {
4884 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4887 return hardlink_internals(conn, oldname, fname);
4890 /****************************************************************************
4891 Deal with SMB_FILE_RENAME_INFORMATION.
4892 ****************************************************************************/
4894 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4895 struct smb_request *req,
4896 const char *pdata, int total_data,
4897 files_struct *fsp, pstring fname)
4904 BOOL dest_has_wcard = False;
4905 NTSTATUS status = NT_STATUS_OK;
4908 if (total_data < 13) {
4909 return NT_STATUS_INVALID_PARAMETER;
4912 overwrite = (CVAL(pdata,0) ? True : False);
4913 root_fid = IVAL(pdata,4);
4914 len = IVAL(pdata,8);
4916 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4917 return NT_STATUS_INVALID_PARAMETER;
4920 srvstr_get_path_wcard(pdata, req->flags2, newname, &pdata[12],
4921 sizeof(newname), len, 0, &status,
4923 if (!NT_STATUS_IS_OK(status)) {
4927 status = resolve_dfspath_wcard(conn,
4928 req->flags2 & FLAGS2_DFS_PATHNAMES,
4929 newname, &dest_has_wcard);
4930 if (!NT_STATUS_IS_OK(status)) {
4934 /* Check the new name has no '/' characters. */
4935 if (strchr_m(newname, '/')) {
4936 return NT_STATUS_NOT_SUPPORTED;
4939 /* Create the base directory. */
4940 pstrcpy(base_name, fname);
4941 p = strrchr_m(base_name, '/');
4945 pstrcpy(base_name, "./");
4947 /* Append the new name. */
4948 pstrcat(base_name, newname);
4951 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4952 fsp->fnum, fsp->fsp_name, base_name ));
4953 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4955 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4957 status = rename_internals(conn, req, fname, base_name, 0,
4958 overwrite, False, dest_has_wcard);
4964 /****************************************************************************
4965 Deal with SMB_SET_POSIX_ACL.
4966 ****************************************************************************/
4968 #if defined(HAVE_POSIX_ACLS)
4969 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4974 SMB_STRUCT_STAT *psbuf)
4976 uint16 posix_acl_version;
4977 uint16 num_file_acls;
4978 uint16 num_def_acls;
4979 BOOL valid_file_acls = True;
4980 BOOL valid_def_acls = True;
4982 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4983 return NT_STATUS_INVALID_PARAMETER;
4985 posix_acl_version = SVAL(pdata,0);
4986 num_file_acls = SVAL(pdata,2);
4987 num_def_acls = SVAL(pdata,4);
4989 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4990 valid_file_acls = False;
4994 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4995 valid_def_acls = False;
4999 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5000 return NT_STATUS_INVALID_PARAMETER;
5003 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5004 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5005 return NT_STATUS_INVALID_PARAMETER;
5008 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5009 fname ? fname : fsp->fsp_name,
5010 (unsigned int)num_file_acls,
5011 (unsigned int)num_def_acls));
5013 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5014 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5015 return map_nt_error_from_unix(errno);
5018 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5019 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5020 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5021 return map_nt_error_from_unix(errno);
5023 return NT_STATUS_OK;
5027 /****************************************************************************
5028 Deal with SMB_SET_POSIX_LOCK.
5029 ****************************************************************************/
5031 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5039 SMB_BIG_UINT offset;
5041 BOOL blocking_lock = False;
5042 enum brl_type lock_type;
5043 NTSTATUS status = NT_STATUS_OK;
5045 if (fsp == NULL || fsp->fh->fd == -1) {
5046 return NT_STATUS_INVALID_HANDLE;
5049 if (total_data != POSIX_LOCK_DATA_SIZE) {
5050 return NT_STATUS_INVALID_PARAMETER;
5053 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5054 case POSIX_LOCK_TYPE_READ:
5055 lock_type = READ_LOCK;
5057 case POSIX_LOCK_TYPE_WRITE:
5058 /* Return the right POSIX-mappable error code for files opened read-only. */
5059 if (!fsp->can_write) {
5060 return NT_STATUS_INVALID_HANDLE;
5062 lock_type = WRITE_LOCK;
5064 case POSIX_LOCK_TYPE_UNLOCK:
5065 lock_type = UNLOCK_LOCK;
5068 return NT_STATUS_INVALID_PARAMETER;
5071 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5072 blocking_lock = False;
5073 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5074 blocking_lock = True;
5076 return NT_STATUS_INVALID_PARAMETER;
5079 if (!lp_blocking_locks(SNUM(conn))) {
5080 blocking_lock = False;
5083 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5084 #if defined(HAVE_LONGLONG)
5085 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5086 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5087 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5088 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5089 #else /* HAVE_LONGLONG */
5090 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5091 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5092 #endif /* HAVE_LONGLONG */
5094 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5095 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5097 (unsigned int)lock_type,
5098 (unsigned int)lock_pid,
5102 if (lock_type == UNLOCK_LOCK) {
5103 status = do_unlock(smbd_messaging_context(),
5110 uint32 block_smbpid;
5112 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5123 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5125 * A blocking lock was requested. Package up
5126 * this smb into a queued request and push it
5127 * onto the blocking lock queue.
5129 if(push_blocking_lock_request(br_lck,
5130 (char *)inbuf, length,
5132 -1, /* infinite timeout. */
5140 TALLOC_FREE(br_lck);
5144 TALLOC_FREE(br_lck);
5150 /****************************************************************************
5151 Deal with SMB_INFO_STANDARD.
5152 ****************************************************************************/
5154 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5159 const SMB_STRUCT_STAT *psbuf)
5161 struct timespec ts[2];
5163 if (total_data < 12) {
5164 return NT_STATUS_INVALID_PARAMETER;
5168 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5170 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5172 DEBUG(10,("smb_set_info_standard: file %s\n",
5173 fname ? fname : fsp->fsp_name ));
5175 return smb_set_file_time(conn,
5182 /****************************************************************************
5183 Deal with SMB_SET_FILE_BASIC_INFO.
5184 ****************************************************************************/
5186 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5191 SMB_STRUCT_STAT *psbuf)
5193 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5194 struct timespec write_time;
5195 struct timespec changed_time;
5197 struct timespec ts[2];
5198 NTSTATUS status = NT_STATUS_OK;
5200 if (total_data < 36) {
5201 return NT_STATUS_INVALID_PARAMETER;
5204 /* Set the attributes */
5205 dosmode = IVAL(pdata,32);
5206 status = smb_set_file_dosmode(conn,
5210 if (!NT_STATUS_IS_OK(status)) {
5214 /* Ignore create time at offset pdata. */
5217 ts[0] = interpret_long_date(pdata+8);
5219 write_time = interpret_long_date(pdata+16);
5220 changed_time = interpret_long_date(pdata+24);
5223 ts[1] = timespec_min(&write_time, &changed_time);
5225 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5229 /* Prefer a defined time to an undefined one. */
5230 if (null_timespec(ts[1])) {
5231 ts[1] = null_timespec(write_time) ? changed_time : write_time;
5234 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5235 fname ? fname : fsp->fsp_name ));
5237 return smb_set_file_time(conn,
5244 /****************************************************************************
5245 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5246 ****************************************************************************/
5248 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5249 struct smb_request *req,
5254 SMB_STRUCT_STAT *psbuf)
5256 SMB_BIG_UINT allocation_size = 0;
5257 NTSTATUS status = NT_STATUS_OK;
5258 files_struct *new_fsp = NULL;
5260 if (!VALID_STAT(*psbuf)) {
5261 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5264 if (total_data < 8) {
5265 return NT_STATUS_INVALID_PARAMETER;
5268 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5269 #ifdef LARGE_SMB_OFF_T
5270 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5271 #else /* LARGE_SMB_OFF_T */
5272 if (IVAL(pdata,4) != 0) {
5273 /* more than 32 bits? */
5274 return NT_STATUS_INVALID_PARAMETER;
5276 #endif /* LARGE_SMB_OFF_T */
5278 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5279 fname, (double)allocation_size ));
5281 if (allocation_size) {
5282 allocation_size = smb_roundup(conn, allocation_size);
5285 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5286 fname, (double)allocation_size ));
5288 if (fsp && fsp->fh->fd != -1) {
5289 /* Open file handle. */
5290 /* Only change if needed. */
5291 if (allocation_size != get_file_size(*psbuf)) {
5292 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5293 return map_nt_error_from_unix(errno);
5296 /* But always update the time. */
5297 if (null_timespec(fsp->pending_modtime)) {
5299 * This is equivalent to a write. Ensure it's seen immediately
5300 * if there are no pending writes.
5302 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
5304 return NT_STATUS_OK;
5307 /* Pathname or stat or directory file. */
5309 status = open_file_ntcreate(conn, req, fname, psbuf,
5311 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5314 FILE_ATTRIBUTE_NORMAL,
5315 FORCE_OPLOCK_BREAK_TO_NONE,
5318 if (!NT_STATUS_IS_OK(status)) {
5319 /* NB. We check for open_was_deferred in the caller. */
5323 /* Only change if needed. */
5324 if (allocation_size != get_file_size(*psbuf)) {
5325 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5326 status = map_nt_error_from_unix(errno);
5327 close_file(new_fsp,NORMAL_CLOSE);
5332 /* Changing the allocation size should set the last mod time. */
5333 /* Don't need to call set_filetime as this will be flushed on
5336 fsp_set_pending_modtime(new_fsp, timespec_current());
5338 close_file(new_fsp,NORMAL_CLOSE);
5339 return NT_STATUS_OK;
5342 /****************************************************************************
5343 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5344 ****************************************************************************/
5346 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5347 struct smb_request *req,
5352 SMB_STRUCT_STAT *psbuf)
5356 if (total_data < 8) {
5357 return NT_STATUS_INVALID_PARAMETER;
5360 size = IVAL(pdata,0);
5361 #ifdef LARGE_SMB_OFF_T
5362 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5363 #else /* LARGE_SMB_OFF_T */
5364 if (IVAL(pdata,4) != 0) {
5365 /* more than 32 bits? */
5366 return NT_STATUS_INVALID_PARAMETER;
5368 #endif /* LARGE_SMB_OFF_T */
5369 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5370 "file %s to %.0f\n", fname, (double)size ));
5372 return smb_set_file_size(conn, req,
5379 /****************************************************************************
5380 Allow a UNIX info mknod.
5381 ****************************************************************************/
5383 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5387 SMB_STRUCT_STAT *psbuf)
5389 uint32 file_type = IVAL(pdata,56);
5390 #if defined(HAVE_MAKEDEV)
5391 uint32 dev_major = IVAL(pdata,60);
5392 uint32 dev_minor = IVAL(pdata,68);
5394 SMB_DEV_T dev = (SMB_DEV_T)0;
5395 uint32 raw_unixmode = IVAL(pdata,84);
5399 if (total_data < 100) {
5400 return NT_STATUS_INVALID_PARAMETER;
5403 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5404 if (!NT_STATUS_IS_OK(status)) {
5408 #if defined(HAVE_MAKEDEV)
5409 dev = makedev(dev_major, dev_minor);
5412 switch (file_type) {
5413 #if defined(S_IFIFO)
5414 case UNIX_TYPE_FIFO:
5415 unixmode |= S_IFIFO;
5418 #if defined(S_IFSOCK)
5419 case UNIX_TYPE_SOCKET:
5420 unixmode |= S_IFSOCK;
5423 #if defined(S_IFCHR)
5424 case UNIX_TYPE_CHARDEV:
5425 unixmode |= S_IFCHR;
5428 #if defined(S_IFBLK)
5429 case UNIX_TYPE_BLKDEV:
5430 unixmode |= S_IFBLK;
5434 return NT_STATUS_INVALID_PARAMETER;
5437 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5438 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5440 /* Ok - do the mknod. */
5441 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5442 return map_nt_error_from_unix(errno);
5445 /* If any of the other "set" calls fail we
5446 * don't want to end up with a half-constructed mknod.
5449 if (lp_inherit_perms(SNUM(conn))) {
5451 conn, parent_dirname(fname),
5455 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5456 status = map_nt_error_from_unix(errno);
5457 SMB_VFS_UNLINK(conn,fname);
5460 return NT_STATUS_OK;
5463 /****************************************************************************
5464 Deal with SMB_SET_FILE_UNIX_BASIC.
5465 ****************************************************************************/
5467 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5468 struct smb_request *req,
5473 SMB_STRUCT_STAT *psbuf)
5475 struct timespec ts[2];
5476 uint32 raw_unixmode;
5479 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5480 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5481 NTSTATUS status = NT_STATUS_OK;
5482 BOOL delete_on_fail = False;
5483 enum perm_type ptype;
5485 if (total_data < 100) {
5486 return NT_STATUS_INVALID_PARAMETER;
5489 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5490 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5491 size=IVAL(pdata,0); /* first 8 Bytes are size */
5492 #ifdef LARGE_SMB_OFF_T
5493 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5494 #else /* LARGE_SMB_OFF_T */
5495 if (IVAL(pdata,4) != 0) {
5496 /* more than 32 bits? */
5497 return NT_STATUS_INVALID_PARAMETER;
5499 #endif /* LARGE_SMB_OFF_T */
5502 ts[0] = interpret_long_date(pdata+24); /* access_time */
5503 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5504 set_owner = (uid_t)IVAL(pdata,40);
5505 set_grp = (gid_t)IVAL(pdata,48);
5506 raw_unixmode = IVAL(pdata,84);
5508 if (VALID_STAT(*psbuf)) {
5509 if (S_ISDIR(psbuf->st_mode)) {
5510 ptype = PERM_EXISTING_DIR;
5512 ptype = PERM_EXISTING_FILE;
5515 ptype = PERM_NEW_FILE;
5518 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5519 if (!NT_STATUS_IS_OK(status)) {
5523 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5524 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5525 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5527 if (!VALID_STAT(*psbuf)) {
5529 * The only valid use of this is to create character and block
5530 * devices, and named pipes. This is deprecated (IMHO) and
5531 * a new info level should be used for mknod. JRA.
5534 status = smb_unix_mknod(conn,
5539 if (!NT_STATUS_IS_OK(status)) {
5543 /* Ensure we don't try and change anything else. */
5544 raw_unixmode = SMB_MODE_NO_CHANGE;
5545 size = get_file_size(*psbuf);
5546 ts[0] = get_atimespec(psbuf);
5547 ts[1] = get_mtimespec(psbuf);
5549 * We continue here as we might want to change the
5552 delete_on_fail = True;
5556 /* Horrible backwards compatibility hack as an old server bug
5557 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5561 size = get_file_size(*psbuf);
5566 * Deal with the UNIX specific mode set.
5569 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5570 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5571 (unsigned int)unixmode, fname ));
5572 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5573 return map_nt_error_from_unix(errno);
5578 * Deal with the UNIX specific uid set.
5581 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5584 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5585 (unsigned int)set_owner, fname ));
5587 if (S_ISLNK(psbuf->st_mode)) {
5588 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5590 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5594 status = map_nt_error_from_unix(errno);
5595 if (delete_on_fail) {
5596 SMB_VFS_UNLINK(conn,fname);
5603 * Deal with the UNIX specific gid set.
5606 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5607 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5608 (unsigned int)set_owner, fname ));
5609 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5610 status = map_nt_error_from_unix(errno);
5611 if (delete_on_fail) {
5612 SMB_VFS_UNLINK(conn,fname);
5618 /* Deal with any size changes. */
5620 status = smb_set_file_size(conn, req,
5625 if (!NT_STATUS_IS_OK(status)) {
5629 /* Deal with any time changes. */
5631 return smb_set_file_time(conn,
5638 /****************************************************************************
5639 Deal with SMB_SET_FILE_UNIX_INFO2.
5640 ****************************************************************************/
5642 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5643 struct smb_request *req,
5648 SMB_STRUCT_STAT *psbuf)
5654 if (total_data < 116) {
5655 return NT_STATUS_INVALID_PARAMETER;
5658 /* Start by setting all the fields that are common between UNIX_BASIC
5661 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5663 if (!NT_STATUS_IS_OK(status)) {
5667 smb_fflags = IVAL(pdata, 108);
5668 smb_fmask = IVAL(pdata, 112);
5670 /* NB: We should only attempt to alter the file flags if the client
5671 * sends a non-zero mask.
5673 if (smb_fmask != 0) {
5674 int stat_fflags = 0;
5676 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5678 /* Client asked to alter a flag we don't understand. */
5679 return NT_STATUS_INVALID_PARAMETER;
5682 if (fsp && fsp->fh->fd != -1) {
5683 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5684 return NT_STATUS_NOT_SUPPORTED;
5686 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5687 return map_nt_error_from_unix(errno);
5692 /* XXX: need to add support for changing the create_time here. You
5693 * can do this for paths on Darwin with setattrlist(2). The right way
5694 * to hook this up is probably by extending the VFS utimes interface.
5697 return NT_STATUS_OK;
5700 /****************************************************************************
5701 Create a directory with POSIX semantics.
5702 ****************************************************************************/
5704 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5705 struct smb_request *req,
5709 SMB_STRUCT_STAT *psbuf,
5710 int *pdata_return_size)
5712 NTSTATUS status = NT_STATUS_OK;
5713 uint32 raw_unixmode = 0;
5714 uint32 mod_unixmode = 0;
5715 mode_t unixmode = (mode_t)0;
5716 files_struct *fsp = NULL;
5717 uint16 info_level_return = 0;
5719 char *pdata = *ppdata;
5721 if (total_data < 18) {
5722 return NT_STATUS_INVALID_PARAMETER;
5725 raw_unixmode = IVAL(pdata,8);
5726 /* Next 4 bytes are not yet defined. */
5728 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5729 if (!NT_STATUS_IS_OK(status)) {
5733 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5735 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5736 fname, (unsigned int)unixmode ));
5738 status = open_directory(conn, req,
5741 FILE_READ_ATTRIBUTES, /* Just a stat open */
5742 FILE_SHARE_NONE, /* Ignored for stat opens */
5749 if (NT_STATUS_IS_OK(status)) {
5750 close_file(fsp, NORMAL_CLOSE);
5753 info_level_return = SVAL(pdata,16);
5755 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5756 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5757 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5758 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5760 *pdata_return_size = 12;
5763 /* Realloc the data size */
5764 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5765 if (*ppdata == NULL) {
5766 *pdata_return_size = 0;
5767 return NT_STATUS_NO_MEMORY;
5771 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5772 SSVAL(pdata,2,0); /* No fnum. */
5773 SIVAL(pdata,4,info); /* Was directory created. */
5775 switch (info_level_return) {
5776 case SMB_QUERY_FILE_UNIX_BASIC:
5777 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5778 SSVAL(pdata,10,0); /* Padding. */
5779 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5781 case SMB_QUERY_FILE_UNIX_INFO2:
5782 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5783 SSVAL(pdata,10,0); /* Padding. */
5784 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5787 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5788 SSVAL(pdata,10,0); /* Padding. */
5795 /****************************************************************************
5796 Open/Create a file with POSIX semantics.
5797 ****************************************************************************/
5799 static NTSTATUS smb_posix_open(connection_struct *conn,
5800 struct smb_request *req,
5804 SMB_STRUCT_STAT *psbuf,
5805 int *pdata_return_size)
5807 BOOL extended_oplock_granted = False;
5808 char *pdata = *ppdata;
5810 uint32 wire_open_mode = 0;
5811 uint32 raw_unixmode = 0;
5812 uint32 mod_unixmode = 0;
5813 uint32 create_disp = 0;
5814 uint32 access_mask = 0;
5815 uint32 create_options = 0;
5816 NTSTATUS status = NT_STATUS_OK;
5817 mode_t unixmode = (mode_t)0;
5818 files_struct *fsp = NULL;
5819 int oplock_request = 0;
5821 uint16 info_level_return = 0;
5823 if (total_data < 18) {
5824 return NT_STATUS_INVALID_PARAMETER;
5827 flags = IVAL(pdata,0);
5828 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5829 if (oplock_request) {
5830 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5833 wire_open_mode = IVAL(pdata,4);
5835 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5836 return smb_posix_mkdir(conn, req,
5844 switch (wire_open_mode & SMB_ACCMODE) {
5846 access_mask = FILE_READ_DATA;
5849 access_mask = FILE_WRITE_DATA;
5852 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5855 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5856 (unsigned int)wire_open_mode ));
5857 return NT_STATUS_INVALID_PARAMETER;
5860 wire_open_mode &= ~SMB_ACCMODE;
5862 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5863 create_disp = FILE_CREATE;
5864 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5865 create_disp = FILE_OVERWRITE_IF;
5866 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5867 create_disp = FILE_OPEN_IF;
5869 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5870 (unsigned int)wire_open_mode ));
5871 return NT_STATUS_INVALID_PARAMETER;
5874 raw_unixmode = IVAL(pdata,8);
5875 /* Next 4 bytes are not yet defined. */
5877 status = unix_perms_from_wire(conn,
5880 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5883 if (!NT_STATUS_IS_OK(status)) {
5887 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5889 if (wire_open_mode & SMB_O_SYNC) {
5890 create_options |= FILE_WRITE_THROUGH;
5892 if (wire_open_mode & SMB_O_APPEND) {
5893 access_mask |= FILE_APPEND_DATA;
5895 if (wire_open_mode & SMB_O_DIRECT) {
5896 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5899 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5901 (unsigned int)wire_open_mode,
5902 (unsigned int)unixmode ));
5904 status = open_file_ntcreate(conn, req,
5908 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5910 0, /* no create options yet. */
5916 if (!NT_STATUS_IS_OK(status)) {
5920 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5921 extended_oplock_granted = True;
5924 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5925 extended_oplock_granted = True;
5928 info_level_return = SVAL(pdata,16);
5930 /* Allocate the correct return size. */
5932 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5933 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5934 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5935 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5937 *pdata_return_size = 12;
5940 /* Realloc the data size */
5941 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5942 if (*ppdata == NULL) {
5943 close_file(fsp,ERROR_CLOSE);
5944 *pdata_return_size = 0;
5945 return NT_STATUS_NO_MEMORY;
5949 if (extended_oplock_granted) {
5950 if (flags & REQUEST_BATCH_OPLOCK) {
5951 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5953 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5955 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5956 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5958 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5961 SSVAL(pdata,2,fsp->fnum);
5962 SIVAL(pdata,4,info); /* Was file created etc. */
5964 switch (info_level_return) {
5965 case SMB_QUERY_FILE_UNIX_BASIC:
5966 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5967 SSVAL(pdata,10,0); /* padding. */
5968 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5970 case SMB_QUERY_FILE_UNIX_INFO2:
5971 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5972 SSVAL(pdata,10,0); /* padding. */
5973 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5976 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5977 SSVAL(pdata,10,0); /* padding. */
5980 return NT_STATUS_OK;
5983 /****************************************************************************
5984 Delete a file with POSIX semantics.
5985 ****************************************************************************/
5987 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5988 struct smb_request *req,
5992 SMB_STRUCT_STAT *psbuf)
5994 NTSTATUS status = NT_STATUS_OK;
5995 files_struct *fsp = NULL;
6000 struct share_mode_lock *lck = NULL;
6002 if (total_data < 2) {
6003 return NT_STATUS_INVALID_PARAMETER;
6006 flags = SVAL(pdata,0);
6008 if (!VALID_STAT(*psbuf)) {
6009 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6012 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6013 !VALID_STAT_OF_DIR(*psbuf)) {
6014 return NT_STATUS_NOT_A_DIRECTORY;
6017 DEBUG(10,("smb_posix_unlink: %s %s\n",
6018 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6021 if (VALID_STAT_OF_DIR(*psbuf)) {
6022 status = open_directory(conn, req,
6026 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6029 FILE_FLAG_POSIX_SEMANTICS|0777,
6034 status = open_file_ntcreate(conn, req,
6038 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6041 FILE_FLAG_POSIX_SEMANTICS|0777,
6042 0, /* No oplock, but break existing ones. */
6047 if (!NT_STATUS_IS_OK(status)) {
6052 * Don't lie to client. If we can't really delete due to
6053 * non-POSIX opens return SHARING_VIOLATION.
6056 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
6058 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6059 "lock for file %s\n", fsp->fsp_name));
6060 close_file(fsp, NORMAL_CLOSE);
6061 return NT_STATUS_INVALID_PARAMETER;
6065 * See if others still have the file open. If this is the case, then
6066 * don't delete. If all opens are POSIX delete we can set the delete
6067 * on close disposition.
6069 for (i=0; i<lck->num_share_modes; i++) {
6070 struct share_mode_entry *e = &lck->share_modes[i];
6071 if (is_valid_share_mode_entry(e)) {
6072 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6075 /* Fail with sharing violation. */
6076 close_file(fsp, NORMAL_CLOSE);
6078 return NT_STATUS_SHARING_VIOLATION;
6083 * Set the delete on close.
6085 status = smb_set_file_disposition_info(conn,
6092 if (!NT_STATUS_IS_OK(status)) {
6093 close_file(fsp, NORMAL_CLOSE);
6098 return close_file(fsp, NORMAL_CLOSE);
6101 /****************************************************************************
6102 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6103 ****************************************************************************/
6105 static void call_trans2setfilepathinfo(connection_struct *conn,
6106 struct smb_request *req,
6107 unsigned int tran_call,
6108 char **pparams, int total_params,
6109 char **ppdata, int total_data,
6110 unsigned int max_data_bytes)
6112 char *params = *pparams;
6113 char *pdata = *ppdata;
6115 SMB_STRUCT_STAT sbuf;
6117 files_struct *fsp = NULL;
6118 NTSTATUS status = NT_STATUS_OK;
6119 int data_return_size = 0;
6122 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6128 if (tran_call == TRANSACT2_SETFILEINFO) {
6129 if (total_params < 4) {
6130 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6134 fsp = file_fsp(SVAL(params,0));
6135 info_level = SVAL(params,2);
6137 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
6139 * This is actually a SETFILEINFO on a directory
6140 * handle (returned from an NT SMB). NT5.0 seems
6141 * to do this call. JRA.
6143 pstrcpy(fname, fsp->fsp_name);
6144 if (INFO_LEVEL_IS_UNIX(info_level)) {
6145 /* Always do lstat for UNIX calls. */
6146 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6147 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6148 reply_unixerror(req,ERRDOS,ERRbadpath);
6152 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6153 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6154 reply_unixerror(req,ERRDOS,ERRbadpath);
6158 } else if (fsp && fsp->print_file) {
6160 * Doing a DELETE_ON_CLOSE should cancel a print job.
6162 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6163 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6165 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6168 send_trans2_replies(req, params, 2,
6174 reply_unixerror(req, ERRDOS, ERRbadpath);
6179 * Original code - this is an open file.
6181 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6185 pstrcpy(fname, fsp->fsp_name);
6187 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6188 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6189 reply_unixerror(req, ERRDOS, ERRbadfid);
6195 if (total_params < 7) {
6196 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6200 info_level = SVAL(params,0);
6201 srvstr_get_path(params, req->flags2, fname, ¶ms[6],
6202 sizeof(fname), total_params - 6, STR_TERMINATE,
6204 if (!NT_STATUS_IS_OK(status)) {
6205 reply_nterror(req, status);
6209 status = resolve_dfspath(conn,
6210 req->flags2 & FLAGS2_DFS_PATHNAMES,
6212 if (!NT_STATUS_IS_OK(status)) {
6213 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6214 reply_botherror(req,
6215 NT_STATUS_PATH_NOT_COVERED,
6216 ERRSRV, ERRbadpath);
6219 reply_nterror(req, status);
6223 status = unix_convert(conn, fname, False, NULL, &sbuf);
6224 if (!NT_STATUS_IS_OK(status)) {
6225 reply_nterror(req, status);
6229 status = check_name(conn, fname);
6230 if (!NT_STATUS_IS_OK(status)) {
6231 reply_nterror(req, status);
6235 if (INFO_LEVEL_IS_UNIX(info_level)) {
6237 * For CIFS UNIX extensions the target name may not exist.
6240 /* Always do lstat for UNIX calls. */
6241 SMB_VFS_LSTAT(conn,fname,&sbuf);
6243 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6244 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6245 reply_unixerror(req, ERRDOS, ERRbadpath);
6250 if (!CAN_WRITE(conn)) {
6251 reply_doserror(req, ERRSRV, ERRaccess);
6255 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6256 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6260 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6261 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6263 /* Realloc the parameter size */
6264 *pparams = (char *)SMB_REALLOC(*pparams,2);
6265 if (*pparams == NULL) {
6266 reply_nterror(req, NT_STATUS_NO_MEMORY);
6273 if (fsp && !null_timespec(fsp->pending_modtime)) {
6274 /* the pending modtime overrides the current modtime */
6275 set_mtimespec(&sbuf, fsp->pending_modtime);
6278 switch (info_level) {
6280 case SMB_INFO_STANDARD:
6282 status = smb_set_info_standard(conn,
6291 case SMB_INFO_SET_EA:
6293 status = smb_info_set_ea(conn,
6301 case SMB_SET_FILE_BASIC_INFO:
6302 case SMB_FILE_BASIC_INFORMATION:
6304 status = smb_set_file_basic_info(conn,
6313 case SMB_FILE_ALLOCATION_INFORMATION:
6314 case SMB_SET_FILE_ALLOCATION_INFO:
6316 status = smb_set_file_allocation_info(conn, req,
6325 case SMB_FILE_END_OF_FILE_INFORMATION:
6326 case SMB_SET_FILE_END_OF_FILE_INFO:
6328 status = smb_set_file_end_of_file_info(conn, req,
6337 case SMB_FILE_DISPOSITION_INFORMATION:
6338 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6341 /* JRA - We used to just ignore this on a path ?
6342 * Shouldn't this be invalid level on a pathname
6345 if (tran_call != TRANSACT2_SETFILEINFO) {
6346 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6349 status = smb_set_file_disposition_info(conn,
6358 case SMB_FILE_POSITION_INFORMATION:
6360 status = smb_file_position_information(conn,
6367 /* From tridge Samba4 :
6368 * MODE_INFORMATION in setfileinfo (I have no
6369 * idea what "mode information" on a file is - it takes a value of 0,
6370 * 2, 4 or 6. What could it be?).
6373 case SMB_FILE_MODE_INFORMATION:
6375 status = smb_file_mode_information(conn,
6382 * CIFS UNIX extensions.
6385 case SMB_SET_FILE_UNIX_BASIC:
6387 status = smb_set_file_unix_basic(conn, req,
6396 case SMB_SET_FILE_UNIX_INFO2:
6398 status = smb_set_file_unix_info2(conn, req,
6407 case SMB_SET_FILE_UNIX_LINK:
6409 if (tran_call != TRANSACT2_SETPATHINFO) {
6410 /* We must have a pathname for this. */
6411 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6414 status = smb_set_file_unix_link(conn, req, pdata,
6419 case SMB_SET_FILE_UNIX_HLINK:
6421 if (tran_call != TRANSACT2_SETPATHINFO) {
6422 /* We must have a pathname for this. */
6423 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6426 status = smb_set_file_unix_hlink(conn, req,
6432 case SMB_FILE_RENAME_INFORMATION:
6434 status = smb_file_rename_information(conn, req,
6440 #if defined(HAVE_POSIX_ACLS)
6441 case SMB_SET_POSIX_ACL:
6443 status = smb_set_posix_acl(conn,
6453 case SMB_SET_POSIX_LOCK:
6455 if (tran_call != TRANSACT2_SETFILEINFO) {
6456 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6459 status = smb_set_posix_lock(conn, req->inbuf,
6460 smb_len(req->inbuf) + 4,
6461 pdata, total_data, fsp);
6465 case SMB_POSIX_PATH_OPEN:
6467 if (tran_call != TRANSACT2_SETPATHINFO) {
6468 /* We must have a pathname for this. */
6469 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6473 status = smb_posix_open(conn, req,
6482 case SMB_POSIX_PATH_UNLINK:
6484 if (tran_call != TRANSACT2_SETPATHINFO) {
6485 /* We must have a pathname for this. */
6486 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6490 status = smb_posix_unlink(conn, req,
6499 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6504 if (!NT_STATUS_IS_OK(status)) {
6505 if (open_was_deferred(req->mid)) {
6506 /* We have re-scheduled this call. */
6509 if (blocking_lock_was_deferred(req->mid)) {
6510 /* We have re-scheduled this call. */
6513 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6514 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6515 ERRSRV, ERRbadpath);
6518 if (info_level == SMB_POSIX_PATH_OPEN &&
6519 NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
6521 * We hit an existing file, and if we're returning DOS
6522 * error codes OBJECT_NAME_COLLISION would map to
6523 * ERRDOS/183, we need to return ERRDOS/80, see bug
6526 reply_botherror(req,
6527 NT_STATUS_OBJECT_NAME_COLLISION,
6528 ERRDOS, ERRfilexists);
6532 reply_nterror(req, status);
6537 send_trans2_replies(req, params, 2, *ppdata, data_return_size,
6543 /****************************************************************************
6544 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6545 ****************************************************************************/
6547 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6548 char **pparams, int total_params,
6549 char **ppdata, int total_data,
6550 unsigned int max_data_bytes)
6552 char *params = *pparams;
6553 char *pdata = *ppdata;
6555 SMB_STRUCT_STAT sbuf;
6556 NTSTATUS status = NT_STATUS_OK;
6557 struct ea_list *ea_list = NULL;
6559 if (!CAN_WRITE(conn)) {
6560 reply_doserror(req, ERRSRV, ERRaccess);
6564 if (total_params < 5) {
6565 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6569 srvstr_get_path(params, req->flags2, directory, ¶ms[4],
6570 sizeof(directory), total_params - 4, STR_TERMINATE,
6572 if (!NT_STATUS_IS_OK(status)) {
6573 reply_nterror(req, status);
6577 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6579 status = unix_convert(conn, directory, False, NULL, &sbuf);
6580 if (!NT_STATUS_IS_OK(status)) {
6581 reply_nterror(req, status);
6585 status = check_name(conn, directory);
6586 if (!NT_STATUS_IS_OK(status)) {
6587 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6588 reply_nterror(req, status);
6592 /* Any data in this call is an EA list. */
6593 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6594 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6599 * OS/2 workplace shell seems to send SET_EA requests of "null"
6600 * length (4 bytes containing IVAL 4).
6601 * They seem to have no effect. Bug #3212. JRA.
6604 if (total_data != 4) {
6605 if (total_data < 10) {
6606 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6610 if (IVAL(pdata,0) > total_data) {
6611 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6612 IVAL(pdata,0), (unsigned int)total_data));
6613 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6617 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6623 } else if (IVAL(pdata,0) != 4) {
6624 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6628 status = create_directory(conn, directory);
6630 if (!NT_STATUS_IS_OK(status)) {
6631 reply_nterror(req, status);
6635 /* Try and set any given EA. */
6637 status = set_ea(conn, NULL, directory, ea_list);
6638 if (!NT_STATUS_IS_OK(status)) {
6639 reply_nterror(req, status);
6644 /* Realloc the parameter and data sizes */
6645 *pparams = (char *)SMB_REALLOC(*pparams,2);
6646 if(*pparams == NULL) {
6647 reply_nterror(req, NT_STATUS_NO_MEMORY);
6654 send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
6659 /****************************************************************************
6660 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6661 We don't actually do this - we just send a null response.
6662 ****************************************************************************/
6664 static void call_trans2findnotifyfirst(connection_struct *conn,
6665 struct smb_request *req,
6666 char **pparams, int total_params,
6667 char **ppdata, int total_data,
6668 unsigned int max_data_bytes)
6670 static uint16 fnf_handle = 257;
6671 char *params = *pparams;
6674 if (total_params < 6) {
6675 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6679 info_level = SVAL(params,4);
6680 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6682 switch (info_level) {
6687 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6691 /* Realloc the parameter and data sizes */
6692 *pparams = (char *)SMB_REALLOC(*pparams,6);
6693 if (*pparams == NULL) {
6694 reply_nterror(req, NT_STATUS_NO_MEMORY);
6699 SSVAL(params,0,fnf_handle);
6700 SSVAL(params,2,0); /* No changes */
6701 SSVAL(params,4,0); /* No EA errors */
6708 send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
6713 /****************************************************************************
6714 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6715 changes). Currently this does nothing.
6716 ****************************************************************************/
6718 static void call_trans2findnotifynext(connection_struct *conn,
6719 struct smb_request *req,
6720 char **pparams, int total_params,
6721 char **ppdata, int total_data,
6722 unsigned int max_data_bytes)
6724 char *params = *pparams;
6726 DEBUG(3,("call_trans2findnotifynext\n"));
6728 /* Realloc the parameter and data sizes */
6729 *pparams = (char *)SMB_REALLOC(*pparams,4);
6730 if (*pparams == NULL) {
6731 reply_nterror(req, NT_STATUS_NO_MEMORY);
6736 SSVAL(params,0,0); /* No changes */
6737 SSVAL(params,2,0); /* No EA errors */
6739 send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes);
6744 /****************************************************************************
6745 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6746 ****************************************************************************/
6748 static void call_trans2getdfsreferral(connection_struct *conn,
6749 struct smb_request *req,
6750 char **pparams, int total_params,
6751 char **ppdata, int total_data,
6752 unsigned int max_data_bytes)
6754 char *params = *pparams;
6757 int max_referral_level;
6758 NTSTATUS status = NT_STATUS_OK;
6760 DEBUG(10,("call_trans2getdfsreferral\n"));
6762 if (total_params < 3) {
6763 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6767 max_referral_level = SVAL(params,0);
6769 if(!lp_host_msdfs()) {
6770 reply_doserror(req, ERRDOS, ERRbadfunc);
6774 srvstr_pull(params, req->flags2, pathname, ¶ms[2],
6775 sizeof(pathname), total_params - 2, STR_TERMINATE);
6776 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6777 ppdata,&status)) < 0) {
6778 reply_nterror(req, status);
6782 SSVAL(req->inbuf, smb_flg2,
6783 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6784 send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes);
6789 #define LMCAT_SPL 0x53
6790 #define LMFUNC_GETJOBID 0x60
6792 /****************************************************************************
6793 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6794 ****************************************************************************/
6796 static void call_trans2ioctl(connection_struct *conn,
6797 struct smb_request *req,
6798 char **pparams, int total_params,
6799 char **ppdata, int total_data,
6800 unsigned int max_data_bytes)
6802 char *pdata = *ppdata;
6803 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6805 /* check for an invalid fid before proceeding */
6808 reply_doserror(req, ERRDOS, ERRbadfid);
6812 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6813 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6814 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6815 if (*ppdata == NULL) {
6816 reply_nterror(req, NT_STATUS_NO_MEMORY);
6821 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6822 CAN ACCEPT THIS IN UNICODE. JRA. */
6824 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6825 srvstr_push(pdata, req->flags2, pdata + 2,
6826 global_myname(), 15,
6827 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6828 srvstr_push(pdata, req->flags2, pdata+18,
6829 lp_servicename(SNUM(conn)), 13,
6830 STR_ASCII|STR_TERMINATE); /* Service name */
6831 send_trans2_replies(req, *pparams, 0, *ppdata, 32,
6836 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6837 reply_doserror(req, ERRSRV, ERRerror);
6840 /****************************************************************************
6841 Reply to a SMBfindclose (stop trans2 directory search).
6842 ****************************************************************************/
6844 void reply_findclose(connection_struct *conn, struct smb_request *req)
6848 START_PROFILE(SMBfindclose);
6851 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6852 END_PROFILE(SMBfindclose);
6856 dptr_num = SVALS(req->inbuf,smb_vwv0);
6858 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6860 dptr_close(&dptr_num);
6862 reply_outbuf(req, 0, 0);
6864 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6866 END_PROFILE(SMBfindclose);
6870 /****************************************************************************
6871 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6872 ****************************************************************************/
6874 void reply_findnclose(connection_struct *conn, struct smb_request *req)
6878 START_PROFILE(SMBfindnclose);
6881 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6882 END_PROFILE(SMBfindnclose);
6886 dptr_num = SVAL(req->inbuf,smb_vwv0);
6888 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6890 /* We never give out valid handles for a
6891 findnotifyfirst - so any dptr_num is ok here.
6894 reply_outbuf(req, 0, 0);
6896 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6898 END_PROFILE(SMBfindnclose);
6902 static void handle_trans2(connection_struct *conn, struct smb_request *req,
6903 struct trans_state *state)
6905 if (Protocol >= PROTOCOL_NT1) {
6906 req->flags2 |= 0x40; /* IS_LONG_NAME */
6907 SSVAL(req->inbuf,smb_flg2,req->flags2);
6910 /* Now we must call the relevant TRANS2 function */
6911 switch(state->call) {
6912 case TRANSACT2_OPEN:
6914 START_PROFILE(Trans2_open);
6915 call_trans2open(conn, req,
6916 &state->param, state->total_param,
6917 &state->data, state->total_data,
6918 state->max_data_return);
6919 END_PROFILE(Trans2_open);
6923 case TRANSACT2_FINDFIRST:
6925 START_PROFILE(Trans2_findfirst);
6926 call_trans2findfirst(conn, req,
6927 &state->param, state->total_param,
6928 &state->data, state->total_data,
6929 state->max_data_return);
6930 END_PROFILE(Trans2_findfirst);
6934 case TRANSACT2_FINDNEXT:
6936 START_PROFILE(Trans2_findnext);
6937 call_trans2findnext(conn, req,
6938 &state->param, state->total_param,
6939 &state->data, state->total_data,
6940 state->max_data_return);
6941 END_PROFILE(Trans2_findnext);
6945 case TRANSACT2_QFSINFO:
6947 START_PROFILE(Trans2_qfsinfo);
6948 call_trans2qfsinfo(conn, req,
6949 &state->param, state->total_param,
6950 &state->data, state->total_data,
6951 state->max_data_return);
6952 END_PROFILE(Trans2_qfsinfo);
6956 case TRANSACT2_SETFSINFO:
6958 START_PROFILE(Trans2_setfsinfo);
6959 call_trans2setfsinfo(conn, req,
6960 &state->param, state->total_param,
6961 &state->data, state->total_data,
6962 state->max_data_return);
6963 END_PROFILE(Trans2_setfsinfo);
6967 case TRANSACT2_QPATHINFO:
6968 case TRANSACT2_QFILEINFO:
6970 START_PROFILE(Trans2_qpathinfo);
6971 call_trans2qfilepathinfo(conn, req, state->call,
6972 &state->param, state->total_param,
6973 &state->data, state->total_data,
6974 state->max_data_return);
6975 END_PROFILE(Trans2_qpathinfo);
6979 case TRANSACT2_SETPATHINFO:
6980 case TRANSACT2_SETFILEINFO:
6982 START_PROFILE(Trans2_setpathinfo);
6983 call_trans2setfilepathinfo(conn, req, state->call,
6984 &state->param, state->total_param,
6985 &state->data, state->total_data,
6986 state->max_data_return);
6987 END_PROFILE(Trans2_setpathinfo);
6991 case TRANSACT2_FINDNOTIFYFIRST:
6993 START_PROFILE(Trans2_findnotifyfirst);
6994 call_trans2findnotifyfirst(conn, req,
6995 &state->param, state->total_param,
6996 &state->data, state->total_data,
6997 state->max_data_return);
6998 END_PROFILE(Trans2_findnotifyfirst);
7002 case TRANSACT2_FINDNOTIFYNEXT:
7004 START_PROFILE(Trans2_findnotifynext);
7005 call_trans2findnotifynext(conn, req,
7006 &state->param, state->total_param,
7007 &state->data, state->total_data,
7008 state->max_data_return);
7009 END_PROFILE(Trans2_findnotifynext);
7013 case TRANSACT2_MKDIR:
7015 START_PROFILE(Trans2_mkdir);
7016 call_trans2mkdir(conn, req,
7017 &state->param, state->total_param,
7018 &state->data, state->total_data,
7019 state->max_data_return);
7020 END_PROFILE(Trans2_mkdir);
7024 case TRANSACT2_GET_DFS_REFERRAL:
7026 START_PROFILE(Trans2_get_dfs_referral);
7027 call_trans2getdfsreferral(conn, req,
7028 &state->param, state->total_param,
7029 &state->data, state->total_data,
7030 state->max_data_return);
7031 END_PROFILE(Trans2_get_dfs_referral);
7035 case TRANSACT2_IOCTL:
7037 START_PROFILE(Trans2_ioctl);
7038 call_trans2ioctl(conn, req,
7039 &state->param, state->total_param,
7040 &state->data, state->total_data,
7041 state->max_data_return);
7042 END_PROFILE(Trans2_ioctl);
7047 /* Error in request */
7048 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7049 reply_doserror(req, ERRSRV,ERRerror);
7053 /****************************************************************************
7054 Reply to a SMBtrans2.
7055 ****************************************************************************/
7057 void reply_trans2(connection_struct *conn, struct smb_request *req)
7063 unsigned int tran_call;
7065 struct trans_state *state;
7068 START_PROFILE(SMBtrans2);
7070 if (req->wct < 14) {
7071 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7072 END_PROFILE(SMBtrans2);
7076 dsoff = SVAL(req->inbuf, smb_dsoff);
7077 dscnt = SVAL(req->inbuf, smb_dscnt);
7078 psoff = SVAL(req->inbuf, smb_psoff);
7079 pscnt = SVAL(req->inbuf, smb_pscnt);
7080 tran_call = SVAL(req->inbuf, smb_setup0);
7081 size = smb_len(req->inbuf) + 4;
7083 result = allow_new_trans(conn->pending_trans, req->mid);
7084 if (!NT_STATUS_IS_OK(result)) {
7085 DEBUG(2, ("Got invalid trans2 request: %s\n",
7086 nt_errstr(result)));
7087 reply_nterror(req, result);
7088 END_PROFILE(SMBtrans2);
7092 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
7093 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
7094 && (tran_call != TRANSACT2_QFILEINFO)) {
7095 reply_doserror(req, ERRSRV, ERRaccess);
7096 END_PROFILE(SMBtrans2);
7100 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7101 DEBUG(0, ("talloc failed\n"));
7102 reply_nterror(req, NT_STATUS_NO_MEMORY);
7103 END_PROFILE(SMBtrans2);
7107 state->cmd = SMBtrans2;
7109 state->mid = req->mid;
7110 state->vuid = req->vuid;
7111 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7112 state->setup = NULL;
7113 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7114 state->param = NULL;
7115 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7117 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7118 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7119 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7120 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7121 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7123 state->call = tran_call;
7125 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7126 is so as a sanity check */
7127 if (state->setup_count != 1) {
7129 * Need to have rc=0 for ioctl to get job id for OS/2.
7130 * Network printing will fail if function is not successful.
7131 * Similar function in reply.c will be used if protocol
7132 * is LANMAN1.0 instead of LM1.2X002.
7133 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7134 * outbuf doesn't have to be set(only job id is used).
7136 if ( (state->setup_count == 4)
7137 && (tran_call == TRANSACT2_IOCTL)
7138 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7139 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7140 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7142 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7143 DEBUG(2,("Transaction is %d\n",tran_call));
7145 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7146 END_PROFILE(SMBtrans2);
7151 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7154 if (state->total_data) {
7155 /* Can't use talloc here, the core routines do realloc on the
7156 * params and data. */
7157 state->data = (char *)SMB_MALLOC(state->total_data);
7158 if (state->data == NULL) {
7159 DEBUG(0,("reply_trans2: data malloc fail for %u "
7160 "bytes !\n", (unsigned int)state->total_data));
7162 reply_nterror(req, NT_STATUS_NO_MEMORY);
7163 END_PROFILE(SMBtrans2);
7166 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7168 if ((smb_base(req->inbuf)+dsoff+dscnt
7169 > (char *)req->inbuf + size) ||
7170 (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7173 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7176 if (state->total_param) {
7177 /* Can't use talloc here, the core routines do realloc on the
7178 * params and data. */
7179 state->param = (char *)SMB_MALLOC(state->total_param);
7180 if (state->param == NULL) {
7181 DEBUG(0,("reply_trans: param malloc fail for %u "
7182 "bytes !\n", (unsigned int)state->total_param));
7183 SAFE_FREE(state->data);
7185 reply_nterror(req, NT_STATUS_NO_MEMORY);
7186 END_PROFILE(SMBtrans2);
7189 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7191 if ((smb_base(req->inbuf)+psoff+pscnt
7192 > (char *)req->inbuf + size) ||
7193 (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7196 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7199 state->received_data = dscnt;
7200 state->received_param = pscnt;
7202 if ((state->received_param == state->total_param) &&
7203 (state->received_data == state->total_data)) {
7205 handle_trans2(conn, req, state);
7207 SAFE_FREE(state->data);
7208 SAFE_FREE(state->param);
7210 END_PROFILE(SMBtrans2);
7214 DLIST_ADD(conn->pending_trans, state);
7216 /* We need to send an interim response then receive the rest
7217 of the parameter/data bytes */
7218 reply_outbuf(req, 0, 0);
7219 show_msg((char *)req->outbuf);
7220 END_PROFILE(SMBtrans2);
7225 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7226 SAFE_FREE(state->data);
7227 SAFE_FREE(state->param);
7229 END_PROFILE(SMBtrans2);
7230 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7234 /****************************************************************************
7235 Reply to a SMBtranss2
7236 ****************************************************************************/
7238 void reply_transs2(connection_struct *conn, struct smb_request *req)
7240 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7241 struct trans_state *state;
7244 START_PROFILE(SMBtranss2);
7246 show_msg((char *)req->inbuf);
7249 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7250 END_PROFILE(SMBtranss2);
7254 size = smb_len(req->inbuf)+4;
7256 for (state = conn->pending_trans; state != NULL;
7257 state = state->next) {
7258 if (state->mid == req->mid) {
7263 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7264 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7265 END_PROFILE(SMBtranss2);
7269 /* Revise state->total_param and state->total_data in case they have
7270 changed downwards */
7272 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7273 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7274 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7275 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7277 pcnt = SVAL(req->inbuf, smb_spscnt);
7278 poff = SVAL(req->inbuf, smb_spsoff);
7279 pdisp = SVAL(req->inbuf, smb_spsdisp);
7281 dcnt = SVAL(req->inbuf, smb_sdscnt);
7282 doff = SVAL(req->inbuf, smb_sdsoff);
7283 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7285 state->received_param += pcnt;
7286 state->received_data += dcnt;
7288 if ((state->received_data > state->total_data) ||
7289 (state->received_param > state->total_param))
7293 if (pdisp+pcnt > state->total_param)
7295 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7297 if (pdisp > state->total_param)
7299 if ((smb_base(req->inbuf) + poff + pcnt
7300 > (char *)req->inbuf + size) ||
7301 (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7303 if (state->param + pdisp < state->param)
7306 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7311 if (ddisp+dcnt > state->total_data)
7313 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7315 if (ddisp > state->total_data)
7317 if ((smb_base(req->inbuf) + doff + dcnt
7318 > (char *)req->inbuf + size) ||
7319 (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7321 if (state->data + ddisp < state->data)
7324 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7328 if ((state->received_param < state->total_param) ||
7329 (state->received_data < state->total_data)) {
7330 END_PROFILE(SMBtranss2);
7335 * construct_reply_common will copy smb_com from inbuf to
7336 * outbuf. SMBtranss2 is wrong here.
7338 SCVAL(req->inbuf,smb_com,SMBtrans2);
7340 handle_trans2(conn, req, state);
7342 DLIST_REMOVE(conn->pending_trans, state);
7343 SAFE_FREE(state->data);
7344 SAFE_FREE(state->param);
7347 END_PROFILE(SMBtranss2);
7352 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7353 DLIST_REMOVE(conn->pending_trans, state);
7354 SAFE_FREE(state->data);
7355 SAFE_FREE(state->param);
7357 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7358 END_PROFILE(SMBtranss2);