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
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 int send_trans2_replies(const char *inbuf,
588 /* As we are using a protocol > LANMAN1 then the max_send
589 variable must have been set in the sessetupX call.
590 This takes precedence over the max_xmit field in the
591 global struct. These different max_xmit variables should
592 be merged as this is now too confusing */
594 int data_to_send = datasize;
595 int params_to_send = paramsize;
597 const char *pp = params;
598 const char *pd = pdata;
599 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
600 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
601 int data_alignment_offset = 0;
603 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
605 set_message(inbuf,outbuf,10,0,True);
607 /* Modify the data_to_send and datasize and set the error if
608 we're trying to send more than max_data_bytes. We still send
609 the part of the packet(s) that fit. Strange, but needed
612 if (max_data_bytes > 0 && datasize > max_data_bytes) {
613 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
614 max_data_bytes, datasize ));
615 datasize = data_to_send = max_data_bytes;
616 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
619 /* If there genuinely are no parameters or data to send just send the empty packet */
621 if(params_to_send == 0 && data_to_send == 0) {
623 if (!send_smb(smbd_server_fd(),outbuf))
624 exit_server_cleanly("send_trans2_replies: send_smb failed.");
628 /* When sending params and data ensure that both are nicely aligned */
629 /* Only do this alignment when there is also data to send - else
630 can cause NT redirector problems. */
632 if (((params_to_send % 4) != 0) && (data_to_send != 0))
633 data_alignment_offset = 4 - (params_to_send % 4);
635 /* Space is bufsize minus Netbios over TCP header minus SMB header */
636 /* The alignment_offset is to align the param bytes on an even byte
637 boundary. NT 4.0 Beta needs this to work correctly. */
639 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
641 /* useable_space can never be more than max_send minus the alignment offset. */
643 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
645 while (params_to_send || data_to_send) {
646 /* Calculate whether we will totally or partially fill this packet */
648 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
650 /* We can never send more than useable_space */
652 * Note that 'useable_space' does not include the alignment offsets,
653 * but we must include the alignment offsets in the calculation of
654 * the length of the data we send over the wire, as the alignment offsets
655 * are sent here. Fix from Marc_Jacobsen@hp.com.
658 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
660 set_message(inbuf, outbuf, 10, total_sent_thistime, True);
662 /* Set total params and data to be sent */
663 SSVAL(outbuf,smb_tprcnt,paramsize);
664 SSVAL(outbuf,smb_tdrcnt,datasize);
666 /* Calculate how many parameters and data we can fit into
667 * this packet. Parameters get precedence
670 params_sent_thistime = MIN(params_to_send,useable_space);
671 data_sent_thistime = useable_space - params_sent_thistime;
672 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
674 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
676 /* smb_proff is the offset from the start of the SMB header to the
677 parameter bytes, however the first 4 bytes of outbuf are
678 the Netbios over TCP header. Thus use smb_base() to subtract
679 them from the calculation */
681 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
683 if(params_sent_thistime == 0)
684 SSVAL(outbuf,smb_prdisp,0);
686 /* Absolute displacement of param bytes sent in this packet */
687 SSVAL(outbuf,smb_prdisp,pp - params);
689 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
690 if(data_sent_thistime == 0) {
691 SSVAL(outbuf,smb_droff,0);
692 SSVAL(outbuf,smb_drdisp, 0);
694 /* The offset of the data bytes is the offset of the
695 parameter bytes plus the number of parameters being sent this time */
696 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
697 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
698 SSVAL(outbuf,smb_drdisp, pd - pdata);
701 /* Copy the param bytes into the packet */
703 if(params_sent_thistime)
704 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
706 /* Copy in the data bytes */
707 if(data_sent_thistime)
708 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
709 data_alignment_offset,pd,data_sent_thistime);
711 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
712 params_sent_thistime, data_sent_thistime, useable_space));
713 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
714 params_to_send, data_to_send, paramsize, datasize));
716 /* Send the packet */
718 if (!send_smb(smbd_server_fd(),outbuf))
719 exit_server_cleanly("send_trans2_replies: send_smb failed.");
721 pp += params_sent_thistime;
722 pd += data_sent_thistime;
724 params_to_send -= params_sent_thistime;
725 data_to_send -= data_sent_thistime;
728 if(params_to_send < 0 || data_to_send < 0) {
729 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
730 params_to_send, data_to_send));
738 /****************************************************************************
739 Reply to a TRANSACT2_OPEN.
740 ****************************************************************************/
742 static int call_trans2open(connection_struct *conn,
743 struct smb_request *req,
744 char *inbuf, char *outbuf, int bufsize,
745 char **pparams, int total_params,
746 char **ppdata, int total_data,
747 unsigned int max_data_bytes)
749 char *params = *pparams;
750 char *pdata = *ppdata;
755 BOOL return_additional_info;
766 SMB_STRUCT_STAT sbuf;
769 struct ea_list *ea_list = NULL;
774 uint32 create_disposition;
775 uint32 create_options = 0;
778 * Ensure we have enough parameters to perform the operation.
781 if (total_params < 29) {
782 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
785 flags = SVAL(params, 0);
786 deny_mode = SVAL(params, 2);
787 open_attr = SVAL(params,6);
788 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
789 if (oplock_request) {
790 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
794 return_additional_info = BITSETW(params,0);
795 open_sattr = SVAL(params, 4);
796 open_time = make_unix_date3(params+8);
798 open_ofun = SVAL(params,12);
799 open_size = IVAL(params,14);
803 return(ERROR_DOS(ERRSRV,ERRaccess));
806 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, pname,
807 sizeof(fname), total_params - 28, STR_TERMINATE,
809 if (!NT_STATUS_IS_OK(status)) {
810 return ERROR_NT(status);
813 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
814 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
815 (unsigned int)open_ofun, open_size));
817 /* XXXX we need to handle passed times, sattr and flags */
819 status = unix_convert(conn, fname, False, NULL, &sbuf);
820 if (!NT_STATUS_IS_OK(status)) {
821 return ERROR_NT(status);
824 status = check_name(conn, fname);
825 if (!NT_STATUS_IS_OK(status)) {
826 return ERROR_NT(status);
829 if (open_ofun == 0) {
830 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
833 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
838 return ERROR_DOS(ERRDOS, ERRbadaccess);
841 /* Any data in this call is an EA list. */
842 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
843 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
846 if (total_data != 4) {
847 if (total_data < 10) {
848 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
851 if (IVAL(pdata,0) > total_data) {
852 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
853 IVAL(pdata,0), (unsigned int)total_data));
854 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
857 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
860 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
862 } else if (IVAL(pdata,0) != 4) {
863 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
866 status = open_file_ntcreate(conn, req, fname, &sbuf,
875 if (!NT_STATUS_IS_OK(status)) {
876 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
877 /* We have re-scheduled this call. */
880 return ERROR_NT(status);
883 size = get_file_size(sbuf);
884 fattr = dos_mode(conn,fname,&sbuf);
885 mtime = sbuf.st_mtime;
888 close_file(fsp,ERROR_CLOSE);
889 return(ERROR_DOS(ERRDOS,ERRnoaccess));
892 /* Save the requested allocation size. */
893 /* Allocate space for the file if a size hint is supplied */
894 if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
895 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
896 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
897 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
898 if (fsp->is_directory) {
899 close_file(fsp,ERROR_CLOSE);
900 /* Can't set allocation size on a directory. */
901 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
903 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
904 close_file(fsp,ERROR_CLOSE);
905 return ERROR_NT(NT_STATUS_DISK_FULL);
908 /* Adjust size here to return the right size in the reply.
909 Windows does it this way. */
910 size = fsp->initial_allocation_size;
912 fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
916 if (ea_list && smb_action == FILE_WAS_CREATED) {
917 status = set_ea(conn, fsp, fname, ea_list);
918 if (!NT_STATUS_IS_OK(status)) {
919 close_file(fsp,ERROR_CLOSE);
920 return ERROR_NT(status);
924 /* Realloc the size of parameters and data we will return */
925 *pparams = (char *)SMB_REALLOC(*pparams, 30);
926 if(*pparams == NULL ) {
927 return ERROR_NT(NT_STATUS_NO_MEMORY);
931 SSVAL(params,0,fsp->fnum);
932 SSVAL(params,2,fattr);
933 srv_put_dos_date2(params,4, mtime);
934 SIVAL(params,8, (uint32)size);
935 SSVAL(params,12,deny_mode);
936 SSVAL(params,14,0); /* open_type - file or directory. */
937 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
939 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
940 smb_action |= EXTENDED_OPLOCK_GRANTED;
943 SSVAL(params,18,smb_action);
946 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
948 SIVAL(params,20,inode);
949 SSVAL(params,24,0); /* Padding. */
951 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
952 SIVAL(params, 26, ea_size);
954 SIVAL(params, 26, 0);
957 /* Send the required number of replies */
958 send_trans2_replies(inbuf, outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
963 /*********************************************************
964 Routine to check if a given string matches exactly.
965 as a special case a mask of "." does NOT match. That
966 is required for correct wildcard semantics
967 Case can be significant or not.
968 **********************************************************/
970 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
972 if (mask[0] == '.' && mask[1] == 0)
974 if (conn->case_sensitive)
975 return strcmp(str,mask)==0;
976 if (StrCaseCmp(str,mask) != 0) {
979 if (dptr_has_wild(conn->dirptr)) {
985 /****************************************************************************
986 Return the filetype for UNIX extensions.
987 ****************************************************************************/
989 static uint32 unix_filetype(mode_t mode)
992 return UNIX_TYPE_FILE;
993 else if(S_ISDIR(mode))
994 return UNIX_TYPE_DIR;
996 else if(S_ISLNK(mode))
997 return UNIX_TYPE_SYMLINK;
1000 else if(S_ISCHR(mode))
1001 return UNIX_TYPE_CHARDEV;
1004 else if(S_ISBLK(mode))
1005 return UNIX_TYPE_BLKDEV;
1008 else if(S_ISFIFO(mode))
1009 return UNIX_TYPE_FIFO;
1012 else if(S_ISSOCK(mode))
1013 return UNIX_TYPE_SOCKET;
1016 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1017 return UNIX_TYPE_UNKNOWN;
1020 /****************************************************************************
1021 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1022 ****************************************************************************/
1024 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1026 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1027 SMB_STRUCT_STAT *psbuf,
1029 enum perm_type ptype,
1034 if (perms == SMB_MODE_NO_CHANGE) {
1035 if (!VALID_STAT(*psbuf)) {
1036 return NT_STATUS_INVALID_PARAMETER;
1038 *ret_perms = psbuf->st_mode;
1039 return NT_STATUS_OK;
1043 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1044 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1045 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1046 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1047 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1048 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1049 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1050 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1051 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1053 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1056 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1059 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1064 /* Apply mode mask */
1065 ret &= lp_create_mask(SNUM(conn));
1066 /* Add in force bits */
1067 ret |= lp_force_create_mode(SNUM(conn));
1070 ret &= lp_dir_mask(SNUM(conn));
1071 /* Add in force bits */
1072 ret |= lp_force_dir_mode(SNUM(conn));
1074 case PERM_EXISTING_FILE:
1075 /* Apply mode mask */
1076 ret &= lp_security_mask(SNUM(conn));
1077 /* Add in force bits */
1078 ret |= lp_force_security_mode(SNUM(conn));
1080 case PERM_EXISTING_DIR:
1081 /* Apply mode mask */
1082 ret &= lp_dir_security_mask(SNUM(conn));
1083 /* Add in force bits */
1084 ret |= lp_force_dir_security_mode(SNUM(conn));
1089 return NT_STATUS_OK;
1092 /****************************************************************************
1093 Get a level dependent lanman2 dir entry.
1094 ****************************************************************************/
1096 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1097 void *inbuf, char *outbuf,
1098 char *path_mask,uint32 dirtype,int info_level,
1099 int requires_resume_key,
1100 BOOL dont_descend,char **ppdata,
1101 char *base_data, int space_remaining,
1102 BOOL *out_of_space, BOOL *got_exact_match,
1103 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1107 SMB_STRUCT_STAT sbuf;
1111 char *p, *q, *pdata = *ppdata;
1115 SMB_OFF_T file_size = 0;
1116 SMB_BIG_UINT allocation_size = 0;
1118 struct timespec mdate_ts, adate_ts, create_date_ts;
1119 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1121 char *last_entry_ptr;
1123 uint32 nt_extmode; /* Used for NT connections instead of mode */
1124 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1125 BOOL check_mangled_names = lp_manglednames(conn->params);
1128 *out_of_space = False;
1129 *got_exact_match = False;
1131 ZERO_STRUCT(mdate_ts);
1132 ZERO_STRUCT(adate_ts);
1133 ZERO_STRUCT(create_date_ts);
1138 p = strrchr_m(path_mask,'/');
1141 pstrcpy(mask,"*.*");
1145 pstrcpy(mask, path_mask);
1150 BOOL ms_dfs_link = False;
1152 /* Needed if we run out of space */
1153 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1154 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1157 * Due to bugs in NT client redirectors we are not using
1158 * resume keys any more - set them to zero.
1159 * Check out the related comments in findfirst/findnext.
1165 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1166 (long)conn->dirptr,curr_dirpos));
1173 * fname may get mangled, dname is never mangled.
1174 * Whenever we're accessing the filesystem we use
1175 * pathreal which is composed from dname.
1178 pstrcpy(fname,dname);
1180 /* This will mangle fname if it's an illegal name. */
1181 mangle_map(fname,False,True,conn->params);
1183 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1184 got_match = mask_match(fname, mask, conn->case_sensitive);
1187 if(!got_match && check_mangled_names &&
1188 !mangle_is_8_3(fname, False, conn->params)) {
1189 pstring mangled_name;
1192 * It turns out that NT matches wildcards against
1193 * both long *and* short names. This may explain some
1194 * of the wildcard wierdness from old DOS clients
1195 * that some people have been seeing.... JRA.
1198 pstrcpy(mangled_name, fname);
1200 /* Force the mangling into 8.3. */
1201 mangle_map( mangled_name, True, False, conn->params);
1202 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1203 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1208 BOOL isdots = (strequal(dname,"..") || strequal(dname,"."));
1209 if (dont_descend && !isdots) {
1213 pstrcpy(pathreal,conn->dirpath);
1215 pstrcat(pathreal,"/");
1217 pstrcat(pathreal,dname);
1219 if (INFO_LEVEL_IS_UNIX(info_level)) {
1220 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1221 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1222 pathreal,strerror(errno)));
1225 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1226 pstring link_target;
1228 /* Needed to show the msdfs symlinks as
1231 if(lp_host_msdfs() &&
1232 lp_msdfs_root(SNUM(conn)) &&
1233 ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1234 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1237 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1241 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1242 pathreal,strerror(errno)));
1248 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1250 mode = dos_mode(conn,pathreal,&sbuf);
1253 if (!dir_check_ftype(conn,mode,dirtype)) {
1254 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1258 if (!(mode & aDIR)) {
1259 file_size = get_file_size(sbuf);
1261 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1263 mdate_ts = get_mtimespec(&sbuf);
1264 adate_ts = get_atimespec(&sbuf);
1265 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1267 if (lp_dos_filetime_resolution(SNUM(conn))) {
1268 dos_filetime_timespec(&create_date_ts);
1269 dos_filetime_timespec(&mdate_ts);
1270 dos_filetime_timespec(&adate_ts);
1273 create_date = convert_timespec_to_time_t(create_date_ts);
1274 mdate = convert_timespec_to_time_t(mdate_ts);
1275 adate = convert_timespec_to_time_t(adate_ts);
1277 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1281 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1288 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1290 switch (info_level) {
1291 case SMB_FIND_INFO_STANDARD:
1292 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1293 if(requires_resume_key) {
1297 srv_put_dos_date2(p,0,create_date);
1298 srv_put_dos_date2(p,4,adate);
1299 srv_put_dos_date2(p,8,mdate);
1300 SIVAL(p,12,(uint32)file_size);
1301 SIVAL(p,16,(uint32)allocation_size);
1305 p += align_string(outbuf, p, 0);
1306 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p,
1307 fname, -1, STR_TERMINATE);
1308 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1310 SCVAL(nameptr, -1, len - 2);
1312 SCVAL(nameptr, -1, 0);
1316 SCVAL(nameptr, -1, len - 1);
1318 SCVAL(nameptr, -1, 0);
1324 case SMB_FIND_EA_SIZE:
1325 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1326 if(requires_resume_key) {
1330 srv_put_dos_date2(p,0,create_date);
1331 srv_put_dos_date2(p,4,adate);
1332 srv_put_dos_date2(p,8,mdate);
1333 SIVAL(p,12,(uint32)file_size);
1334 SIVAL(p,16,(uint32)allocation_size);
1337 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1338 SIVAL(p,22,ea_size); /* Extended attributes */
1342 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
1344 STR_TERMINATE | STR_NOALIGN);
1345 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1358 SCVAL(nameptr,0,len);
1360 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1363 case SMB_FIND_EA_LIST:
1365 struct ea_list *file_list = NULL;
1368 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1372 if(requires_resume_key) {
1376 srv_put_dos_date2(p,0,create_date);
1377 srv_put_dos_date2(p,4,adate);
1378 srv_put_dos_date2(p,8,mdate);
1379 SIVAL(p,12,(uint32)file_size);
1380 SIVAL(p,16,(uint32)allocation_size);
1382 p += 22; /* p now points to the EA area. */
1384 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1385 name_list = ea_list_union(name_list, file_list, &ea_len);
1387 /* We need to determine if this entry will fit in the space available. */
1388 /* Max string size is 255 bytes. */
1389 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1390 /* Move the dirptr back to prev_dirpos */
1391 dptr_SeekDir(conn->dirptr, prev_dirpos);
1392 *out_of_space = True;
1393 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1394 return False; /* Not finished - just out of space */
1397 /* Push the ea_data followed by the name. */
1398 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1400 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
1402 STR_TERMINATE | STR_NOALIGN);
1403 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1416 SCVAL(nameptr,0,len);
1418 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1422 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1423 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1424 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1426 SIVAL(p,0,reskey); p += 4;
1427 put_long_date_timespec(p,create_date_ts); p += 8;
1428 put_long_date_timespec(p,adate_ts); p += 8;
1429 put_long_date_timespec(p,mdate_ts); p += 8;
1430 put_long_date_timespec(p,mdate_ts); p += 8;
1431 SOFF_T(p,0,file_size); p += 8;
1432 SOFF_T(p,0,allocation_size); p += 8;
1433 SIVAL(p,0,nt_extmode); p += 4;
1434 q = p; p += 4; /* q is placeholder for name length. */
1436 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1437 SIVAL(p,0,ea_size); /* Extended attributes */
1440 /* Clear the short name buffer. This is
1441 * IMPORTANT as not doing so will trigger
1442 * a Win2k client bug. JRA.
1444 if (!was_8_3 && check_mangled_names) {
1445 pstring mangled_name;
1446 pstrcpy(mangled_name, fname);
1447 mangle_map(mangled_name,True,True,
1449 mangled_name[12] = 0;
1450 len = srvstr_push(outbuf,
1451 SVAL(outbuf, smb_flg2),
1452 p+2, mangled_name, 24,
1453 STR_UPPER|STR_UNICODE);
1455 memset(p + 2 + len,'\0',24 - len);
1462 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p,
1463 fname, -1, STR_TERMINATE_ASCII);
1466 SIVAL(p,0,0); /* Ensure any padding is null. */
1467 len = PTR_DIFF(p, pdata);
1468 len = (len + 3) & ~3;
1473 case SMB_FIND_FILE_DIRECTORY_INFO:
1474 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1476 SIVAL(p,0,reskey); p += 4;
1477 put_long_date_timespec(p,create_date_ts); p += 8;
1478 put_long_date_timespec(p,adate_ts); p += 8;
1479 put_long_date_timespec(p,mdate_ts); p += 8;
1480 put_long_date_timespec(p,mdate_ts); p += 8;
1481 SOFF_T(p,0,file_size); p += 8;
1482 SOFF_T(p,0,allocation_size); p += 8;
1483 SIVAL(p,0,nt_extmode); p += 4;
1484 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
1486 STR_TERMINATE_ASCII);
1489 SIVAL(p,0,0); /* Ensure any padding is null. */
1490 len = PTR_DIFF(p, pdata);
1491 len = (len + 3) & ~3;
1496 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1497 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1499 SIVAL(p,0,reskey); p += 4;
1500 put_long_date_timespec(p,create_date_ts); p += 8;
1501 put_long_date_timespec(p,adate_ts); p += 8;
1502 put_long_date_timespec(p,mdate_ts); p += 8;
1503 put_long_date_timespec(p,mdate_ts); p += 8;
1504 SOFF_T(p,0,file_size); p += 8;
1505 SOFF_T(p,0,allocation_size); p += 8;
1506 SIVAL(p,0,nt_extmode); p += 4;
1507 q = p; p += 4; /* q is placeholder for name length. */
1509 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1510 SIVAL(p,0,ea_size); /* Extended attributes */
1513 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p,
1514 fname, -1, 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_NAMES_INFO:
1526 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1528 SIVAL(p,0,reskey); p += 4;
1530 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1531 acl on a dir (tridge) */
1532 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
1533 p, fname, -1, STR_TERMINATE_ASCII);
1536 SIVAL(p,0,0); /* Ensure any padding is null. */
1537 len = PTR_DIFF(p, pdata);
1538 len = (len + 3) & ~3;
1543 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1544 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1546 SIVAL(p,0,reskey); p += 4;
1547 put_long_date_timespec(p,create_date_ts); p += 8;
1548 put_long_date_timespec(p,adate_ts); p += 8;
1549 put_long_date_timespec(p,mdate_ts); p += 8;
1550 put_long_date_timespec(p,mdate_ts); p += 8;
1551 SOFF_T(p,0,file_size); p += 8;
1552 SOFF_T(p,0,allocation_size); p += 8;
1553 SIVAL(p,0,nt_extmode); p += 4;
1554 q = p; p += 4; /* q is placeholder for name length. */
1556 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1557 SIVAL(p,0,ea_size); /* Extended attributes */
1560 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1561 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1562 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1563 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p,
1564 fname, -1, STR_TERMINATE_ASCII);
1567 SIVAL(p,0,0); /* Ensure any padding is null. */
1568 len = PTR_DIFF(p, pdata);
1569 len = (len + 3) & ~3;
1574 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1575 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1576 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1578 SIVAL(p,0,reskey); p += 4;
1579 put_long_date_timespec(p,create_date_ts); p += 8;
1580 put_long_date_timespec(p,adate_ts); p += 8;
1581 put_long_date_timespec(p,mdate_ts); p += 8;
1582 put_long_date_timespec(p,mdate_ts); p += 8;
1583 SOFF_T(p,0,file_size); p += 8;
1584 SOFF_T(p,0,allocation_size); p += 8;
1585 SIVAL(p,0,nt_extmode); p += 4;
1586 q = p; p += 4; /* q is placeholder for name length */
1588 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1589 SIVAL(p,0,ea_size); /* Extended attributes */
1592 /* Clear the short name buffer. This is
1593 * IMPORTANT as not doing so will trigger
1594 * a Win2k client bug. JRA.
1596 if (!was_8_3 && check_mangled_names) {
1597 pstring mangled_name;
1598 pstrcpy(mangled_name, fname);
1599 mangle_map(mangled_name,True,True,
1601 mangled_name[12] = 0;
1602 len = srvstr_push(outbuf,
1603 SVAL(outbuf, smb_flg2),
1604 p+2, mangled_name, 24,
1605 STR_UPPER|STR_UNICODE);
1608 memset(p + 2 + len,'\0',24 - len);
1615 SSVAL(p,0,0); p += 2; /* Reserved ? */
1616 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1617 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1618 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p,
1619 fname, -1, 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 /* CIFS UNIX Extension. */
1631 case SMB_FIND_FILE_UNIX:
1632 case SMB_FIND_FILE_UNIX_INFO2:
1634 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1636 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1638 if (info_level == SMB_FIND_FILE_UNIX) {
1639 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1640 p = store_file_unix_basic(conn, p,
1642 len = srvstr_push(outbuf,
1643 SVAL(outbuf, smb_flg2),
1647 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1648 p = store_file_unix_basic_info2(conn, p,
1652 len = srvstr_push(outbuf,
1653 SVAL(outbuf, smb_flg2),
1655 SIVAL(nameptr, 0, len);
1659 SIVAL(p,0,0); /* Ensure any padding is null. */
1661 len = PTR_DIFF(p, pdata);
1662 len = (len + 3) & ~3;
1663 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1665 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1674 if (PTR_DIFF(p,pdata) > space_remaining) {
1675 /* Move the dirptr back to prev_dirpos */
1676 dptr_SeekDir(conn->dirptr, prev_dirpos);
1677 *out_of_space = True;
1678 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1679 return False; /* Not finished - just out of space */
1682 /* Setup the last entry pointer, as an offset from base_data */
1683 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1684 /* Advance the data pointer to the next slot */
1690 /****************************************************************************
1691 Reply to a TRANS2_FINDFIRST.
1692 ****************************************************************************/
1694 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1695 char **pparams, int total_params, char **ppdata, int total_data,
1696 unsigned int max_data_bytes)
1698 /* We must be careful here that we don't return more than the
1699 allowed number of data bytes. If this means returning fewer than
1700 maxentries then so be it. We assume that the redirector has
1701 enough room for the fixed number of parameter bytes it has
1703 char *params = *pparams;
1704 char *pdata = *ppdata;
1707 uint16 findfirst_flags;
1708 BOOL close_after_first;
1710 BOOL requires_resume_key;
1715 int last_entry_off=0;
1719 BOOL finished = False;
1720 BOOL dont_descend = False;
1721 BOOL out_of_space = False;
1722 int space_remaining;
1723 BOOL mask_contains_wcard = False;
1724 SMB_STRUCT_STAT sbuf;
1725 TALLOC_CTX *ea_ctx = NULL;
1726 struct ea_list *ea_list = NULL;
1727 NTSTATUS ntstatus = NT_STATUS_OK;
1729 if (total_params < 13) {
1730 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1733 dirtype = SVAL(params,0);
1734 maxentries = SVAL(params,2);
1735 findfirst_flags = SVAL(params,4);
1736 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1737 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1738 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1739 info_level = SVAL(params,6);
1741 *directory = *mask = 0;
1743 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1744 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1745 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1746 info_level, max_data_bytes));
1749 /* W2K3 seems to treat zero as 1. */
1753 switch (info_level) {
1754 case SMB_FIND_INFO_STANDARD:
1755 case SMB_FIND_EA_SIZE:
1756 case SMB_FIND_EA_LIST:
1757 case SMB_FIND_FILE_DIRECTORY_INFO:
1758 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1759 case SMB_FIND_FILE_NAMES_INFO:
1760 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1761 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1762 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1764 case SMB_FIND_FILE_UNIX:
1765 case SMB_FIND_FILE_UNIX_INFO2:
1766 if (!lp_unix_extensions()) {
1767 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1771 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1774 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), directory,
1775 params+12, sizeof(directory), total_params - 12,
1776 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1777 if (!NT_STATUS_IS_OK(ntstatus)) {
1778 return ERROR_NT(ntstatus);
1781 ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1782 if (!NT_STATUS_IS_OK(ntstatus)) {
1783 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1784 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1786 return ERROR_NT(ntstatus);
1789 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1790 if (!NT_STATUS_IS_OK(ntstatus)) {
1791 return ERROR_NT(ntstatus);
1793 ntstatus = check_name(conn, directory);
1794 if (!NT_STATUS_IS_OK(ntstatus)) {
1795 return ERROR_NT(ntstatus);
1798 p = strrchr_m(directory,'/');
1800 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1801 if((directory[0] == '.') && (directory[1] == '\0')) {
1803 mask_contains_wcard = True;
1805 pstrcpy(mask,directory);
1807 pstrcpy(directory,"./");
1813 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1815 if (info_level == SMB_FIND_EA_LIST) {
1818 if (total_data < 4) {
1819 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1822 ea_size = IVAL(pdata,0);
1823 if (ea_size != total_data) {
1824 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1825 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1826 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1829 if (!lp_ea_support(SNUM(conn))) {
1830 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1833 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1834 return ERROR_NT(NT_STATUS_NO_MEMORY);
1837 /* Pull out the list of names. */
1838 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1840 talloc_destroy(ea_ctx);
1841 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1845 *ppdata = (char *)SMB_REALLOC(
1846 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1847 if(*ppdata == NULL ) {
1848 talloc_destroy(ea_ctx);
1849 return ERROR_NT(NT_STATUS_NO_MEMORY);
1853 /* Realloc the params space */
1854 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1855 if (*pparams == NULL) {
1856 talloc_destroy(ea_ctx);
1857 return ERROR_NT(NT_STATUS_NO_MEMORY);
1861 /* Save the wildcard match and attribs we are using on this directory -
1862 needed as lanman2 assumes these are being saved between calls */
1864 ntstatus = dptr_create(conn,
1868 SVAL(inbuf,smb_pid),
1870 mask_contains_wcard,
1874 if (!NT_STATUS_IS_OK(ntstatus)) {
1875 talloc_destroy(ea_ctx);
1876 return ERROR_NT(ntstatus);
1879 dptr_num = dptr_dnum(conn->dirptr);
1880 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1882 /* We don't need to check for VOL here as this is returned by
1883 a different TRANS2 call. */
1885 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1886 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1887 dont_descend = True;
1890 space_remaining = max_data_bytes;
1891 out_of_space = False;
1893 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1894 BOOL got_exact_match = False;
1896 /* this is a heuristic to avoid seeking the dirptr except when
1897 absolutely necessary. It allows for a filename of about 40 chars */
1898 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1899 out_of_space = True;
1902 finished = !get_lanman2_dir_entry(conn,
1904 mask,dirtype,info_level,
1905 requires_resume_key,dont_descend,
1906 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1907 &last_entry_off, ea_list, ea_ctx);
1910 if (finished && out_of_space)
1913 if (!finished && !out_of_space)
1917 * As an optimisation if we know we aren't looking
1918 * for a wildcard name (ie. the name matches the wildcard exactly)
1919 * then we can finish on any (first) match.
1920 * This speeds up large directory searches. JRA.
1926 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1929 talloc_destroy(ea_ctx);
1931 /* Check if we can close the dirptr */
1932 if(close_after_first || (finished && close_if_end)) {
1933 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1934 dptr_close(&dptr_num);
1938 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1939 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1940 * the protocol level is less than NT1. Tested with smbclient. JRA.
1941 * This should fix the OS/2 client bug #2335.
1944 if(numentries == 0) {
1945 dptr_close(&dptr_num);
1946 if (Protocol < PROTOCOL_NT1) {
1947 return ERROR_DOS(ERRDOS,ERRnofiles);
1949 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1953 /* At this point pdata points to numentries directory entries. */
1955 /* Set up the return parameter block */
1956 SSVAL(params,0,dptr_num);
1957 SSVAL(params,2,numentries);
1958 SSVAL(params,4,finished);
1959 SSVAL(params,6,0); /* Never an EA error */
1960 SSVAL(params,8,last_entry_off);
1962 send_trans2_replies(inbuf, outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1964 if ((! *directory) && dptr_path(dptr_num))
1965 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1967 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1968 smb_fn_name(CVAL(inbuf,smb_com)),
1969 mask, directory, dirtype, numentries ) );
1972 * Force a name mangle here to ensure that the
1973 * mask as an 8.3 name is top of the mangled cache.
1974 * The reasons for this are subtle. Don't remove
1975 * this code unless you know what you are doing
1976 * (see PR#13758). JRA.
1979 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1980 mangle_map(mask, True, True, conn->params);
1985 /****************************************************************************
1986 Reply to a TRANS2_FINDNEXT.
1987 ****************************************************************************/
1989 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1990 char **pparams, int total_params, char **ppdata, int total_data,
1991 unsigned int max_data_bytes)
1993 /* We must be careful here that we don't return more than the
1994 allowed number of data bytes. If this means returning fewer than
1995 maxentries then so be it. We assume that the redirector has
1996 enough room for the fixed number of parameter bytes it has
1998 char *params = *pparams;
1999 char *pdata = *ppdata;
2004 uint16 findnext_flags;
2005 BOOL close_after_request;
2007 BOOL requires_resume_key;
2009 BOOL mask_contains_wcard = False;
2010 pstring resume_name;
2016 int i, last_entry_off=0;
2017 BOOL finished = False;
2018 BOOL dont_descend = False;
2019 BOOL out_of_space = False;
2020 int space_remaining;
2021 TALLOC_CTX *ea_ctx = NULL;
2022 struct ea_list *ea_list = NULL;
2023 NTSTATUS ntstatus = NT_STATUS_OK;
2025 if (total_params < 13) {
2026 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2029 dptr_num = SVAL(params,0);
2030 maxentries = SVAL(params,2);
2031 info_level = SVAL(params,4);
2032 resume_key = IVAL(params,6);
2033 findnext_flags = SVAL(params,10);
2034 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2035 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2036 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2037 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2039 *mask = *directory = *resume_name = 0;
2041 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), resume_name,
2042 params+12, sizeof(resume_name),
2043 total_params - 12, STR_TERMINATE, &ntstatus,
2044 &mask_contains_wcard);
2045 if (!NT_STATUS_IS_OK(ntstatus)) {
2046 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2047 complain (it thinks we're asking for the directory above the shared
2048 path or an invalid name). Catch this as the resume name is only compared, never used in
2049 a file access. JRA. */
2050 srvstr_pull(inbuf, SVAL(inbuf,smb_flg2),
2051 resume_name, params+12,
2052 sizeof(resume_name), total_params - 12,
2055 if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2056 return ERROR_NT(ntstatus);
2060 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2061 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2062 resume_key = %d resume name = %s continue=%d level = %d\n",
2063 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2064 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2067 /* W2K3 seems to treat zero as 1. */
2071 switch (info_level) {
2072 case SMB_FIND_INFO_STANDARD:
2073 case SMB_FIND_EA_SIZE:
2074 case SMB_FIND_EA_LIST:
2075 case SMB_FIND_FILE_DIRECTORY_INFO:
2076 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2077 case SMB_FIND_FILE_NAMES_INFO:
2078 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2079 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2080 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2082 case SMB_FIND_FILE_UNIX:
2083 case SMB_FIND_FILE_UNIX_INFO2:
2084 if (!lp_unix_extensions()) {
2085 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2089 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2092 if (info_level == SMB_FIND_EA_LIST) {
2095 if (total_data < 4) {
2096 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2099 ea_size = IVAL(pdata,0);
2100 if (ea_size != total_data) {
2101 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2102 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2103 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2106 if (!lp_ea_support(SNUM(conn))) {
2107 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2110 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2111 return ERROR_NT(NT_STATUS_NO_MEMORY);
2114 /* Pull out the list of names. */
2115 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2117 talloc_destroy(ea_ctx);
2118 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2122 *ppdata = (char *)SMB_REALLOC(
2123 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2124 if(*ppdata == NULL) {
2125 talloc_destroy(ea_ctx);
2126 return ERROR_NT(NT_STATUS_NO_MEMORY);
2131 /* Realloc the params space */
2132 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2133 if(*pparams == NULL ) {
2134 talloc_destroy(ea_ctx);
2135 return ERROR_NT(NT_STATUS_NO_MEMORY);
2140 /* Check that the dptr is valid */
2141 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2142 talloc_destroy(ea_ctx);
2143 return ERROR_DOS(ERRDOS,ERRnofiles);
2146 string_set(&conn->dirpath,dptr_path(dptr_num));
2148 /* Get the wildcard mask from the dptr */
2149 if((p = dptr_wcard(dptr_num))== NULL) {
2150 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2151 talloc_destroy(ea_ctx);
2152 return ERROR_DOS(ERRDOS,ERRnofiles);
2156 pstrcpy(directory,conn->dirpath);
2158 /* Get the attr mask from the dptr */
2159 dirtype = dptr_attr(dptr_num);
2161 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2162 dptr_num, mask, dirtype,
2164 dptr_TellDir(conn->dirptr)));
2166 /* We don't need to check for VOL here as this is returned by
2167 a different TRANS2 call. */
2169 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2170 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2171 dont_descend = True;
2174 space_remaining = max_data_bytes;
2175 out_of_space = False;
2178 * Seek to the correct position. We no longer use the resume key but
2179 * depend on the last file name instead.
2182 if(*resume_name && !continue_bit) {
2185 long current_pos = 0;
2187 * Remember, mangle_map is called by
2188 * get_lanman2_dir_entry(), so the resume name
2189 * could be mangled. Ensure we check the unmangled name.
2192 if (mangle_is_mangled(resume_name, conn->params)) {
2193 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2198 * Fix for NT redirector problem triggered by resume key indexes
2199 * changing between directory scans. We now return a resume key of 0
2200 * and instead look for the filename to continue from (also given
2201 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2202 * findfirst/findnext (as is usual) then the directory pointer
2203 * should already be at the correct place.
2206 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2207 } /* end if resume_name && !continue_bit */
2209 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2210 BOOL got_exact_match = False;
2212 /* this is a heuristic to avoid seeking the dirptr except when
2213 absolutely necessary. It allows for a filename of about 40 chars */
2214 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2215 out_of_space = True;
2218 finished = !get_lanman2_dir_entry(conn,
2220 mask,dirtype,info_level,
2221 requires_resume_key,dont_descend,
2222 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2223 &last_entry_off, ea_list, ea_ctx);
2226 if (finished && out_of_space)
2229 if (!finished && !out_of_space)
2233 * As an optimisation if we know we aren't looking
2234 * for a wildcard name (ie. the name matches the wildcard exactly)
2235 * then we can finish on any (first) match.
2236 * This speeds up large directory searches. JRA.
2242 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2245 talloc_destroy(ea_ctx);
2247 /* Check if we can close the dirptr */
2248 if(close_after_request || (finished && close_if_end)) {
2249 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2250 dptr_close(&dptr_num); /* This frees up the saved mask */
2253 /* Set up the return parameter block */
2254 SSVAL(params,0,numentries);
2255 SSVAL(params,2,finished);
2256 SSVAL(params,4,0); /* Never an EA error */
2257 SSVAL(params,6,last_entry_off);
2259 send_trans2_replies(inbuf, outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2261 if ((! *directory) && dptr_path(dptr_num))
2262 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2264 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2265 smb_fn_name(CVAL(inbuf,smb_com)),
2266 mask, directory, dirtype, numentries ) );
2271 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2273 E_md4hash(lp_servicename(SNUM(conn)),objid);
2277 /****************************************************************************
2278 Reply to a TRANS2_QFSINFO (query filesystem info).
2279 ****************************************************************************/
2281 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2282 char **pparams, int total_params, char **ppdata, int total_data,
2283 unsigned int max_data_bytes)
2286 char *params = *pparams;
2290 const char *vname = volume_label(SNUM(conn));
2291 int snum = SNUM(conn);
2292 char *fstype = lp_fstype(SNUM(conn));
2295 if (total_params < 2) {
2296 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2299 info_level = SVAL(params,0);
2301 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2303 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2304 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2305 return ERROR_DOS(ERRSRV,ERRinvdevice);
2308 *ppdata = (char *)SMB_REALLOC(
2309 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2310 if (*ppdata == NULL ) {
2311 return ERROR_NT(NT_STATUS_NO_MEMORY);
2315 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2317 switch (info_level) {
2318 case SMB_INFO_ALLOCATION:
2320 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2322 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2323 return(UNIXERROR(ERRHRD,ERRgeneral));
2326 block_size = lp_block_size(snum);
2327 if (bsize < block_size) {
2328 SMB_BIG_UINT factor = block_size/bsize;
2333 if (bsize > block_size) {
2334 SMB_BIG_UINT factor = bsize/block_size;
2339 bytes_per_sector = 512;
2340 sectors_per_unit = bsize/bytes_per_sector;
2342 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2343 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2344 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2346 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2347 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2348 SIVAL(pdata,l1_cUnit,dsize);
2349 SIVAL(pdata,l1_cUnitAvail,dfree);
2350 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2354 case SMB_INFO_VOLUME:
2355 /* Return volume name */
2357 * Add volume serial number - hash of a combination of
2358 * the called hostname and the service name.
2360 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2362 * Win2k3 and previous mess this up by sending a name length
2363 * one byte short. I believe only older clients (OS/2 Win9x) use
2364 * this call so try fixing this by adding a terminating null to
2365 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2367 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
2368 pdata+l2_vol_szVolLabel, vname,
2369 -1, STR_NOALIGN|STR_TERMINATE);
2370 SCVAL(pdata,l2_vol_cch,len);
2371 data_len = l2_vol_szVolLabel + len;
2372 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2373 (unsigned)st.st_ctime, len, vname));
2376 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2377 case SMB_FS_ATTRIBUTE_INFORMATION:
2380 #if defined(HAVE_SYS_QUOTAS)
2381 quota_flag = FILE_VOLUME_QUOTAS;
2384 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2385 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2386 FILE_SUPPORTS_OBJECT_IDS|
2387 FILE_UNICODE_ON_DISK|
2388 quota_flag); /* FS ATTRIBUTES */
2390 SIVAL(pdata,4,255); /* Max filename component length */
2391 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2392 and will think we can't do long filenames */
2393 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
2394 pdata+12, fstype, -1, STR_UNICODE);
2396 data_len = 12 + len;
2399 case SMB_QUERY_FS_LABEL_INFO:
2400 case SMB_FS_LABEL_INFORMATION:
2401 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
2402 pdata+4, vname, -1, 0);
2407 case SMB_QUERY_FS_VOLUME_INFO:
2408 case SMB_FS_VOLUME_INFORMATION:
2411 * Add volume serial number - hash of a combination of
2412 * the called hostname and the service name.
2414 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2415 (str_checksum(get_local_machine_name())<<16));
2417 /* Max label len is 32 characters. */
2418 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
2419 pdata+18, vname, -1, STR_UNICODE);
2420 SIVAL(pdata,12,len);
2423 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2424 (int)strlen(vname),vname, lp_servicename(snum)));
2427 case SMB_QUERY_FS_SIZE_INFO:
2428 case SMB_FS_SIZE_INFORMATION:
2430 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2432 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2433 return(UNIXERROR(ERRHRD,ERRgeneral));
2435 block_size = lp_block_size(snum);
2436 if (bsize < block_size) {
2437 SMB_BIG_UINT factor = block_size/bsize;
2442 if (bsize > block_size) {
2443 SMB_BIG_UINT factor = bsize/block_size;
2448 bytes_per_sector = 512;
2449 sectors_per_unit = bsize/bytes_per_sector;
2450 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2451 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2452 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2453 SBIG_UINT(pdata,0,dsize);
2454 SBIG_UINT(pdata,8,dfree);
2455 SIVAL(pdata,16,sectors_per_unit);
2456 SIVAL(pdata,20,bytes_per_sector);
2460 case SMB_FS_FULL_SIZE_INFORMATION:
2462 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2464 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2465 return(UNIXERROR(ERRHRD,ERRgeneral));
2467 block_size = lp_block_size(snum);
2468 if (bsize < block_size) {
2469 SMB_BIG_UINT factor = block_size/bsize;
2474 if (bsize > block_size) {
2475 SMB_BIG_UINT factor = bsize/block_size;
2480 bytes_per_sector = 512;
2481 sectors_per_unit = bsize/bytes_per_sector;
2482 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2483 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2484 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2485 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2486 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2487 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2488 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2489 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2493 case SMB_QUERY_FS_DEVICE_INFO:
2494 case SMB_FS_DEVICE_INFORMATION:
2496 SIVAL(pdata,0,0); /* dev type */
2497 SIVAL(pdata,4,0); /* characteristics */
2500 #ifdef HAVE_SYS_QUOTAS
2501 case SMB_FS_QUOTA_INFORMATION:
2503 * what we have to send --metze:
2505 * Unknown1: 24 NULL bytes
2506 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2507 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2508 * Quota Flags: 2 byte :
2509 * Unknown3: 6 NULL bytes
2513 * details for Quota Flags:
2515 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2516 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2517 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2518 * 0x0001 Enable Quotas: enable quota for this fs
2522 /* we need to fake up a fsp here,
2523 * because its not send in this call
2526 SMB_NTQUOTA_STRUCT quotas;
2529 ZERO_STRUCT(quotas);
2535 if (current_user.ut.uid != 0) {
2536 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2537 lp_servicename(SNUM(conn)),conn->user));
2538 return ERROR_DOS(ERRDOS,ERRnoaccess);
2541 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2542 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2543 return ERROR_DOS(ERRSRV,ERRerror);
2548 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2550 /* Unknown1 24 NULL bytes*/
2551 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2552 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2553 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2555 /* Default Soft Quota 8 bytes */
2556 SBIG_UINT(pdata,24,quotas.softlim);
2558 /* Default Hard Quota 8 bytes */
2559 SBIG_UINT(pdata,32,quotas.hardlim);
2561 /* Quota flag 2 bytes */
2562 SSVAL(pdata,40,quotas.qflags);
2564 /* Unknown3 6 NULL bytes */
2570 #endif /* HAVE_SYS_QUOTAS */
2571 case SMB_FS_OBJECTID_INFORMATION:
2573 unsigned char objid[16];
2574 memcpy(pdata,create_volume_objectid(conn, objid),16);
2580 * Query the version and capabilities of the CIFS UNIX extensions
2584 case SMB_QUERY_CIFS_UNIX_INFO:
2585 if (!lp_unix_extensions()) {
2586 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2589 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2590 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2591 /* We have POSIX ACLs, pathname and locking capability. */
2592 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2593 CIFS_UNIX_POSIX_ACLS_CAP|
2594 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2595 CIFS_UNIX_FCNTL_LOCKS_CAP|
2596 CIFS_UNIX_EXTATTR_CAP|
2597 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2598 /* Ensure we don't do this on signed or sealed data. */
2599 (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2603 case SMB_QUERY_POSIX_FS_INFO:
2606 vfs_statvfs_struct svfs;
2608 if (!lp_unix_extensions()) {
2609 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2612 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2616 SIVAL(pdata,0,svfs.OptimalTransferSize);
2617 SIVAL(pdata,4,svfs.BlockSize);
2618 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2619 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2620 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2621 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2622 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2623 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2624 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2626 } else if (rc == EOPNOTSUPP) {
2627 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2628 #endif /* EOPNOTSUPP */
2630 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2631 return ERROR_DOS(ERRSRV,ERRerror);
2636 case SMB_QUERY_POSIX_WHOAMI:
2642 if (!lp_unix_extensions()) {
2643 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2646 if (max_data_bytes < 40) {
2647 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2650 /* We ARE guest if global_sid_Builtin_Guests is
2651 * in our list of SIDs.
2653 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2654 current_user.nt_user_token)) {
2655 flags |= SMB_WHOAMI_GUEST;
2658 /* We are NOT guest if global_sid_Authenticated_Users
2659 * is in our list of SIDs.
2661 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2662 current_user.nt_user_token)) {
2663 flags &= ~SMB_WHOAMI_GUEST;
2666 /* NOTE: 8 bytes for UID/GID, irrespective of native
2667 * platform size. This matches
2668 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2670 data_len = 4 /* flags */
2677 + 4 /* pad/reserved */
2678 + (current_user.ut.ngroups * 8)
2680 + (current_user.nt_user_token->num_sids *
2684 SIVAL(pdata, 0, flags);
2685 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2686 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2687 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2690 if (data_len >= max_data_bytes) {
2691 /* Potential overflow, skip the GIDs and SIDs. */
2693 SIVAL(pdata, 24, 0); /* num_groups */
2694 SIVAL(pdata, 28, 0); /* num_sids */
2695 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2696 SIVAL(pdata, 36, 0); /* reserved */
2702 SIVAL(pdata, 24, current_user.ut.ngroups);
2704 current_user.nt_user_token->num_sids);
2706 /* We walk the SID list twice, but this call is fairly
2707 * infrequent, and I don't expect that it's performance
2708 * sensitive -- jpeach
2710 for (i = 0, sid_bytes = 0;
2711 i < current_user.nt_user_token->num_sids; ++i) {
2713 sid_size(¤t_user.nt_user_token->user_sids[i]);
2716 /* SID list byte count */
2717 SIVAL(pdata, 32, sid_bytes);
2719 /* 4 bytes pad/reserved - must be zero */
2720 SIVAL(pdata, 36, 0);
2724 for (i = 0; i < current_user.ut.ngroups; ++i) {
2725 SBIG_UINT(pdata, data_len,
2726 (SMB_BIG_UINT)current_user.ut.groups[i]);
2732 i < current_user.nt_user_token->num_sids; ++i) {
2734 sid_size(¤t_user.nt_user_token->user_sids[i]);
2736 sid_linearize(pdata + data_len, sid_len,
2737 ¤t_user.nt_user_token->user_sids[i]);
2738 data_len += sid_len;
2744 case SMB_MAC_QUERY_FS_INFO:
2746 * Thursby MAC extension... ONLY on NTFS filesystems
2747 * once we do streams then we don't need this
2749 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2751 SIVAL(pdata,84,0x100); /* Don't support mac... */
2756 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2760 send_trans2_replies(inbuf, outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2762 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2767 /****************************************************************************
2768 Reply to a TRANS2_SETFSINFO (set filesystem info).
2769 ****************************************************************************/
2771 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2772 char **pparams, int total_params, char **ppdata, int total_data,
2773 unsigned int max_data_bytes)
2775 char *pdata = *ppdata;
2776 char *params = *pparams;
2780 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2783 if (total_params < 4) {
2784 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2786 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2789 info_level = SVAL(params,2);
2791 switch(info_level) {
2792 case SMB_SET_CIFS_UNIX_INFO:
2794 uint16 client_unix_major;
2795 uint16 client_unix_minor;
2796 uint32 client_unix_cap_low;
2797 uint32 client_unix_cap_high;
2799 if (!lp_unix_extensions()) {
2800 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2803 /* There should be 12 bytes of capabilities set. */
2804 if (total_data < 8) {
2805 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2807 client_unix_major = SVAL(pdata,0);
2808 client_unix_minor = SVAL(pdata,2);
2809 client_unix_cap_low = IVAL(pdata,4);
2810 client_unix_cap_high = IVAL(pdata,8);
2811 /* Just print these values for now. */
2812 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2813 cap_low = 0x%x, cap_high = 0x%x\n",
2814 (unsigned int)client_unix_major,
2815 (unsigned int)client_unix_minor,
2816 (unsigned int)client_unix_cap_low,
2817 (unsigned int)client_unix_cap_high ));
2819 /* Here is where we must switch to posix pathname processing... */
2820 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2821 lp_set_posix_pathnames();
2822 mangle_change_to_posix();
2825 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2826 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2827 /* Client that knows how to do posix locks,
2828 * but not posix open/mkdir operations. Set a
2829 * default type for read/write checks. */
2831 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2836 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2839 size_t param_len = 0;
2840 size_t data_len = total_data;
2842 if (!lp_unix_extensions()) {
2843 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2846 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2848 status = srv_request_encryption_setup(conn,
2849 (unsigned char **)ppdata,
2851 (unsigned char **)pparams,
2855 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2856 error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
2857 } else if (!NT_STATUS_IS_OK(status)) {
2858 return ERROR_NT(status);
2861 send_trans2_replies(inbuf, outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes);
2863 if (NT_STATUS_IS_OK(status)) {
2864 /* Server-side transport encryption is now *on*. */
2865 status = srv_encryption_start(conn);
2866 if (!NT_STATUS_IS_OK(status)) {
2867 exit_server_cleanly("Failure in setting up encrypted transport");
2872 case SMB_FS_QUOTA_INFORMATION:
2874 files_struct *fsp = NULL;
2875 SMB_NTQUOTA_STRUCT quotas;
2877 ZERO_STRUCT(quotas);
2880 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2881 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2882 lp_servicename(SNUM(conn)),conn->user));
2883 return ERROR_DOS(ERRSRV,ERRaccess);
2886 /* note: normaly there're 48 bytes,
2887 * but we didn't use the last 6 bytes for now
2890 fsp = file_fsp(SVAL(params,0));
2891 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2892 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2893 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2896 if (total_data < 42) {
2897 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2899 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2902 /* unknown_1 24 NULL bytes in pdata*/
2904 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2905 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2906 #ifdef LARGE_SMB_OFF_T
2907 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2908 #else /* LARGE_SMB_OFF_T */
2909 if ((IVAL(pdata,28) != 0)&&
2910 ((quotas.softlim != 0xFFFFFFFF)||
2911 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2912 /* more than 32 bits? */
2913 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2915 #endif /* LARGE_SMB_OFF_T */
2917 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2918 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2919 #ifdef LARGE_SMB_OFF_T
2920 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2921 #else /* LARGE_SMB_OFF_T */
2922 if ((IVAL(pdata,36) != 0)&&
2923 ((quotas.hardlim != 0xFFFFFFFF)||
2924 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2925 /* more than 32 bits? */
2926 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2928 #endif /* LARGE_SMB_OFF_T */
2930 /* quota_flags 2 bytes **/
2931 quotas.qflags = SVAL(pdata,40);
2933 /* unknown_2 6 NULL bytes follow*/
2935 /* now set the quotas */
2936 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2937 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2938 return ERROR_DOS(ERRSRV,ERRerror);
2944 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2946 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2951 * sending this reply works fine,
2952 * but I'm not sure it's the same
2953 * like windows do...
2956 outsize = set_message(inbuf, outbuf,10,0,True);
2961 #if defined(HAVE_POSIX_ACLS)
2962 /****************************************************************************
2963 Utility function to count the number of entries in a POSIX acl.
2964 ****************************************************************************/
2966 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2968 unsigned int ace_count = 0;
2969 int entry_id = SMB_ACL_FIRST_ENTRY;
2970 SMB_ACL_ENTRY_T entry;
2972 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2974 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2975 entry_id = SMB_ACL_NEXT_ENTRY;
2982 /****************************************************************************
2983 Utility function to marshall a POSIX acl into wire format.
2984 ****************************************************************************/
2986 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2988 int entry_id = SMB_ACL_FIRST_ENTRY;
2989 SMB_ACL_ENTRY_T entry;
2991 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2992 SMB_ACL_TAG_T tagtype;
2993 SMB_ACL_PERMSET_T permset;
2994 unsigned char perms = 0;
2995 unsigned int own_grp;
2998 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2999 entry_id = SMB_ACL_NEXT_ENTRY;
3002 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3003 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3007 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3008 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3012 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3013 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3014 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3016 SCVAL(pdata,1,perms);
3019 case SMB_ACL_USER_OBJ:
3020 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3021 own_grp = (unsigned int)pst->st_uid;
3022 SIVAL(pdata,2,own_grp);
3027 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3029 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3032 own_grp = (unsigned int)*puid;
3033 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3034 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3035 SIVAL(pdata,2,own_grp);
3039 case SMB_ACL_GROUP_OBJ:
3040 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3041 own_grp = (unsigned int)pst->st_gid;
3042 SIVAL(pdata,2,own_grp);
3047 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3049 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3052 own_grp = (unsigned int)*pgid;
3053 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3054 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3055 SIVAL(pdata,2,own_grp);
3060 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3061 SIVAL(pdata,2,0xFFFFFFFF);
3062 SIVAL(pdata,6,0xFFFFFFFF);
3065 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3066 SIVAL(pdata,2,0xFFFFFFFF);
3067 SIVAL(pdata,6,0xFFFFFFFF);
3070 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3073 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3080 /****************************************************************************
3081 Store the FILE_UNIX_BASIC info.
3082 ****************************************************************************/
3084 static char *store_file_unix_basic(connection_struct *conn,
3087 const SMB_STRUCT_STAT *psbuf)
3089 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3090 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3092 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3095 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3098 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3099 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3100 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3103 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3107 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3111 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3114 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3118 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3122 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3125 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3129 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3136 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3137 * the chflags(2) (or equivalent) flags.
3139 * XXX: this really should be behind the VFS interface. To do this, we would
3140 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3141 * Each VFS module could then implement it's own mapping as appropriate for the
3142 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3144 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3148 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3152 { UF_IMMUTABLE, EXT_IMMUTABLE },
3156 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3160 { UF_HIDDEN, EXT_HIDDEN },
3163 /* Do not remove. We need to guarantee that this array has at least one
3164 * entry to build on HP-UX.
3170 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3171 uint32 *smb_fflags, uint32 *smb_fmask)
3173 #ifdef HAVE_STAT_ST_FLAGS
3176 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3177 *smb_fmask |= info2_flags_map[i].smb_fflag;
3178 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3179 *smb_fflags |= info2_flags_map[i].smb_fflag;
3182 #endif /* HAVE_STAT_ST_FLAGS */
3185 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3186 const uint32 smb_fflags,
3187 const uint32 smb_fmask,
3190 #ifdef HAVE_STAT_ST_FLAGS
3191 uint32 max_fmask = 0;
3194 *stat_fflags = psbuf->st_flags;
3196 /* For each flags requested in smb_fmask, check the state of the
3197 * corresponding flag in smb_fflags and set or clear the matching
3201 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3202 max_fmask |= info2_flags_map[i].smb_fflag;
3203 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3204 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3205 *stat_fflags |= info2_flags_map[i].stat_fflag;
3207 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3212 /* If smb_fmask is asking to set any bits that are not supported by
3213 * our flag mappings, we should fail.
3215 if ((smb_fmask & max_fmask) != smb_fmask) {
3222 #endif /* HAVE_STAT_ST_FLAGS */
3226 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3227 * of file flags and birth (create) time.
3229 static char *store_file_unix_basic_info2(connection_struct *conn,
3232 const SMB_STRUCT_STAT *psbuf)
3234 uint32 file_flags = 0;
3235 uint32 flags_mask = 0;
3237 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3239 /* Create (birth) time 64 bit */
3240 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3243 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3244 SIVAL(pdata, 0, file_flags); /* flags */
3245 SIVAL(pdata, 4, flags_mask); /* mask */
3251 /****************************************************************************
3252 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3253 ****************************************************************************/
3255 static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3256 unsigned int tran_call,
3257 char **pparams, int total_params, char **ppdata, int total_data,
3258 unsigned int max_data_bytes)
3260 char *params = *pparams;
3261 char *pdata = *ppdata;
3262 unsigned int data_size = 0;
3263 unsigned int param_size = 2;
3265 smb_np_struct *p_pipe = NULL;
3268 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3271 if (total_params < 4) {
3272 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3275 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3276 if (p_pipe == NULL) {
3277 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3280 info_level = SVAL(params,2);
3282 *pparams = (char *)SMB_REALLOC(*pparams,2);
3283 if (*pparams == NULL) {
3284 return ERROR_NT(NT_STATUS_NO_MEMORY);
3288 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3289 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3290 if (*ppdata == NULL ) {
3291 return ERROR_NT(NT_STATUS_NO_MEMORY);
3295 switch (info_level) {
3296 case SMB_FILE_STANDARD_INFORMATION:
3298 SOFF_T(pdata,0,4096LL);
3305 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3308 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3313 /****************************************************************************
3314 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3315 file name or file id).
3316 ****************************************************************************/
3318 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3319 unsigned int tran_call,
3320 char **pparams, int total_params, char **ppdata, int total_data,
3321 unsigned int max_data_bytes)
3323 char *params = *pparams;
3324 char *pdata = *ppdata;
3328 SMB_OFF_T file_size=0;
3329 SMB_BIG_UINT allocation_size=0;
3330 unsigned int data_size = 0;
3331 unsigned int param_size = 2;
3332 SMB_STRUCT_STAT sbuf;
3333 pstring fname, dos_fname;
3338 BOOL delete_pending = False;
3340 time_t create_time, mtime, atime;
3341 struct timespec create_time_ts, mtime_ts, atime_ts;
3342 files_struct *fsp = NULL;
3343 struct file_id fileid;
3344 TALLOC_CTX *data_ctx = NULL;
3345 struct ea_list *ea_list = NULL;
3346 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3347 char *lock_data = NULL;
3350 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3354 if (tran_call == TRANSACT2_QFILEINFO) {
3355 if (total_params < 4) {
3356 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3360 return call_trans2qpipeinfo(conn,
3373 fsp = file_fsp(SVAL(params,0));
3374 info_level = SVAL(params,2);
3376 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3378 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3379 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3382 if(fsp && (fsp->fake_file_handle)) {
3384 * This is actually for the QUOTA_FAKE_FILE --metze
3387 pstrcpy(fname, fsp->fsp_name);
3388 /* We know this name is ok, it's already passed the checks. */
3390 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3392 * This is actually a QFILEINFO on a directory
3393 * handle (returned from an NT SMB). NT5.0 seems
3394 * to do this call. JRA.
3396 /* We know this name is ok, it's already passed the checks. */
3397 pstrcpy(fname, fsp->fsp_name);
3399 if (INFO_LEVEL_IS_UNIX(info_level)) {
3400 /* Always do lstat for UNIX calls. */
3401 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3402 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3403 return UNIXERROR(ERRDOS,ERRbadpath);
3405 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3406 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3407 return UNIXERROR(ERRDOS,ERRbadpath);
3410 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3411 delete_pending = get_delete_on_close_flag(fileid);
3414 * Original code - this is an open file.
3416 CHECK_FSP(fsp,conn);
3418 pstrcpy(fname, fsp->fsp_name);
3419 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3420 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3421 return(UNIXERROR(ERRDOS,ERRbadfid));
3423 pos = fsp->fh->position_information;
3424 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3425 delete_pending = get_delete_on_close_flag(fileid);
3426 access_mask = fsp->access_mask;
3429 NTSTATUS status = NT_STATUS_OK;
3432 if (total_params < 7) {
3433 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3436 info_level = SVAL(params,0);
3438 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3440 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3441 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3444 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, ¶ms[6],
3445 sizeof(fname), total_params - 6,
3446 STR_TERMINATE, &status);
3447 if (!NT_STATUS_IS_OK(status)) {
3448 return ERROR_NT(status);
3451 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3452 if (!NT_STATUS_IS_OK(status)) {
3453 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3454 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3456 return ERROR_NT(status);
3459 status = unix_convert(conn, fname, False, NULL, &sbuf);
3460 if (!NT_STATUS_IS_OK(status)) {
3461 return ERROR_NT(status);
3463 status = check_name(conn, fname);
3464 if (!NT_STATUS_IS_OK(status)) {
3465 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3466 return ERROR_NT(status);
3469 if (INFO_LEVEL_IS_UNIX(info_level)) {
3470 /* Always do lstat for UNIX calls. */
3471 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3472 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3473 return UNIXERROR(ERRDOS,ERRbadpath);
3475 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3476 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3477 return UNIXERROR(ERRDOS,ERRbadpath);
3480 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3481 delete_pending = get_delete_on_close_flag(fileid);
3482 if (delete_pending) {
3483 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3487 nlink = sbuf.st_nlink;
3489 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3490 /* NTFS does not seem to count ".." */
3494 if ((nlink > 0) && delete_pending) {
3498 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3499 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3502 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3503 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3505 p = strrchr_m(fname,'/');
3511 mode = dos_mode(conn,fname,&sbuf);
3513 mode = FILE_ATTRIBUTE_NORMAL;
3515 fullpathname = fname;
3517 file_size = get_file_size(sbuf);
3519 /* Pull out any data sent here before we realloc. */
3520 switch (info_level) {
3521 case SMB_INFO_QUERY_EAS_FROM_LIST:
3523 /* Pull any EA list from the data portion. */
3526 if (total_data < 4) {
3527 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3529 ea_size = IVAL(pdata,0);
3531 if (total_data > 0 && ea_size != total_data) {
3532 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3533 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3534 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3537 if (!lp_ea_support(SNUM(conn))) {
3538 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3541 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3542 return ERROR_NT(NT_STATUS_NO_MEMORY);
3545 /* Pull out the list of names. */
3546 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3548 talloc_destroy(data_ctx);
3549 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3554 case SMB_QUERY_POSIX_LOCK:
3556 if (fsp == NULL || fsp->fh->fd == -1) {
3557 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3560 if (total_data != POSIX_LOCK_DATA_SIZE) {
3561 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3564 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3565 return ERROR_NT(NT_STATUS_NO_MEMORY);
3568 /* Copy the lock range data. */
3569 lock_data = (char *)TALLOC_MEMDUP(
3570 data_ctx, pdata, total_data);
3572 talloc_destroy(data_ctx);
3573 return ERROR_NT(NT_STATUS_NO_MEMORY);
3580 *pparams = (char *)SMB_REALLOC(*pparams,2);
3581 if (*pparams == NULL) {
3582 talloc_destroy(data_ctx);
3583 return ERROR_NT(NT_STATUS_NO_MEMORY);
3587 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3588 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3589 if (*ppdata == NULL ) {
3590 talloc_destroy(data_ctx);
3591 return ERROR_NT(NT_STATUS_NO_MEMORY);
3595 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3596 mtime_ts = get_mtimespec(&sbuf);
3597 atime_ts = get_atimespec(&sbuf);
3599 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3602 if (!null_timespec(fsp->pending_modtime)) {
3603 /* the pending modtime overrides the current modtime */
3604 mtime_ts = fsp->pending_modtime;
3608 /* Do we have this path open ? */
3609 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3610 fsp1 = file_find_di_first(fileid);
3611 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3612 /* the pending modtime overrides the current modtime */
3613 mtime_ts = fsp1->pending_modtime;
3615 if (fsp1 && fsp1->initial_allocation_size) {
3616 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3620 if (lp_dos_filetime_resolution(SNUM(conn))) {
3621 dos_filetime_timespec(&create_time_ts);
3622 dos_filetime_timespec(&mtime_ts);
3623 dos_filetime_timespec(&atime_ts);
3626 create_time = convert_timespec_to_time_t(create_time_ts);
3627 mtime = convert_timespec_to_time_t(mtime_ts);
3628 atime = convert_timespec_to_time_t(atime_ts);
3630 /* NT expects the name to be in an exact form of the *full*
3631 filename. See the trans2 torture test */
3632 if (strequal(base_name,".")) {
3633 pstrcpy(dos_fname, "\\");
3635 pstr_sprintf(dos_fname, "\\%s", fname);
3636 string_replace(dos_fname, '/', '\\');
3639 switch (info_level) {
3640 case SMB_INFO_STANDARD:
3641 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3643 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3644 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3645 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3646 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3647 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3648 SSVAL(pdata,l1_attrFile,mode);
3651 case SMB_INFO_QUERY_EA_SIZE:
3653 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3654 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3656 srv_put_dos_date2(pdata,0,create_time);
3657 srv_put_dos_date2(pdata,4,atime);
3658 srv_put_dos_date2(pdata,8,mtime); /* write time */
3659 SIVAL(pdata,12,(uint32)file_size);
3660 SIVAL(pdata,16,(uint32)allocation_size);
3661 SSVAL(pdata,20,mode);
3662 SIVAL(pdata,22,ea_size);
3666 case SMB_INFO_IS_NAME_VALID:
3667 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3668 if (tran_call == TRANSACT2_QFILEINFO) {
3669 /* os/2 needs this ? really ?*/
3670 return ERROR_DOS(ERRDOS,ERRbadfunc);
3676 case SMB_INFO_QUERY_EAS_FROM_LIST:
3678 size_t total_ea_len = 0;
3679 struct ea_list *ea_file_list = NULL;
3681 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3683 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3684 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3686 if (!ea_list || (total_ea_len > data_size)) {
3687 talloc_destroy(data_ctx);
3689 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3693 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3694 talloc_destroy(data_ctx);
3698 case SMB_INFO_QUERY_ALL_EAS:
3700 /* We have data_size bytes to put EA's into. */
3701 size_t total_ea_len = 0;
3703 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3705 data_ctx = talloc_init("ea_ctx");
3707 return ERROR_NT(NT_STATUS_NO_MEMORY);
3710 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3711 if (!ea_list || (total_ea_len > data_size)) {
3712 talloc_destroy(data_ctx);
3714 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3718 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3719 talloc_destroy(data_ctx);
3723 case SMB_FILE_BASIC_INFORMATION:
3724 case SMB_QUERY_FILE_BASIC_INFO:
3726 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3727 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3728 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3730 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3734 put_long_date_timespec(pdata,create_time_ts);
3735 put_long_date_timespec(pdata+8,atime_ts);
3736 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3737 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3738 SIVAL(pdata,32,mode);
3740 DEBUG(5,("SMB_QFBI - "));
3741 DEBUG(5,("create: %s ", ctime(&create_time)));
3742 DEBUG(5,("access: %s ", ctime(&atime)));
3743 DEBUG(5,("write: %s ", ctime(&mtime)));
3744 DEBUG(5,("change: %s ", ctime(&mtime)));
3745 DEBUG(5,("mode: %x\n", mode));
3748 case SMB_FILE_STANDARD_INFORMATION:
3749 case SMB_QUERY_FILE_STANDARD_INFO:
3751 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3753 SOFF_T(pdata,0,allocation_size);
3754 SOFF_T(pdata,8,file_size);
3755 SIVAL(pdata,16,nlink);
3756 SCVAL(pdata,20,delete_pending?1:0);
3757 SCVAL(pdata,21,(mode&aDIR)?1:0);
3758 SSVAL(pdata,22,0); /* Padding. */
3761 case SMB_FILE_EA_INFORMATION:
3762 case SMB_QUERY_FILE_EA_INFO:
3764 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3765 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3767 SIVAL(pdata,0,ea_size);
3771 /* Get the 8.3 name - used if NT SMB was negotiated. */
3772 case SMB_QUERY_FILE_ALT_NAME_INFO:
3773 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3777 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3778 pstrcpy(short_name,base_name);
3779 /* Mangle if not already 8.3 */
3780 if(!mangle_is_8_3(short_name, True, conn->params)) {
3781 mangle_map(short_name,True,True,conn->params);
3783 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
3784 pdata+4, short_name, -1,
3786 data_size = 4 + len;
3791 case SMB_QUERY_FILE_NAME_INFO:
3793 this must be *exactly* right for ACLs on mapped drives to work
3795 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
3796 pdata+4, dos_fname, -1, STR_UNICODE);
3797 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3798 data_size = 4 + len;
3802 case SMB_FILE_ALLOCATION_INFORMATION:
3803 case SMB_QUERY_FILE_ALLOCATION_INFO:
3804 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3806 SOFF_T(pdata,0,allocation_size);
3809 case SMB_FILE_END_OF_FILE_INFORMATION:
3810 case SMB_QUERY_FILE_END_OF_FILEINFO:
3811 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3813 SOFF_T(pdata,0,file_size);
3816 case SMB_QUERY_FILE_ALL_INFO:
3817 case SMB_FILE_ALL_INFORMATION:
3819 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3820 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3821 put_long_date_timespec(pdata,create_time_ts);
3822 put_long_date_timespec(pdata+8,atime_ts);
3823 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3824 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3825 SIVAL(pdata,32,mode);
3826 SIVAL(pdata,36,0); /* padding. */
3828 SOFF_T(pdata,0,allocation_size);
3829 SOFF_T(pdata,8,file_size);
3830 SIVAL(pdata,16,nlink);
3831 SCVAL(pdata,20,delete_pending);
3832 SCVAL(pdata,21,(mode&aDIR)?1:0);
3835 SIVAL(pdata,0,ea_size);
3836 pdata += 4; /* EA info */
3837 len = srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
3838 pdata+4, dos_fname, -1, STR_UNICODE);
3841 data_size = PTR_DIFF(pdata,(*ppdata));
3844 case SMB_FILE_INTERNAL_INFORMATION:
3845 /* This should be an index number - looks like
3848 I think this causes us to fail the IFSKIT
3849 BasicFileInformationTest. -tpot */
3851 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3852 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3853 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3857 case SMB_FILE_ACCESS_INFORMATION:
3858 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3859 SIVAL(pdata,0,access_mask);
3863 case SMB_FILE_NAME_INFORMATION:
3864 /* Pathname with leading '\'. */
3867 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3868 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3869 SIVAL(pdata,0,byte_len);
3870 data_size = 4 + byte_len;
3874 case SMB_FILE_DISPOSITION_INFORMATION:
3875 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3877 SCVAL(pdata,0,delete_pending);
3880 case SMB_FILE_POSITION_INFORMATION:
3881 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3883 SOFF_T(pdata,0,pos);
3886 case SMB_FILE_MODE_INFORMATION:
3887 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3888 SIVAL(pdata,0,mode);
3892 case SMB_FILE_ALIGNMENT_INFORMATION:
3893 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3894 SIVAL(pdata,0,0); /* No alignment needed. */
3900 * NT4 server just returns "invalid query" to this - if we try to answer
3901 * it then NTws gets a BSOD! (tridge).
3902 * W2K seems to want this. JRA.
3904 case SMB_QUERY_FILE_STREAM_INFO:
3906 case SMB_FILE_STREAM_INFORMATION:
3907 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3911 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3912 SIVAL(pdata,0,0); /* ??? */
3913 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3914 SOFF_T(pdata,8,file_size);
3915 SOFF_T(pdata,16,allocation_size);
3916 data_size = 24 + byte_len;
3920 case SMB_QUERY_COMPRESSION_INFO:
3921 case SMB_FILE_COMPRESSION_INFORMATION:
3922 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3923 SOFF_T(pdata,0,file_size);
3924 SIVAL(pdata,8,0); /* ??? */
3925 SIVAL(pdata,12,0); /* ??? */
3929 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3930 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3931 put_long_date_timespec(pdata,create_time_ts);
3932 put_long_date_timespec(pdata+8,atime_ts);
3933 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3934 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3935 SOFF_T(pdata,32,allocation_size);
3936 SOFF_T(pdata,40,file_size);
3937 SIVAL(pdata,48,mode);
3938 SIVAL(pdata,52,0); /* ??? */
3942 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3943 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3944 SIVAL(pdata,0,mode);
3950 * CIFS UNIX Extensions.
3953 case SMB_QUERY_FILE_UNIX_BASIC:
3955 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3956 data_size = PTR_DIFF(pdata,(*ppdata));
3960 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3962 for (i=0; i<100; i++)
3963 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3969 case SMB_QUERY_FILE_UNIX_INFO2:
3971 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3972 data_size = PTR_DIFF(pdata,(*ppdata));
3976 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3978 for (i=0; i<100; i++)
3979 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3985 case SMB_QUERY_FILE_UNIX_LINK:
3989 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3991 if(!S_ISLNK(sbuf.st_mode))
3992 return(UNIXERROR(ERRSRV,ERRbadlink));
3994 return(UNIXERROR(ERRDOS,ERRbadlink));
3996 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3998 return(UNIXERROR(ERRDOS,ERRnoaccess));
4000 len = srvstr_push(outbuf,
4001 SVAL(outbuf, smb_flg2),
4005 data_size = PTR_DIFF(pdata,(*ppdata));
4010 #if defined(HAVE_POSIX_ACLS)
4011 case SMB_QUERY_POSIX_ACL:
4013 SMB_ACL_T file_acl = NULL;
4014 SMB_ACL_T def_acl = NULL;
4015 uint16 num_file_acls = 0;
4016 uint16 num_def_acls = 0;
4018 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4019 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4021 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4024 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4025 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4027 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
4030 if (S_ISDIR(sbuf.st_mode)) {
4031 if (fsp && fsp->is_directory) {
4032 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4034 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4036 def_acl = free_empty_sys_acl(conn, def_acl);
4039 num_file_acls = count_acl_entries(conn, file_acl);
4040 num_def_acls = count_acl_entries(conn, def_acl);
4042 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4043 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4045 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4046 SMB_POSIX_ACL_HEADER_SIZE) ));
4048 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4051 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4053 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
4056 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4057 SSVAL(pdata,2,num_file_acls);
4058 SSVAL(pdata,4,num_def_acls);
4059 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4061 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4064 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4066 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4068 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4070 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4073 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4075 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4079 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4082 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4084 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4090 case SMB_QUERY_POSIX_LOCK:
4092 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4094 SMB_BIG_UINT offset;
4096 enum brl_type lock_type;
4098 if (total_data != POSIX_LOCK_DATA_SIZE) {
4099 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4102 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4103 case POSIX_LOCK_TYPE_READ:
4104 lock_type = READ_LOCK;
4106 case POSIX_LOCK_TYPE_WRITE:
4107 lock_type = WRITE_LOCK;
4109 case POSIX_LOCK_TYPE_UNLOCK:
4111 /* There's no point in asking for an unlock... */
4112 talloc_destroy(data_ctx);
4113 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4116 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4117 #if defined(HAVE_LONGLONG)
4118 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4119 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4120 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4121 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4122 #else /* HAVE_LONGLONG */
4123 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4124 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4125 #endif /* HAVE_LONGLONG */
4127 status = query_lock(fsp,
4134 if (ERROR_WAS_LOCK_DENIED(status)) {
4135 /* Here we need to report who has it locked... */
4136 data_size = POSIX_LOCK_DATA_SIZE;
4138 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4139 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4140 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4141 #if defined(HAVE_LONGLONG)
4142 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4143 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4144 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4145 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4146 #else /* HAVE_LONGLONG */
4147 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4148 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4149 #endif /* HAVE_LONGLONG */
4151 } else if (NT_STATUS_IS_OK(status)) {
4152 /* For success we just return a copy of what we sent
4153 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4154 data_size = POSIX_LOCK_DATA_SIZE;
4155 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4156 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4158 return ERROR_NT(status);
4164 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4167 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
4172 /****************************************************************************
4173 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4175 ****************************************************************************/
4177 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4179 SMB_STRUCT_STAT sbuf1, sbuf2;
4180 pstring last_component_oldname;
4181 pstring last_component_newname;
4182 NTSTATUS status = NT_STATUS_OK;
4187 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4188 if (!NT_STATUS_IS_OK(status)) {
4192 status = check_name(conn, oldname);
4193 if (!NT_STATUS_IS_OK(status)) {
4197 /* source must already exist. */
4198 if (!VALID_STAT(sbuf1)) {
4199 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4202 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4203 if (!NT_STATUS_IS_OK(status)) {
4207 status = check_name(conn, newname);
4208 if (!NT_STATUS_IS_OK(status)) {
4212 /* Disallow if newname already exists. */
4213 if (VALID_STAT(sbuf2)) {
4214 return NT_STATUS_OBJECT_NAME_COLLISION;
4217 /* No links from a directory. */
4218 if (S_ISDIR(sbuf1.st_mode)) {
4219 return NT_STATUS_FILE_IS_A_DIRECTORY;
4222 /* Ensure this is within the share. */
4223 status = check_reduced_name(conn, oldname);
4224 if (!NT_STATUS_IS_OK(status)) {
4228 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4230 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4231 status = map_nt_error_from_unix(errno);
4232 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4233 nt_errstr(status), newname, oldname));
4239 /****************************************************************************
4240 Deal with setting the time from any of the setfilepathinfo functions.
4241 ****************************************************************************/
4243 static NTSTATUS smb_set_file_time(connection_struct *conn,
4246 const SMB_STRUCT_STAT *psbuf,
4247 struct timespec ts[2])
4250 FILE_NOTIFY_CHANGE_LAST_ACCESS
4251 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4254 if (!VALID_STAT(*psbuf)) {
4255 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4258 /* get some defaults (no modifications) if any info is zero or -1. */
4259 if (null_timespec(ts[0])) {
4260 ts[0] = get_atimespec(psbuf);
4261 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4264 if (null_timespec(ts[1])) {
4265 ts[1] = get_mtimespec(psbuf);
4266 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4269 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4270 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4273 * Try and set the times of this file if
4274 * they are different from the current values.
4278 struct timespec mts = get_mtimespec(psbuf);
4279 struct timespec ats = get_atimespec(psbuf);
4280 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4281 return NT_STATUS_OK;
4287 * This was a setfileinfo on an open file.
4288 * NT does this a lot. We also need to
4289 * set the time here, as it can be read by
4290 * FindFirst/FindNext and with the patch for bug #2045
4291 * in smbd/fileio.c it ensures that this timestamp is
4292 * kept sticky even after a write. We save the request
4293 * away and will set it on file close and after a write. JRA.
4296 if (!null_timespec(ts[1])) {
4297 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4298 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4299 fsp_set_pending_modtime(fsp, ts[1]);
4303 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4305 if(file_ntimes(conn, fname, ts)!=0) {
4306 return map_nt_error_from_unix(errno);
4309 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4311 return NT_STATUS_OK;
4314 /****************************************************************************
4315 Deal with setting the dosmode from any of the setfilepathinfo functions.
4316 ****************************************************************************/
4318 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4320 SMB_STRUCT_STAT *psbuf,
4323 if (!VALID_STAT(*psbuf)) {
4324 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4328 if (S_ISDIR(psbuf->st_mode)) {
4335 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4337 /* check the mode isn't different, before changing it */
4338 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4340 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4341 fname, (unsigned int)dosmode ));
4343 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4344 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4345 fname, strerror(errno)));
4346 return map_nt_error_from_unix(errno);
4349 return NT_STATUS_OK;
4352 /****************************************************************************
4353 Deal with setting the size from any of the setfilepathinfo functions.
4354 ****************************************************************************/
4356 static NTSTATUS smb_set_file_size(connection_struct *conn,
4357 struct smb_request *req,
4360 SMB_STRUCT_STAT *psbuf,
4363 NTSTATUS status = NT_STATUS_OK;
4364 files_struct *new_fsp = NULL;
4366 if (!VALID_STAT(*psbuf)) {
4367 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4370 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4372 if (size == get_file_size(*psbuf)) {
4373 return NT_STATUS_OK;
4376 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4377 fname, (double)size ));
4379 if (fsp && fsp->fh->fd != -1) {
4380 /* Handle based call. */
4381 if (vfs_set_filelen(fsp, size) == -1) {
4382 return map_nt_error_from_unix(errno);
4384 return NT_STATUS_OK;
4387 status = open_file_ntcreate(conn, req, fname, psbuf,
4389 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4392 FILE_ATTRIBUTE_NORMAL,
4393 FORCE_OPLOCK_BREAK_TO_NONE,
4396 if (!NT_STATUS_IS_OK(status)) {
4397 /* NB. We check for open_was_deferred in the caller. */
4401 if (vfs_set_filelen(new_fsp, size) == -1) {
4402 status = map_nt_error_from_unix(errno);
4403 close_file(new_fsp,NORMAL_CLOSE);
4407 close_file(new_fsp,NORMAL_CLOSE);
4408 return NT_STATUS_OK;
4411 /****************************************************************************
4412 Deal with SMB_INFO_SET_EA.
4413 ****************************************************************************/
4415 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4421 struct ea_list *ea_list = NULL;
4422 TALLOC_CTX *ctx = NULL;
4423 NTSTATUS status = NT_STATUS_OK;
4425 if (total_data < 10) {
4427 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4428 length. They seem to have no effect. Bug #3212. JRA */
4430 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4431 /* We're done. We only get EA info in this call. */
4432 return NT_STATUS_OK;
4435 return NT_STATUS_INVALID_PARAMETER;
4438 if (IVAL(pdata,0) > total_data) {
4439 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4440 IVAL(pdata,0), (unsigned int)total_data));
4441 return NT_STATUS_INVALID_PARAMETER;
4444 ctx = talloc_init("SMB_INFO_SET_EA");
4446 return NT_STATUS_NO_MEMORY;
4448 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4450 talloc_destroy(ctx);
4451 return NT_STATUS_INVALID_PARAMETER;
4453 status = set_ea(conn, fsp, fname, ea_list);
4454 talloc_destroy(ctx);
4459 /****************************************************************************
4460 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4461 ****************************************************************************/
4463 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4468 SMB_STRUCT_STAT *psbuf)
4470 NTSTATUS status = NT_STATUS_OK;
4471 BOOL delete_on_close;
4474 if (total_data < 1) {
4475 return NT_STATUS_INVALID_PARAMETER;
4479 return NT_STATUS_INVALID_HANDLE;
4482 delete_on_close = (CVAL(pdata,0) ? True : False);
4483 dosmode = dos_mode(conn, fname, psbuf);
4485 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4486 "delete_on_close = %u\n",
4488 (unsigned int)dosmode,
4489 (unsigned int)delete_on_close ));
4491 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4493 if (!NT_STATUS_IS_OK(status)) {
4497 /* The set is across all open files on this dev/inode pair. */
4498 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4499 return NT_STATUS_ACCESS_DENIED;
4501 return NT_STATUS_OK;
4504 /****************************************************************************
4505 Deal with SMB_FILE_POSITION_INFORMATION.
4506 ****************************************************************************/
4508 static NTSTATUS smb_file_position_information(connection_struct *conn,
4513 SMB_BIG_UINT position_information;
4515 if (total_data < 8) {
4516 return NT_STATUS_INVALID_PARAMETER;
4520 /* Ignore on pathname based set. */
4521 return NT_STATUS_OK;
4524 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4525 #ifdef LARGE_SMB_OFF_T
4526 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4527 #else /* LARGE_SMB_OFF_T */
4528 if (IVAL(pdata,4) != 0) {
4529 /* more than 32 bits? */
4530 return NT_STATUS_INVALID_PARAMETER;
4532 #endif /* LARGE_SMB_OFF_T */
4534 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4535 fsp->fsp_name, (double)position_information ));
4536 fsp->fh->position_information = position_information;
4537 return NT_STATUS_OK;
4540 /****************************************************************************
4541 Deal with SMB_FILE_MODE_INFORMATION.
4542 ****************************************************************************/
4544 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4550 if (total_data < 4) {
4551 return NT_STATUS_INVALID_PARAMETER;
4553 mode = IVAL(pdata,0);
4554 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4555 return NT_STATUS_INVALID_PARAMETER;
4557 return NT_STATUS_OK;
4560 /****************************************************************************
4561 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4562 ****************************************************************************/
4564 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4570 pstring link_target;
4571 const char *newname = fname;
4572 NTSTATUS status = NT_STATUS_OK;
4574 /* Set a symbolic link. */
4575 /* Don't allow this if follow links is false. */
4577 if (total_data == 0) {
4578 return NT_STATUS_INVALID_PARAMETER;
4581 if (!lp_symlinks(SNUM(conn))) {
4582 return NT_STATUS_ACCESS_DENIED;
4585 srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), link_target, pdata,
4586 sizeof(link_target), total_data, STR_TERMINATE);
4588 /* !widelinks forces the target path to be within the share. */
4589 /* This means we can interpret the target as a pathname. */
4590 if (!lp_widelinks(SNUM(conn))) {
4592 char *last_dirp = NULL;
4594 if (*link_target == '/') {
4595 /* No absolute paths allowed. */
4596 return NT_STATUS_ACCESS_DENIED;
4598 pstrcpy(rel_name, newname);
4599 last_dirp = strrchr_m(rel_name, '/');
4601 last_dirp[1] = '\0';
4603 pstrcpy(rel_name, "./");
4605 pstrcat(rel_name, link_target);
4607 status = check_name(conn, rel_name);
4608 if (!NT_STATUS_IS_OK(status)) {
4613 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4614 newname, link_target ));
4616 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4617 return map_nt_error_from_unix(errno);
4620 return NT_STATUS_OK;
4623 /****************************************************************************
4624 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4625 ****************************************************************************/
4627 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4635 NTSTATUS status = NT_STATUS_OK;
4637 /* Set a hard link. */
4638 if (total_data == 0) {
4639 return NT_STATUS_INVALID_PARAMETER;
4642 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), oldname, pdata,
4643 sizeof(oldname), total_data, STR_TERMINATE, &status);
4644 if (!NT_STATUS_IS_OK(status)) {
4648 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4649 if (!NT_STATUS_IS_OK(status)) {
4653 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4656 return hardlink_internals(conn, oldname, fname);
4659 /****************************************************************************
4660 Deal with SMB_FILE_RENAME_INFORMATION.
4661 ****************************************************************************/
4663 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4664 struct smb_request *req,
4677 BOOL dest_has_wcard = False;
4678 NTSTATUS status = NT_STATUS_OK;
4681 if (total_data < 13) {
4682 return NT_STATUS_INVALID_PARAMETER;
4685 overwrite = (CVAL(pdata,0) ? True : False);
4686 root_fid = IVAL(pdata,4);
4687 len = IVAL(pdata,8);
4689 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4690 return NT_STATUS_INVALID_PARAMETER;
4693 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, &pdata[12],
4694 sizeof(newname), len, 0, &status,
4696 if (!NT_STATUS_IS_OK(status)) {
4700 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4701 if (!NT_STATUS_IS_OK(status)) {
4705 /* Check the new name has no '/' characters. */
4706 if (strchr_m(newname, '/')) {
4707 return NT_STATUS_NOT_SUPPORTED;
4710 /* Create the base directory. */
4711 pstrcpy(base_name, fname);
4712 p = strrchr_m(base_name, '/');
4716 pstrcpy(base_name, "./");
4718 /* Append the new name. */
4719 pstrcat(base_name, newname);
4722 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4723 fsp->fnum, fsp->fsp_name, base_name ));
4724 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4726 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4728 status = rename_internals(conn, req, fname, base_name, 0,
4729 overwrite, False, dest_has_wcard);
4735 /****************************************************************************
4736 Deal with SMB_SET_POSIX_ACL.
4737 ****************************************************************************/
4739 #if defined(HAVE_POSIX_ACLS)
4740 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4745 SMB_STRUCT_STAT *psbuf)
4747 uint16 posix_acl_version;
4748 uint16 num_file_acls;
4749 uint16 num_def_acls;
4750 BOOL valid_file_acls = True;
4751 BOOL valid_def_acls = True;
4753 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4754 return NT_STATUS_INVALID_PARAMETER;
4756 posix_acl_version = SVAL(pdata,0);
4757 num_file_acls = SVAL(pdata,2);
4758 num_def_acls = SVAL(pdata,4);
4760 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4761 valid_file_acls = False;
4765 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4766 valid_def_acls = False;
4770 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4771 return NT_STATUS_INVALID_PARAMETER;
4774 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4775 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4776 return NT_STATUS_INVALID_PARAMETER;
4779 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4780 fname ? fname : fsp->fsp_name,
4781 (unsigned int)num_file_acls,
4782 (unsigned int)num_def_acls));
4784 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4785 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4786 return map_nt_error_from_unix(errno);
4789 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4790 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4791 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4792 return map_nt_error_from_unix(errno);
4794 return NT_STATUS_OK;
4798 /****************************************************************************
4799 Deal with SMB_SET_POSIX_LOCK.
4800 ****************************************************************************/
4802 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4810 SMB_BIG_UINT offset;
4812 BOOL blocking_lock = False;
4813 enum brl_type lock_type;
4814 NTSTATUS status = NT_STATUS_OK;
4816 if (fsp == NULL || fsp->fh->fd == -1) {
4817 return NT_STATUS_INVALID_HANDLE;
4820 if (total_data != POSIX_LOCK_DATA_SIZE) {
4821 return NT_STATUS_INVALID_PARAMETER;
4824 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4825 case POSIX_LOCK_TYPE_READ:
4826 lock_type = READ_LOCK;
4828 case POSIX_LOCK_TYPE_WRITE:
4829 /* Return the right POSIX-mappable error code for files opened read-only. */
4830 if (!fsp->can_write) {
4831 return NT_STATUS_INVALID_HANDLE;
4833 lock_type = WRITE_LOCK;
4835 case POSIX_LOCK_TYPE_UNLOCK:
4836 lock_type = UNLOCK_LOCK;
4839 return NT_STATUS_INVALID_PARAMETER;
4842 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4843 blocking_lock = False;
4844 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4845 blocking_lock = True;
4847 return NT_STATUS_INVALID_PARAMETER;
4850 if (!lp_blocking_locks(SNUM(conn))) {
4851 blocking_lock = False;
4854 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4855 #if defined(HAVE_LONGLONG)
4856 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4857 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4858 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4859 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4860 #else /* HAVE_LONGLONG */
4861 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4862 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4863 #endif /* HAVE_LONGLONG */
4865 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4866 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4868 (unsigned int)lock_type,
4869 (unsigned int)lock_pid,
4873 if (lock_type == UNLOCK_LOCK) {
4874 status = do_unlock(smbd_messaging_context(),
4881 uint32 block_smbpid;
4883 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
4894 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4896 * A blocking lock was requested. Package up
4897 * this smb into a queued request and push it
4898 * onto the blocking lock queue.
4900 if(push_blocking_lock_request(br_lck,
4903 -1, /* infinite timeout. */
4911 TALLOC_FREE(br_lck);
4915 TALLOC_FREE(br_lck);
4921 /****************************************************************************
4922 Deal with SMB_INFO_STANDARD.
4923 ****************************************************************************/
4925 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4930 const SMB_STRUCT_STAT *psbuf)
4932 struct timespec ts[2];
4934 if (total_data < 12) {
4935 return NT_STATUS_INVALID_PARAMETER;
4939 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4941 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4943 DEBUG(10,("smb_set_info_standard: file %s\n",
4944 fname ? fname : fsp->fsp_name ));
4946 return smb_set_file_time(conn,
4953 /****************************************************************************
4954 Deal with SMB_SET_FILE_BASIC_INFO.
4955 ****************************************************************************/
4957 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4962 SMB_STRUCT_STAT *psbuf)
4964 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4965 struct timespec write_time;
4966 struct timespec changed_time;
4968 struct timespec ts[2];
4969 NTSTATUS status = NT_STATUS_OK;
4971 if (total_data < 36) {
4972 return NT_STATUS_INVALID_PARAMETER;
4975 /* Set the attributes */
4976 dosmode = IVAL(pdata,32);
4977 status = smb_set_file_dosmode(conn,
4981 if (!NT_STATUS_IS_OK(status)) {
4985 /* Ignore create time at offset pdata. */
4988 ts[0] = interpret_long_date(pdata+8);
4990 write_time = interpret_long_date(pdata+16);
4991 changed_time = interpret_long_date(pdata+24);
4994 ts[1] = timespec_min(&write_time, &changed_time);
4996 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5000 /* Prefer a defined time to an undefined one. */
5001 if (null_timespec(ts[1])) {
5002 ts[1] = null_timespec(write_time) ? changed_time : write_time;
5005 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5006 fname ? fname : fsp->fsp_name ));
5008 return smb_set_file_time(conn,
5015 /****************************************************************************
5016 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5017 ****************************************************************************/
5019 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5020 struct smb_request *req,
5025 SMB_STRUCT_STAT *psbuf)
5027 SMB_BIG_UINT allocation_size = 0;
5028 NTSTATUS status = NT_STATUS_OK;
5029 files_struct *new_fsp = NULL;
5031 if (!VALID_STAT(*psbuf)) {
5032 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5035 if (total_data < 8) {
5036 return NT_STATUS_INVALID_PARAMETER;
5039 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5040 #ifdef LARGE_SMB_OFF_T
5041 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5042 #else /* LARGE_SMB_OFF_T */
5043 if (IVAL(pdata,4) != 0) {
5044 /* more than 32 bits? */
5045 return NT_STATUS_INVALID_PARAMETER;
5047 #endif /* LARGE_SMB_OFF_T */
5049 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5050 fname, (double)allocation_size ));
5052 if (allocation_size) {
5053 allocation_size = smb_roundup(conn, allocation_size);
5056 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5057 fname, (double)allocation_size ));
5059 if (fsp && fsp->fh->fd != -1) {
5060 /* Open file handle. */
5061 /* Only change if needed. */
5062 if (allocation_size != get_file_size(*psbuf)) {
5063 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5064 return map_nt_error_from_unix(errno);
5067 /* But always update the time. */
5068 if (null_timespec(fsp->pending_modtime)) {
5070 * This is equivalent to a write. Ensure it's seen immediately
5071 * if there are no pending writes.
5073 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
5075 return NT_STATUS_OK;
5078 /* Pathname or stat or directory file. */
5080 status = open_file_ntcreate(conn, req, fname, psbuf,
5082 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5085 FILE_ATTRIBUTE_NORMAL,
5086 FORCE_OPLOCK_BREAK_TO_NONE,
5089 if (!NT_STATUS_IS_OK(status)) {
5090 /* NB. We check for open_was_deferred in the caller. */
5094 /* Only change if needed. */
5095 if (allocation_size != get_file_size(*psbuf)) {
5096 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5097 status = map_nt_error_from_unix(errno);
5098 close_file(new_fsp,NORMAL_CLOSE);
5103 /* Changing the allocation size should set the last mod time. */
5104 /* Don't need to call set_filetime as this will be flushed on
5107 fsp_set_pending_modtime(new_fsp, timespec_current());
5109 close_file(new_fsp,NORMAL_CLOSE);
5110 return NT_STATUS_OK;
5113 /****************************************************************************
5114 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5115 ****************************************************************************/
5117 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5118 struct smb_request *req,
5123 SMB_STRUCT_STAT *psbuf)
5127 if (total_data < 8) {
5128 return NT_STATUS_INVALID_PARAMETER;
5131 size = IVAL(pdata,0);
5132 #ifdef LARGE_SMB_OFF_T
5133 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5134 #else /* LARGE_SMB_OFF_T */
5135 if (IVAL(pdata,4) != 0) {
5136 /* more than 32 bits? */
5137 return NT_STATUS_INVALID_PARAMETER;
5139 #endif /* LARGE_SMB_OFF_T */
5140 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5141 "file %s to %.0f\n", fname, (double)size ));
5143 return smb_set_file_size(conn, req,
5150 /****************************************************************************
5151 Allow a UNIX info mknod.
5152 ****************************************************************************/
5154 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5158 SMB_STRUCT_STAT *psbuf)
5160 uint32 file_type = IVAL(pdata,56);
5161 #if defined(HAVE_MAKEDEV)
5162 uint32 dev_major = IVAL(pdata,60);
5163 uint32 dev_minor = IVAL(pdata,68);
5165 SMB_DEV_T dev = (SMB_DEV_T)0;
5166 uint32 raw_unixmode = IVAL(pdata,84);
5170 if (total_data < 100) {
5171 return NT_STATUS_INVALID_PARAMETER;
5174 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5175 if (!NT_STATUS_IS_OK(status)) {
5179 #if defined(HAVE_MAKEDEV)
5180 dev = makedev(dev_major, dev_minor);
5183 switch (file_type) {
5184 #if defined(S_IFIFO)
5185 case UNIX_TYPE_FIFO:
5186 unixmode |= S_IFIFO;
5189 #if defined(S_IFSOCK)
5190 case UNIX_TYPE_SOCKET:
5191 unixmode |= S_IFSOCK;
5194 #if defined(S_IFCHR)
5195 case UNIX_TYPE_CHARDEV:
5196 unixmode |= S_IFCHR;
5199 #if defined(S_IFBLK)
5200 case UNIX_TYPE_BLKDEV:
5201 unixmode |= S_IFBLK;
5205 return NT_STATUS_INVALID_PARAMETER;
5208 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5209 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5211 /* Ok - do the mknod. */
5212 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5213 return map_nt_error_from_unix(errno);
5216 /* If any of the other "set" calls fail we
5217 * don't want to end up with a half-constructed mknod.
5220 if (lp_inherit_perms(SNUM(conn))) {
5222 conn, parent_dirname(fname),
5226 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5227 status = map_nt_error_from_unix(errno);
5228 SMB_VFS_UNLINK(conn,fname);
5231 return NT_STATUS_OK;
5234 /****************************************************************************
5235 Deal with SMB_SET_FILE_UNIX_BASIC.
5236 ****************************************************************************/
5238 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5239 struct smb_request *req,
5244 SMB_STRUCT_STAT *psbuf)
5246 struct timespec ts[2];
5247 uint32 raw_unixmode;
5250 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5251 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5252 NTSTATUS status = NT_STATUS_OK;
5253 BOOL delete_on_fail = False;
5254 enum perm_type ptype;
5256 if (total_data < 100) {
5257 return NT_STATUS_INVALID_PARAMETER;
5260 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5261 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5262 size=IVAL(pdata,0); /* first 8 Bytes are size */
5263 #ifdef LARGE_SMB_OFF_T
5264 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5265 #else /* LARGE_SMB_OFF_T */
5266 if (IVAL(pdata,4) != 0) {
5267 /* more than 32 bits? */
5268 return NT_STATUS_INVALID_PARAMETER;
5270 #endif /* LARGE_SMB_OFF_T */
5273 ts[0] = interpret_long_date(pdata+24); /* access_time */
5274 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5275 set_owner = (uid_t)IVAL(pdata,40);
5276 set_grp = (gid_t)IVAL(pdata,48);
5277 raw_unixmode = IVAL(pdata,84);
5279 if (VALID_STAT(*psbuf)) {
5280 if (S_ISDIR(psbuf->st_mode)) {
5281 ptype = PERM_EXISTING_DIR;
5283 ptype = PERM_EXISTING_FILE;
5286 ptype = PERM_NEW_FILE;
5289 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5290 if (!NT_STATUS_IS_OK(status)) {
5294 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5295 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5296 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5298 if (!VALID_STAT(*psbuf)) {
5300 * The only valid use of this is to create character and block
5301 * devices, and named pipes. This is deprecated (IMHO) and
5302 * a new info level should be used for mknod. JRA.
5305 status = smb_unix_mknod(conn,
5310 if (!NT_STATUS_IS_OK(status)) {
5314 /* Ensure we don't try and change anything else. */
5315 raw_unixmode = SMB_MODE_NO_CHANGE;
5316 size = get_file_size(*psbuf);
5317 ts[0] = get_atimespec(psbuf);
5318 ts[1] = get_mtimespec(psbuf);
5320 * We continue here as we might want to change the
5323 delete_on_fail = True;
5327 /* Horrible backwards compatibility hack as an old server bug
5328 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5332 size = get_file_size(*psbuf);
5337 * Deal with the UNIX specific mode set.
5340 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5341 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5342 (unsigned int)unixmode, fname ));
5343 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5344 return map_nt_error_from_unix(errno);
5349 * Deal with the UNIX specific uid set.
5352 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5355 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5356 (unsigned int)set_owner, fname ));
5358 if (S_ISLNK(psbuf->st_mode)) {
5359 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5361 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5365 status = map_nt_error_from_unix(errno);
5366 if (delete_on_fail) {
5367 SMB_VFS_UNLINK(conn,fname);
5374 * Deal with the UNIX specific gid set.
5377 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5378 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5379 (unsigned int)set_owner, fname ));
5380 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5381 status = map_nt_error_from_unix(errno);
5382 if (delete_on_fail) {
5383 SMB_VFS_UNLINK(conn,fname);
5389 /* Deal with any size changes. */
5391 status = smb_set_file_size(conn, req,
5396 if (!NT_STATUS_IS_OK(status)) {
5400 /* Deal with any time changes. */
5402 return smb_set_file_time(conn,
5409 /****************************************************************************
5410 Deal with SMB_SET_FILE_UNIX_INFO2.
5411 ****************************************************************************/
5413 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5414 struct smb_request *req,
5419 SMB_STRUCT_STAT *psbuf)
5425 if (total_data < 116) {
5426 return NT_STATUS_INVALID_PARAMETER;
5429 /* Start by setting all the fields that are common between UNIX_BASIC
5432 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5434 if (!NT_STATUS_IS_OK(status)) {
5438 smb_fflags = IVAL(pdata, 108);
5439 smb_fmask = IVAL(pdata, 112);
5441 /* NB: We should only attempt to alter the file flags if the client
5442 * sends a non-zero mask.
5444 if (smb_fmask != 0) {
5445 int stat_fflags = 0;
5447 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5449 /* Client asked to alter a flag we don't understand. */
5450 return NT_STATUS_INVALID_PARAMETER;
5453 if (fsp && fsp->fh->fd != -1) {
5454 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5455 return NT_STATUS_NOT_SUPPORTED;
5457 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5458 return map_nt_error_from_unix(errno);
5463 /* XXX: need to add support for changing the create_time here. You
5464 * can do this for paths on Darwin with setattrlist(2). The right way
5465 * to hook this up is probably by extending the VFS utimes interface.
5468 return NT_STATUS_OK;
5471 /****************************************************************************
5472 Create a directory with POSIX semantics.
5473 ****************************************************************************/
5475 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5476 struct smb_request *req,
5480 SMB_STRUCT_STAT *psbuf,
5481 int *pdata_return_size)
5483 NTSTATUS status = NT_STATUS_OK;
5484 uint32 raw_unixmode = 0;
5485 uint32 mod_unixmode = 0;
5486 mode_t unixmode = (mode_t)0;
5487 files_struct *fsp = NULL;
5488 uint16 info_level_return = 0;
5490 char *pdata = *ppdata;
5492 if (total_data < 18) {
5493 return NT_STATUS_INVALID_PARAMETER;
5496 raw_unixmode = IVAL(pdata,8);
5497 /* Next 4 bytes are not yet defined. */
5499 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5500 if (!NT_STATUS_IS_OK(status)) {
5504 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5506 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5507 fname, (unsigned int)unixmode ));
5509 status = open_directory(conn, req,
5512 FILE_READ_ATTRIBUTES, /* Just a stat open */
5513 FILE_SHARE_NONE, /* Ignored for stat opens */
5520 if (NT_STATUS_IS_OK(status)) {
5521 close_file(fsp, NORMAL_CLOSE);
5524 info_level_return = SVAL(pdata,16);
5526 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5527 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5528 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5529 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5531 *pdata_return_size = 12;
5534 /* Realloc the data size */
5535 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5536 if (*ppdata == NULL) {
5537 *pdata_return_size = 0;
5538 return NT_STATUS_NO_MEMORY;
5542 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5543 SSVAL(pdata,2,0); /* No fnum. */
5544 SIVAL(pdata,4,info); /* Was directory created. */
5546 switch (info_level_return) {
5547 case SMB_QUERY_FILE_UNIX_BASIC:
5548 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5549 SSVAL(pdata,10,0); /* Padding. */
5550 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5552 case SMB_QUERY_FILE_UNIX_INFO2:
5553 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5554 SSVAL(pdata,10,0); /* Padding. */
5555 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5558 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5559 SSVAL(pdata,10,0); /* Padding. */
5566 /****************************************************************************
5567 Open/Create a file with POSIX semantics.
5568 ****************************************************************************/
5570 static NTSTATUS smb_posix_open(connection_struct *conn,
5571 struct smb_request *req,
5575 SMB_STRUCT_STAT *psbuf,
5576 int *pdata_return_size)
5578 BOOL extended_oplock_granted = False;
5579 char *pdata = *ppdata;
5581 uint32 wire_open_mode = 0;
5582 uint32 raw_unixmode = 0;
5583 uint32 mod_unixmode = 0;
5584 uint32 create_disp = 0;
5585 uint32 access_mask = 0;
5586 uint32 create_options = 0;
5587 NTSTATUS status = NT_STATUS_OK;
5588 mode_t unixmode = (mode_t)0;
5589 files_struct *fsp = NULL;
5590 int oplock_request = 0;
5592 uint16 info_level_return = 0;
5594 if (total_data < 18) {
5595 return NT_STATUS_INVALID_PARAMETER;
5598 flags = IVAL(pdata,0);
5599 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5600 if (oplock_request) {
5601 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5604 wire_open_mode = IVAL(pdata,4);
5606 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5607 return smb_posix_mkdir(conn, req,
5615 switch (wire_open_mode & SMB_ACCMODE) {
5617 access_mask = FILE_READ_DATA;
5620 access_mask = FILE_WRITE_DATA;
5623 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5626 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5627 (unsigned int)wire_open_mode ));
5628 return NT_STATUS_INVALID_PARAMETER;
5631 wire_open_mode &= ~SMB_ACCMODE;
5633 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5634 create_disp = FILE_CREATE;
5635 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5636 create_disp = FILE_OVERWRITE_IF;
5637 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5638 create_disp = FILE_OPEN_IF;
5640 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5641 (unsigned int)wire_open_mode ));
5642 return NT_STATUS_INVALID_PARAMETER;
5645 raw_unixmode = IVAL(pdata,8);
5646 /* Next 4 bytes are not yet defined. */
5648 status = unix_perms_from_wire(conn,
5651 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5654 if (!NT_STATUS_IS_OK(status)) {
5658 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5660 if (wire_open_mode & SMB_O_SYNC) {
5661 create_options |= FILE_WRITE_THROUGH;
5663 if (wire_open_mode & SMB_O_APPEND) {
5664 access_mask |= FILE_APPEND_DATA;
5666 if (wire_open_mode & SMB_O_DIRECT) {
5667 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5670 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5672 (unsigned int)wire_open_mode,
5673 (unsigned int)unixmode ));
5675 status = open_file_ntcreate(conn, req,
5679 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5681 0, /* no create options yet. */
5687 if (!NT_STATUS_IS_OK(status)) {
5691 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5692 extended_oplock_granted = True;
5695 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5696 extended_oplock_granted = True;
5699 info_level_return = SVAL(pdata,16);
5701 /* Allocate the correct return size. */
5703 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5704 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5705 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5706 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5708 *pdata_return_size = 12;
5711 /* Realloc the data size */
5712 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5713 if (*ppdata == NULL) {
5714 close_file(fsp,ERROR_CLOSE);
5715 *pdata_return_size = 0;
5716 return NT_STATUS_NO_MEMORY;
5720 if (extended_oplock_granted) {
5721 if (flags & REQUEST_BATCH_OPLOCK) {
5722 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5724 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5726 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5727 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5729 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5732 SSVAL(pdata,2,fsp->fnum);
5733 SIVAL(pdata,4,info); /* Was file created etc. */
5735 switch (info_level_return) {
5736 case SMB_QUERY_FILE_UNIX_BASIC:
5737 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5738 SSVAL(pdata,10,0); /* padding. */
5739 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5741 case SMB_QUERY_FILE_UNIX_INFO2:
5742 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5743 SSVAL(pdata,10,0); /* padding. */
5744 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5747 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5748 SSVAL(pdata,10,0); /* padding. */
5751 return NT_STATUS_OK;
5754 /****************************************************************************
5755 Delete a file with POSIX semantics.
5756 ****************************************************************************/
5758 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5759 struct smb_request *req,
5763 SMB_STRUCT_STAT *psbuf)
5765 NTSTATUS status = NT_STATUS_OK;
5766 files_struct *fsp = NULL;
5771 struct share_mode_lock *lck = NULL;
5773 if (total_data < 2) {
5774 return NT_STATUS_INVALID_PARAMETER;
5777 flags = SVAL(pdata,0);
5779 if (!VALID_STAT(*psbuf)) {
5780 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5783 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5784 !VALID_STAT_OF_DIR(*psbuf)) {
5785 return NT_STATUS_NOT_A_DIRECTORY;
5788 DEBUG(10,("smb_posix_unlink: %s %s\n",
5789 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5792 if (VALID_STAT_OF_DIR(*psbuf)) {
5793 status = open_directory(conn, req,
5797 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5800 FILE_FLAG_POSIX_SEMANTICS|0777,
5805 status = open_file_ntcreate(conn, req,
5809 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5812 FILE_FLAG_POSIX_SEMANTICS|0777,
5813 0, /* No oplock, but break existing ones. */
5818 if (!NT_STATUS_IS_OK(status)) {
5823 * Don't lie to client. If we can't really delete due to
5824 * non-POSIX opens return SHARING_VIOLATION.
5827 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
5829 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
5830 "lock for file %s\n", fsp->fsp_name));
5831 close_file(fsp, NORMAL_CLOSE);
5832 return NT_STATUS_INVALID_PARAMETER;
5836 * See if others still have the file open. If this is the case, then
5837 * don't delete. If all opens are POSIX delete we can set the delete
5838 * on close disposition.
5840 for (i=0; i<lck->num_share_modes; i++) {
5841 struct share_mode_entry *e = &lck->share_modes[i];
5842 if (is_valid_share_mode_entry(e)) {
5843 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
5846 /* Fail with sharing violation. */
5847 close_file(fsp, NORMAL_CLOSE);
5849 return NT_STATUS_SHARING_VIOLATION;
5854 * Set the delete on close.
5856 status = smb_set_file_disposition_info(conn,
5863 if (!NT_STATUS_IS_OK(status)) {
5864 close_file(fsp, NORMAL_CLOSE);
5869 return close_file(fsp, NORMAL_CLOSE);
5872 /****************************************************************************
5873 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5874 ****************************************************************************/
5876 static int call_trans2setfilepathinfo(connection_struct *conn,
5877 struct smb_request *req,
5878 char *inbuf, char *outbuf, int length,
5880 unsigned int tran_call,
5881 char **pparams, int total_params, char **ppdata, int total_data,
5882 unsigned int max_data_bytes)
5884 char *params = *pparams;
5885 char *pdata = *ppdata;
5887 SMB_STRUCT_STAT sbuf;
5889 files_struct *fsp = NULL;
5890 NTSTATUS status = NT_STATUS_OK;
5891 int data_return_size = 0;
5894 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5899 if (tran_call == TRANSACT2_SETFILEINFO) {
5900 if (total_params < 4) {
5901 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5904 fsp = file_fsp(SVAL(params,0));
5905 info_level = SVAL(params,2);
5907 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5909 * This is actually a SETFILEINFO on a directory
5910 * handle (returned from an NT SMB). NT5.0 seems
5911 * to do this call. JRA.
5913 pstrcpy(fname, fsp->fsp_name);
5914 if (INFO_LEVEL_IS_UNIX(info_level)) {
5915 /* Always do lstat for UNIX calls. */
5916 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
5917 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
5918 return UNIXERROR(ERRDOS,ERRbadpath);
5921 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5922 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5923 return UNIXERROR(ERRDOS,ERRbadpath);
5926 } else if (fsp && fsp->print_file) {
5928 * Doing a DELETE_ON_CLOSE should cancel a print job.
5930 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5931 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5933 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5936 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5939 return (UNIXERROR(ERRDOS,ERRbadpath));
5942 * Original code - this is an open file.
5944 CHECK_FSP(fsp,conn);
5946 pstrcpy(fname, fsp->fsp_name);
5948 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5949 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5950 return(UNIXERROR(ERRDOS,ERRbadfid));
5955 if (total_params < 7) {
5956 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5959 info_level = SVAL(params,0);
5960 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, ¶ms[6],
5961 sizeof(fname), total_params - 6, STR_TERMINATE,
5963 if (!NT_STATUS_IS_OK(status)) {
5964 return ERROR_NT(status);
5967 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5968 if (!NT_STATUS_IS_OK(status)) {
5969 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5970 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5972 return ERROR_NT(status);
5975 status = unix_convert(conn, fname, False, NULL, &sbuf);
5976 if (!NT_STATUS_IS_OK(status)) {
5977 return ERROR_NT(status);
5980 status = check_name(conn, fname);
5981 if (!NT_STATUS_IS_OK(status)) {
5982 return ERROR_NT(status);
5985 if (INFO_LEVEL_IS_UNIX(info_level)) {
5987 * For CIFS UNIX extensions the target name may not exist.
5990 /* Always do lstat for UNIX calls. */
5991 SMB_VFS_LSTAT(conn,fname,&sbuf);
5993 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
5994 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
5995 return UNIXERROR(ERRDOS,ERRbadpath);
5999 if (!CAN_WRITE(conn)) {
6000 return ERROR_DOS(ERRSRV,ERRaccess);
6003 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6004 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6007 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6008 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6010 /* Realloc the parameter size */
6011 *pparams = (char *)SMB_REALLOC(*pparams,2);
6012 if (*pparams == NULL) {
6013 return ERROR_NT(NT_STATUS_NO_MEMORY);
6019 if (fsp && !null_timespec(fsp->pending_modtime)) {
6020 /* the pending modtime overrides the current modtime */
6021 set_mtimespec(&sbuf, fsp->pending_modtime);
6024 switch (info_level) {
6026 case SMB_INFO_STANDARD:
6028 status = smb_set_info_standard(conn,
6037 case SMB_INFO_SET_EA:
6039 status = smb_info_set_ea(conn,
6047 case SMB_SET_FILE_BASIC_INFO:
6048 case SMB_FILE_BASIC_INFORMATION:
6050 status = smb_set_file_basic_info(conn,
6059 case SMB_FILE_ALLOCATION_INFORMATION:
6060 case SMB_SET_FILE_ALLOCATION_INFO:
6062 status = smb_set_file_allocation_info(conn, req,
6071 case SMB_FILE_END_OF_FILE_INFORMATION:
6072 case SMB_SET_FILE_END_OF_FILE_INFO:
6074 status = smb_set_file_end_of_file_info(conn, req,
6083 case SMB_FILE_DISPOSITION_INFORMATION:
6084 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6087 /* JRA - We used to just ignore this on a path ?
6088 * Shouldn't this be invalid level on a pathname
6091 if (tran_call != TRANSACT2_SETFILEINFO) {
6092 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6095 status = smb_set_file_disposition_info(conn,
6104 case SMB_FILE_POSITION_INFORMATION:
6106 status = smb_file_position_information(conn,
6113 /* From tridge Samba4 :
6114 * MODE_INFORMATION in setfileinfo (I have no
6115 * idea what "mode information" on a file is - it takes a value of 0,
6116 * 2, 4 or 6. What could it be?).
6119 case SMB_FILE_MODE_INFORMATION:
6121 status = smb_file_mode_information(conn,
6128 * CIFS UNIX extensions.
6131 case SMB_SET_FILE_UNIX_BASIC:
6133 status = smb_set_file_unix_basic(conn, req,
6142 case SMB_SET_FILE_UNIX_INFO2:
6144 status = smb_set_file_unix_info2(conn, req,
6153 case SMB_SET_FILE_UNIX_LINK:
6155 if (tran_call != TRANSACT2_SETPATHINFO) {
6156 /* We must have a pathname for this. */
6157 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6159 status = smb_set_file_unix_link(conn,
6167 case SMB_SET_FILE_UNIX_HLINK:
6169 if (tran_call != TRANSACT2_SETPATHINFO) {
6170 /* We must have a pathname for this. */
6171 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6173 status = smb_set_file_unix_hlink(conn,
6182 case SMB_FILE_RENAME_INFORMATION:
6184 status = smb_file_rename_information(conn, req,
6194 #if defined(HAVE_POSIX_ACLS)
6195 case SMB_SET_POSIX_ACL:
6197 status = smb_set_posix_acl(conn,
6207 case SMB_SET_POSIX_LOCK:
6209 if (tran_call != TRANSACT2_SETFILEINFO) {
6210 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6212 status = smb_set_posix_lock(conn,
6221 case SMB_POSIX_PATH_OPEN:
6223 if (tran_call != TRANSACT2_SETPATHINFO) {
6224 /* We must have a pathname for this. */
6225 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6228 status = smb_posix_open(conn, req,
6237 case SMB_POSIX_PATH_UNLINK:
6239 if (tran_call != TRANSACT2_SETPATHINFO) {
6240 /* We must have a pathname for this. */
6241 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6244 status = smb_posix_unlink(conn, req,
6253 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6257 if (!NT_STATUS_IS_OK(status)) {
6258 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6259 /* We have re-scheduled this call. */
6262 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6263 /* We have re-scheduled this call. */
6266 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6267 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6269 return ERROR_NT(status);
6273 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6278 /****************************************************************************
6279 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6280 ****************************************************************************/
6282 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6283 char **pparams, int total_params, char **ppdata, int total_data,
6284 unsigned int max_data_bytes)
6286 char *params = *pparams;
6287 char *pdata = *ppdata;
6289 SMB_STRUCT_STAT sbuf;
6290 NTSTATUS status = NT_STATUS_OK;
6291 struct ea_list *ea_list = NULL;
6293 if (!CAN_WRITE(conn))
6294 return ERROR_DOS(ERRSRV,ERRaccess);
6296 if (total_params < 5) {
6297 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6300 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory, ¶ms[4],
6301 sizeof(directory), total_params - 4, STR_TERMINATE,
6303 if (!NT_STATUS_IS_OK(status)) {
6304 return ERROR_NT(status);
6307 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6309 status = unix_convert(conn, directory, False, NULL, &sbuf);
6310 if (!NT_STATUS_IS_OK(status)) {
6311 return ERROR_NT(status);
6314 status = check_name(conn, directory);
6315 if (!NT_STATUS_IS_OK(status)) {
6316 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6317 return ERROR_NT(status);
6320 /* Any data in this call is an EA list. */
6321 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6322 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6326 * OS/2 workplace shell seems to send SET_EA requests of "null"
6327 * length (4 bytes containing IVAL 4).
6328 * They seem to have no effect. Bug #3212. JRA.
6331 if (total_data != 4) {
6332 if (total_data < 10) {
6333 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6336 if (IVAL(pdata,0) > total_data) {
6337 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6338 IVAL(pdata,0), (unsigned int)total_data));
6339 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6342 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6345 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6347 } else if (IVAL(pdata,0) != 4) {
6348 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6351 status = create_directory(conn, directory);
6353 if (!NT_STATUS_IS_OK(status)) {
6354 return ERROR_NT(status);
6357 /* Try and set any given EA. */
6359 status = set_ea(conn, NULL, directory, ea_list);
6360 if (!NT_STATUS_IS_OK(status)) {
6361 return ERROR_NT(status);
6365 /* Realloc the parameter and data sizes */
6366 *pparams = (char *)SMB_REALLOC(*pparams,2);
6367 if(*pparams == NULL) {
6368 return ERROR_NT(NT_STATUS_NO_MEMORY);
6374 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6379 /****************************************************************************
6380 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6381 We don't actually do this - we just send a null response.
6382 ****************************************************************************/
6384 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6385 char **pparams, int total_params, char **ppdata, int total_data,
6386 unsigned int max_data_bytes)
6388 static uint16 fnf_handle = 257;
6389 char *params = *pparams;
6392 if (total_params < 6) {
6393 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6396 info_level = SVAL(params,4);
6397 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6399 switch (info_level) {
6404 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6407 /* Realloc the parameter and data sizes */
6408 *pparams = (char *)SMB_REALLOC(*pparams,6);
6409 if (*pparams == NULL) {
6410 return ERROR_NT(NT_STATUS_NO_MEMORY);
6414 SSVAL(params,0,fnf_handle);
6415 SSVAL(params,2,0); /* No changes */
6416 SSVAL(params,4,0); /* No EA errors */
6423 send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6428 /****************************************************************************
6429 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6430 changes). Currently this does nothing.
6431 ****************************************************************************/
6433 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6434 char **pparams, int total_params, char **ppdata, int total_data,
6435 unsigned int max_data_bytes)
6437 char *params = *pparams;
6439 DEBUG(3,("call_trans2findnotifynext\n"));
6441 /* Realloc the parameter and data sizes */
6442 *pparams = (char *)SMB_REALLOC(*pparams,4);
6443 if (*pparams == NULL) {
6444 return ERROR_NT(NT_STATUS_NO_MEMORY);
6448 SSVAL(params,0,0); /* No changes */
6449 SSVAL(params,2,0); /* No EA errors */
6451 send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6456 /****************************************************************************
6457 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6458 ****************************************************************************/
6460 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6461 char **pparams, int total_params, char **ppdata, int total_data,
6462 unsigned int max_data_bytes)
6464 char *params = *pparams;
6467 int max_referral_level;
6468 NTSTATUS status = NT_STATUS_OK;
6470 DEBUG(10,("call_trans2getdfsreferral\n"));
6472 if (total_params < 3) {
6473 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6476 max_referral_level = SVAL(params,0);
6478 if(!lp_host_msdfs())
6479 return ERROR_DOS(ERRDOS,ERRbadfunc);
6481 srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), pathname, ¶ms[2],
6482 sizeof(pathname), total_params - 2, STR_TERMINATE);
6483 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6484 return ERROR_NT(status);
6486 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6487 send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6492 #define LMCAT_SPL 0x53
6493 #define LMFUNC_GETJOBID 0x60
6495 /****************************************************************************
6496 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6497 ****************************************************************************/
6499 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6500 char **pparams, int total_params, char **ppdata, int total_data,
6501 unsigned int max_data_bytes)
6503 char *pdata = *ppdata;
6504 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv15));
6506 /* check for an invalid fid before proceeding */
6509 return(ERROR_DOS(ERRDOS,ERRbadfid));
6511 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6512 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6513 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6514 if (*ppdata == NULL) {
6515 return ERROR_NT(NT_STATUS_NO_MEMORY);
6519 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6520 CAN ACCEPT THIS IN UNICODE. JRA. */
6522 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6523 srvstr_push( outbuf, SVAL(outbuf, smb_flg2), pdata + 2,
6524 global_myname(), 15,
6525 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6526 srvstr_push( outbuf, SVAL(outbuf, smb_flg2), pdata+18,
6527 lp_servicename(SNUM(conn)), 13,
6528 STR_ASCII|STR_TERMINATE); /* Service name */
6529 send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6532 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6533 return ERROR_DOS(ERRSRV,ERRerror);
6537 /****************************************************************************
6538 Reply to a SMBfindclose (stop trans2 directory search).
6539 ****************************************************************************/
6541 int reply_findclose(connection_struct *conn,
6542 char *inbuf,char *outbuf,int length,int bufsize)
6545 int dptr_num=SVALS(inbuf,smb_vwv0);
6546 START_PROFILE(SMBfindclose);
6548 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6550 dptr_close(&dptr_num);
6552 outsize = set_message(inbuf, outbuf,0,0,False);
6554 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6556 END_PROFILE(SMBfindclose);
6560 /****************************************************************************
6561 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6562 ****************************************************************************/
6564 int reply_findnclose(connection_struct *conn,
6565 char *inbuf,char *outbuf,int length,int bufsize)
6569 START_PROFILE(SMBfindnclose);
6571 dptr_num = SVAL(inbuf,smb_vwv0);
6573 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6575 /* We never give out valid handles for a
6576 findnotifyfirst - so any dptr_num is ok here.
6579 outsize = set_message(inbuf, outbuf,0,0,False);
6581 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6583 END_PROFILE(SMBfindnclose);
6587 static int handle_trans2(connection_struct *conn, struct smb_request *req,
6588 struct trans_state *state,
6589 char *inbuf, char *outbuf, int size, int bufsize)
6593 if (Protocol >= PROTOCOL_NT1) {
6594 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6597 /* Now we must call the relevant TRANS2 function */
6598 switch(state->call) {
6599 case TRANSACT2_OPEN:
6601 START_PROFILE(Trans2_open);
6602 outsize = call_trans2open(
6603 conn, req, inbuf, outbuf, bufsize,
6604 &state->param, state->total_param,
6605 &state->data, state->total_data,
6606 state->max_data_return);
6607 END_PROFILE(Trans2_open);
6611 case TRANSACT2_FINDFIRST:
6613 START_PROFILE(Trans2_findfirst);
6614 outsize = call_trans2findfirst(
6615 conn, inbuf, outbuf, bufsize,
6616 &state->param, state->total_param,
6617 &state->data, state->total_data,
6618 state->max_data_return);
6619 END_PROFILE(Trans2_findfirst);
6623 case TRANSACT2_FINDNEXT:
6625 START_PROFILE(Trans2_findnext);
6626 outsize = call_trans2findnext(
6627 conn, inbuf, outbuf, size, bufsize,
6628 &state->param, state->total_param,
6629 &state->data, state->total_data,
6630 state->max_data_return);
6631 END_PROFILE(Trans2_findnext);
6635 case TRANSACT2_QFSINFO:
6637 START_PROFILE(Trans2_qfsinfo);
6638 outsize = call_trans2qfsinfo(
6639 conn, inbuf, outbuf, size, bufsize,
6640 &state->param, state->total_param,
6641 &state->data, state->total_data,
6642 state->max_data_return);
6643 END_PROFILE(Trans2_qfsinfo);
6647 case TRANSACT2_SETFSINFO:
6649 START_PROFILE(Trans2_setfsinfo);
6650 outsize = call_trans2setfsinfo(
6651 conn, inbuf, outbuf, size, bufsize,
6652 &state->param, state->total_param,
6653 &state->data, state->total_data,
6654 state->max_data_return);
6655 END_PROFILE(Trans2_setfsinfo);
6659 case TRANSACT2_QPATHINFO:
6660 case TRANSACT2_QFILEINFO:
6662 START_PROFILE(Trans2_qpathinfo);
6663 outsize = call_trans2qfilepathinfo(
6664 conn, inbuf, outbuf, size, bufsize, state->call,
6665 &state->param, state->total_param,
6666 &state->data, state->total_data,
6667 state->max_data_return);
6668 END_PROFILE(Trans2_qpathinfo);
6672 case TRANSACT2_SETPATHINFO:
6673 case TRANSACT2_SETFILEINFO:
6675 START_PROFILE(Trans2_setpathinfo);
6676 outsize = call_trans2setfilepathinfo(
6677 conn, req, inbuf, outbuf, size, bufsize, state->call,
6678 &state->param, state->total_param,
6679 &state->data, state->total_data,
6680 state->max_data_return);
6681 END_PROFILE(Trans2_setpathinfo);
6685 case TRANSACT2_FINDNOTIFYFIRST:
6687 START_PROFILE(Trans2_findnotifyfirst);
6688 outsize = call_trans2findnotifyfirst(
6689 conn, inbuf, outbuf, size, bufsize,
6690 &state->param, state->total_param,
6691 &state->data, state->total_data,
6692 state->max_data_return);
6693 END_PROFILE(Trans2_findnotifyfirst);
6697 case TRANSACT2_FINDNOTIFYNEXT:
6699 START_PROFILE(Trans2_findnotifynext);
6700 outsize = call_trans2findnotifynext(
6701 conn, inbuf, outbuf, size, bufsize,
6702 &state->param, state->total_param,
6703 &state->data, state->total_data,
6704 state->max_data_return);
6705 END_PROFILE(Trans2_findnotifynext);
6709 case TRANSACT2_MKDIR:
6711 START_PROFILE(Trans2_mkdir);
6712 outsize = call_trans2mkdir(
6713 conn, inbuf, outbuf, size, bufsize,
6714 &state->param, state->total_param,
6715 &state->data, state->total_data,
6716 state->max_data_return);
6717 END_PROFILE(Trans2_mkdir);
6721 case TRANSACT2_GET_DFS_REFERRAL:
6723 START_PROFILE(Trans2_get_dfs_referral);
6724 outsize = call_trans2getdfsreferral(
6725 conn, inbuf, outbuf, size, bufsize,
6726 &state->param, state->total_param,
6727 &state->data, state->total_data,
6728 state->max_data_return);
6729 END_PROFILE(Trans2_get_dfs_referral);
6733 case TRANSACT2_IOCTL:
6735 START_PROFILE(Trans2_ioctl);
6736 outsize = call_trans2ioctl(
6737 conn, inbuf, outbuf, size, bufsize,
6738 &state->param, state->total_param,
6739 &state->data, state->total_data,
6740 state->max_data_return);
6741 END_PROFILE(Trans2_ioctl);
6746 /* Error in request */
6747 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6748 outsize = ERROR_DOS(ERRSRV,ERRerror);
6754 /****************************************************************************
6755 Reply to a SMBtrans2.
6756 ****************************************************************************/
6758 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6759 int size, int bufsize)
6762 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6763 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6764 unsigned int psoff = SVAL(inbuf, smb_psoff);
6765 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6766 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6767 struct trans_state *state;
6770 START_PROFILE(SMBtrans2);
6772 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6773 if (!NT_STATUS_IS_OK(result)) {
6774 DEBUG(2, ("Got invalid trans2 request: %s\n",
6775 nt_errstr(result)));
6776 END_PROFILE(SMBtrans2);
6777 return ERROR_NT(result);
6780 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6781 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
6782 && (tran_call != TRANSACT2_QFILEINFO)) {
6783 END_PROFILE(SMBtrans2);
6784 return ERROR_DOS(ERRSRV,ERRaccess);
6787 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6788 DEBUG(0, ("talloc failed\n"));
6789 END_PROFILE(SMBtrans2);
6790 return ERROR_NT(NT_STATUS_NO_MEMORY);
6793 state->cmd = SMBtrans2;
6795 state->mid = SVAL(inbuf, smb_mid);
6796 state->vuid = SVAL(inbuf, smb_uid);
6797 state->setup_count = SVAL(inbuf, smb_suwcnt);
6798 state->setup = NULL;
6799 state->total_param = SVAL(inbuf, smb_tpscnt);
6800 state->param = NULL;
6801 state->total_data = SVAL(inbuf, smb_tdscnt);
6803 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6804 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6805 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6806 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6807 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6809 state->call = tran_call;
6811 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6812 is so as a sanity check */
6813 if (state->setup_count != 1) {
6815 * Need to have rc=0 for ioctl to get job id for OS/2.
6816 * Network printing will fail if function is not successful.
6817 * Similar function in reply.c will be used if protocol
6818 * is LANMAN1.0 instead of LM1.2X002.
6819 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6820 * outbuf doesn't have to be set(only job id is used).
6822 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6823 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6824 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6825 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6827 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6828 DEBUG(2,("Transaction is %d\n",tran_call));
6830 END_PROFILE(SMBtrans2);
6831 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6835 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6838 if (state->total_data) {
6839 /* Can't use talloc here, the core routines do realloc on the
6840 * params and data. */
6841 state->data = (char *)SMB_MALLOC(state->total_data);
6842 if (state->data == NULL) {
6843 DEBUG(0,("reply_trans2: data malloc fail for %u "
6844 "bytes !\n", (unsigned int)state->total_data));
6846 END_PROFILE(SMBtrans2);
6847 return(ERROR_DOS(ERRDOS,ERRnomem));
6849 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6851 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6852 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6855 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6858 if (state->total_param) {
6859 /* Can't use talloc here, the core routines do realloc on the
6860 * params and data. */
6861 state->param = (char *)SMB_MALLOC(state->total_param);
6862 if (state->param == NULL) {
6863 DEBUG(0,("reply_trans: param malloc fail for %u "
6864 "bytes !\n", (unsigned int)state->total_param));
6865 SAFE_FREE(state->data);
6867 END_PROFILE(SMBtrans2);
6868 return(ERROR_DOS(ERRDOS,ERRnomem));
6870 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6872 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6873 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6876 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6879 state->received_data = dscnt;
6880 state->received_param = pscnt;
6882 if ((state->received_param == state->total_param) &&
6883 (state->received_data == state->total_data)) {
6885 struct smb_request req;
6886 init_smb_request(&req, (uint8 *)inbuf);
6888 outsize = handle_trans2(conn, &req, state, inbuf, outbuf,
6890 SAFE_FREE(state->data);
6891 SAFE_FREE(state->param);
6893 END_PROFILE(SMBtrans2);
6897 DLIST_ADD(conn->pending_trans, state);
6899 /* We need to send an interim response then receive the rest
6900 of the parameter/data bytes */
6901 outsize = set_message(inbuf, outbuf,0,0,False);
6903 END_PROFILE(SMBtrans2);
6908 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6909 SAFE_FREE(state->data);
6910 SAFE_FREE(state->param);
6912 END_PROFILE(SMBtrans2);
6913 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6917 /****************************************************************************
6918 Reply to a SMBtranss2
6919 ****************************************************************************/
6921 int reply_transs2(connection_struct *conn,
6922 char *inbuf,char *outbuf,int size,int bufsize)
6925 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6926 struct trans_state *state;
6927 struct smb_request req;
6929 START_PROFILE(SMBtranss2);
6933 for (state = conn->pending_trans; state != NULL;
6934 state = state->next) {
6935 if (state->mid == SVAL(inbuf,smb_mid)) {
6940 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6941 END_PROFILE(SMBtranss2);
6942 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6945 /* Revise state->total_param and state->total_data in case they have
6946 changed downwards */
6948 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6949 state->total_param = SVAL(inbuf, smb_tpscnt);
6950 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6951 state->total_data = SVAL(inbuf, smb_tdscnt);
6953 pcnt = SVAL(inbuf, smb_spscnt);
6954 poff = SVAL(inbuf, smb_spsoff);
6955 pdisp = SVAL(inbuf, smb_spsdisp);
6957 dcnt = SVAL(inbuf, smb_sdscnt);
6958 doff = SVAL(inbuf, smb_sdsoff);
6959 ddisp = SVAL(inbuf, smb_sdsdisp);
6961 state->received_param += pcnt;
6962 state->received_data += dcnt;
6964 if ((state->received_data > state->total_data) ||
6965 (state->received_param > state->total_param))
6969 if (pdisp+pcnt > state->total_param)
6971 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6973 if (pdisp > state->total_param)
6975 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6976 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6978 if (state->param + pdisp < state->param)
6981 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6986 if (ddisp+dcnt > state->total_data)
6988 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6990 if (ddisp > state->total_data)
6992 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6993 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6995 if (state->data + ddisp < state->data)
6998 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
7002 if ((state->received_param < state->total_param) ||
7003 (state->received_data < state->total_data)) {
7004 END_PROFILE(SMBtranss2);
7008 /* construct_reply_common has done us the favor to pre-fill the
7009 * command field with SMBtranss2 which is wrong :-)
7011 SCVAL(outbuf,smb_com,SMBtrans2);
7013 init_smb_request(&req, (uint8 *)inbuf);
7015 outsize = handle_trans2(conn, &req, state, inbuf, outbuf, size,
7018 DLIST_REMOVE(conn->pending_trans, state);
7019 SAFE_FREE(state->data);
7020 SAFE_FREE(state->param);
7024 END_PROFILE(SMBtranss2);
7025 return(ERROR_DOS(ERRSRV,ERRnosupport));
7028 END_PROFILE(SMBtranss2);
7033 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7034 DLIST_REMOVE(conn->pending_trans, state);
7035 SAFE_FREE(state->data);
7036 SAFE_FREE(state->param);
7038 END_PROFILE(SMBtranss2);
7039 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);