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, p, fname, -1, STR_TERMINATE);
1307 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1309 SCVAL(nameptr, -1, len - 2);
1311 SCVAL(nameptr, -1, 0);
1315 SCVAL(nameptr, -1, len - 1);
1317 SCVAL(nameptr, -1, 0);
1323 case SMB_FIND_EA_SIZE:
1324 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1325 if(requires_resume_key) {
1329 srv_put_dos_date2(p,0,create_date);
1330 srv_put_dos_date2(p,4,adate);
1331 srv_put_dos_date2(p,8,mdate);
1332 SIVAL(p,12,(uint32)file_size);
1333 SIVAL(p,16,(uint32)allocation_size);
1336 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1337 SIVAL(p,22,ea_size); /* Extended attributes */
1341 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1342 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1355 SCVAL(nameptr,0,len);
1357 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1360 case SMB_FIND_EA_LIST:
1362 struct ea_list *file_list = NULL;
1365 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1369 if(requires_resume_key) {
1373 srv_put_dos_date2(p,0,create_date);
1374 srv_put_dos_date2(p,4,adate);
1375 srv_put_dos_date2(p,8,mdate);
1376 SIVAL(p,12,(uint32)file_size);
1377 SIVAL(p,16,(uint32)allocation_size);
1379 p += 22; /* p now points to the EA area. */
1381 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1382 name_list = ea_list_union(name_list, file_list, &ea_len);
1384 /* We need to determine if this entry will fit in the space available. */
1385 /* Max string size is 255 bytes. */
1386 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1387 /* Move the dirptr back to prev_dirpos */
1388 dptr_SeekDir(conn->dirptr, prev_dirpos);
1389 *out_of_space = True;
1390 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1391 return False; /* Not finished - just out of space */
1394 /* Push the ea_data followed by the name. */
1395 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1397 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1398 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1411 SCVAL(nameptr,0,len);
1413 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1417 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1418 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1419 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1421 SIVAL(p,0,reskey); p += 4;
1422 put_long_date_timespec(p,create_date_ts); p += 8;
1423 put_long_date_timespec(p,adate_ts); p += 8;
1424 put_long_date_timespec(p,mdate_ts); p += 8;
1425 put_long_date_timespec(p,mdate_ts); p += 8;
1426 SOFF_T(p,0,file_size); p += 8;
1427 SOFF_T(p,0,allocation_size); p += 8;
1428 SIVAL(p,0,nt_extmode); p += 4;
1429 q = p; p += 4; /* q is placeholder for name length. */
1431 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1432 SIVAL(p,0,ea_size); /* Extended attributes */
1435 /* Clear the short name buffer. This is
1436 * IMPORTANT as not doing so will trigger
1437 * a Win2k client bug. JRA.
1439 if (!was_8_3 && check_mangled_names) {
1440 pstring mangled_name;
1441 pstrcpy(mangled_name, fname);
1442 mangle_map(mangled_name,True,True,
1444 mangled_name[12] = 0;
1445 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1447 memset(p + 2 + len,'\0',24 - len);
1454 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1457 SIVAL(p,0,0); /* Ensure any padding is null. */
1458 len = PTR_DIFF(p, pdata);
1459 len = (len + 3) & ~3;
1464 case SMB_FIND_FILE_DIRECTORY_INFO:
1465 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1467 SIVAL(p,0,reskey); p += 4;
1468 put_long_date_timespec(p,create_date_ts); p += 8;
1469 put_long_date_timespec(p,adate_ts); p += 8;
1470 put_long_date_timespec(p,mdate_ts); p += 8;
1471 put_long_date_timespec(p,mdate_ts); p += 8;
1472 SOFF_T(p,0,file_size); p += 8;
1473 SOFF_T(p,0,allocation_size); p += 8;
1474 SIVAL(p,0,nt_extmode); p += 4;
1475 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1478 SIVAL(p,0,0); /* Ensure any padding is null. */
1479 len = PTR_DIFF(p, pdata);
1480 len = (len + 3) & ~3;
1485 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1486 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1488 SIVAL(p,0,reskey); p += 4;
1489 put_long_date_timespec(p,create_date_ts); p += 8;
1490 put_long_date_timespec(p,adate_ts); p += 8;
1491 put_long_date_timespec(p,mdate_ts); p += 8;
1492 put_long_date_timespec(p,mdate_ts); p += 8;
1493 SOFF_T(p,0,file_size); p += 8;
1494 SOFF_T(p,0,allocation_size); p += 8;
1495 SIVAL(p,0,nt_extmode); p += 4;
1496 q = p; p += 4; /* q is placeholder for name length. */
1498 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1499 SIVAL(p,0,ea_size); /* Extended attributes */
1502 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1506 SIVAL(p,0,0); /* Ensure any padding is null. */
1507 len = PTR_DIFF(p, pdata);
1508 len = (len + 3) & ~3;
1513 case SMB_FIND_FILE_NAMES_INFO:
1514 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1516 SIVAL(p,0,reskey); p += 4;
1518 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1519 acl on a dir (tridge) */
1520 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1523 SIVAL(p,0,0); /* Ensure any padding is null. */
1524 len = PTR_DIFF(p, pdata);
1525 len = (len + 3) & ~3;
1530 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1531 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1533 SIVAL(p,0,reskey); p += 4;
1534 put_long_date_timespec(p,create_date_ts); p += 8;
1535 put_long_date_timespec(p,adate_ts); p += 8;
1536 put_long_date_timespec(p,mdate_ts); p += 8;
1537 put_long_date_timespec(p,mdate_ts); p += 8;
1538 SOFF_T(p,0,file_size); p += 8;
1539 SOFF_T(p,0,allocation_size); p += 8;
1540 SIVAL(p,0,nt_extmode); p += 4;
1541 q = p; p += 4; /* q is placeholder for name length. */
1543 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1544 SIVAL(p,0,ea_size); /* Extended attributes */
1547 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1548 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1549 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1550 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1553 SIVAL(p,0,0); /* Ensure any padding is null. */
1554 len = PTR_DIFF(p, pdata);
1555 len = (len + 3) & ~3;
1560 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1561 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1562 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1564 SIVAL(p,0,reskey); p += 4;
1565 put_long_date_timespec(p,create_date_ts); p += 8;
1566 put_long_date_timespec(p,adate_ts); p += 8;
1567 put_long_date_timespec(p,mdate_ts); p += 8;
1568 put_long_date_timespec(p,mdate_ts); p += 8;
1569 SOFF_T(p,0,file_size); p += 8;
1570 SOFF_T(p,0,allocation_size); p += 8;
1571 SIVAL(p,0,nt_extmode); p += 4;
1572 q = p; p += 4; /* q is placeholder for name length */
1574 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1575 SIVAL(p,0,ea_size); /* Extended attributes */
1578 /* Clear the short name buffer. This is
1579 * IMPORTANT as not doing so will trigger
1580 * a Win2k client bug. JRA.
1582 if (!was_8_3 && check_mangled_names) {
1583 pstring mangled_name;
1584 pstrcpy(mangled_name, fname);
1585 mangle_map(mangled_name,True,True,
1587 mangled_name[12] = 0;
1588 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1591 memset(p + 2 + len,'\0',24 - len);
1598 SSVAL(p,0,0); p += 2; /* Reserved ? */
1599 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1600 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1601 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1604 SIVAL(p,0,0); /* Ensure any padding is null. */
1605 len = PTR_DIFF(p, pdata);
1606 len = (len + 3) & ~3;
1611 /* CIFS UNIX Extension. */
1613 case SMB_FIND_FILE_UNIX:
1614 case SMB_FIND_FILE_UNIX_INFO2:
1616 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1618 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1620 if (info_level == SMB_FIND_FILE_UNIX) {
1621 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1622 p = store_file_unix_basic(conn, p,
1624 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1626 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1627 p = store_file_unix_basic_info2(conn, p,
1631 len = srvstr_push(outbuf, p, fname, -1, 0);
1632 SIVAL(nameptr, 0, len);
1636 SIVAL(p,0,0); /* Ensure any padding is null. */
1638 len = PTR_DIFF(p, pdata);
1639 len = (len + 3) & ~3;
1640 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1642 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1651 if (PTR_DIFF(p,pdata) > space_remaining) {
1652 /* Move the dirptr back to prev_dirpos */
1653 dptr_SeekDir(conn->dirptr, prev_dirpos);
1654 *out_of_space = True;
1655 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1656 return False; /* Not finished - just out of space */
1659 /* Setup the last entry pointer, as an offset from base_data */
1660 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1661 /* Advance the data pointer to the next slot */
1667 /****************************************************************************
1668 Reply to a TRANS2_FINDFIRST.
1669 ****************************************************************************/
1671 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1672 char **pparams, int total_params, char **ppdata, int total_data,
1673 unsigned int max_data_bytes)
1675 /* We must be careful here that we don't return more than the
1676 allowed number of data bytes. If this means returning fewer than
1677 maxentries then so be it. We assume that the redirector has
1678 enough room for the fixed number of parameter bytes it has
1680 char *params = *pparams;
1681 char *pdata = *ppdata;
1684 uint16 findfirst_flags;
1685 BOOL close_after_first;
1687 BOOL requires_resume_key;
1692 int last_entry_off=0;
1696 BOOL finished = False;
1697 BOOL dont_descend = False;
1698 BOOL out_of_space = False;
1699 int space_remaining;
1700 BOOL mask_contains_wcard = False;
1701 SMB_STRUCT_STAT sbuf;
1702 TALLOC_CTX *ea_ctx = NULL;
1703 struct ea_list *ea_list = NULL;
1704 NTSTATUS ntstatus = NT_STATUS_OK;
1706 if (total_params < 13) {
1707 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1710 dirtype = SVAL(params,0);
1711 maxentries = SVAL(params,2);
1712 findfirst_flags = SVAL(params,4);
1713 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1714 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1715 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1716 info_level = SVAL(params,6);
1718 *directory = *mask = 0;
1720 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1721 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1722 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1723 info_level, max_data_bytes));
1726 /* W2K3 seems to treat zero as 1. */
1730 switch (info_level) {
1731 case SMB_FIND_INFO_STANDARD:
1732 case SMB_FIND_EA_SIZE:
1733 case SMB_FIND_EA_LIST:
1734 case SMB_FIND_FILE_DIRECTORY_INFO:
1735 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1736 case SMB_FIND_FILE_NAMES_INFO:
1737 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1738 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1739 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1741 case SMB_FIND_FILE_UNIX:
1742 case SMB_FIND_FILE_UNIX_INFO2:
1743 if (!lp_unix_extensions()) {
1744 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1748 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1751 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), directory,
1752 params+12, sizeof(directory), total_params - 12,
1753 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1754 if (!NT_STATUS_IS_OK(ntstatus)) {
1755 return ERROR_NT(ntstatus);
1758 ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1759 if (!NT_STATUS_IS_OK(ntstatus)) {
1760 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1761 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1763 return ERROR_NT(ntstatus);
1766 ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1767 if (!NT_STATUS_IS_OK(ntstatus)) {
1768 return ERROR_NT(ntstatus);
1770 ntstatus = check_name(conn, directory);
1771 if (!NT_STATUS_IS_OK(ntstatus)) {
1772 return ERROR_NT(ntstatus);
1775 p = strrchr_m(directory,'/');
1777 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1778 if((directory[0] == '.') && (directory[1] == '\0')) {
1780 mask_contains_wcard = True;
1782 pstrcpy(mask,directory);
1784 pstrcpy(directory,"./");
1790 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1792 if (info_level == SMB_FIND_EA_LIST) {
1795 if (total_data < 4) {
1796 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1799 ea_size = IVAL(pdata,0);
1800 if (ea_size != total_data) {
1801 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1802 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1803 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1806 if (!lp_ea_support(SNUM(conn))) {
1807 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1810 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1811 return ERROR_NT(NT_STATUS_NO_MEMORY);
1814 /* Pull out the list of names. */
1815 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1817 talloc_destroy(ea_ctx);
1818 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1822 *ppdata = (char *)SMB_REALLOC(
1823 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1824 if(*ppdata == NULL ) {
1825 talloc_destroy(ea_ctx);
1826 return ERROR_NT(NT_STATUS_NO_MEMORY);
1830 /* Realloc the params space */
1831 *pparams = (char *)SMB_REALLOC(*pparams, 10);
1832 if (*pparams == NULL) {
1833 talloc_destroy(ea_ctx);
1834 return ERROR_NT(NT_STATUS_NO_MEMORY);
1838 /* Save the wildcard match and attribs we are using on this directory -
1839 needed as lanman2 assumes these are being saved between calls */
1841 ntstatus = dptr_create(conn,
1845 SVAL(inbuf,smb_pid),
1847 mask_contains_wcard,
1851 if (!NT_STATUS_IS_OK(ntstatus)) {
1852 talloc_destroy(ea_ctx);
1853 return ERROR_NT(ntstatus);
1856 dptr_num = dptr_dnum(conn->dirptr);
1857 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1859 /* We don't need to check for VOL here as this is returned by
1860 a different TRANS2 call. */
1862 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1863 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1864 dont_descend = True;
1867 space_remaining = max_data_bytes;
1868 out_of_space = False;
1870 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1871 BOOL got_exact_match = False;
1873 /* this is a heuristic to avoid seeking the dirptr except when
1874 absolutely necessary. It allows for a filename of about 40 chars */
1875 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1876 out_of_space = True;
1879 finished = !get_lanman2_dir_entry(conn,
1881 mask,dirtype,info_level,
1882 requires_resume_key,dont_descend,
1883 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1884 &last_entry_off, ea_list, ea_ctx);
1887 if (finished && out_of_space)
1890 if (!finished && !out_of_space)
1894 * As an optimisation if we know we aren't looking
1895 * for a wildcard name (ie. the name matches the wildcard exactly)
1896 * then we can finish on any (first) match.
1897 * This speeds up large directory searches. JRA.
1903 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1906 talloc_destroy(ea_ctx);
1908 /* Check if we can close the dirptr */
1909 if(close_after_first || (finished && close_if_end)) {
1910 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1911 dptr_close(&dptr_num);
1915 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1916 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1917 * the protocol level is less than NT1. Tested with smbclient. JRA.
1918 * This should fix the OS/2 client bug #2335.
1921 if(numentries == 0) {
1922 dptr_close(&dptr_num);
1923 if (Protocol < PROTOCOL_NT1) {
1924 return ERROR_DOS(ERRDOS,ERRnofiles);
1926 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1930 /* At this point pdata points to numentries directory entries. */
1932 /* Set up the return parameter block */
1933 SSVAL(params,0,dptr_num);
1934 SSVAL(params,2,numentries);
1935 SSVAL(params,4,finished);
1936 SSVAL(params,6,0); /* Never an EA error */
1937 SSVAL(params,8,last_entry_off);
1939 send_trans2_replies(inbuf, outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1941 if ((! *directory) && dptr_path(dptr_num))
1942 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1944 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1945 smb_fn_name(CVAL(inbuf,smb_com)),
1946 mask, directory, dirtype, numentries ) );
1949 * Force a name mangle here to ensure that the
1950 * mask as an 8.3 name is top of the mangled cache.
1951 * The reasons for this are subtle. Don't remove
1952 * this code unless you know what you are doing
1953 * (see PR#13758). JRA.
1956 if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1957 mangle_map(mask, True, True, conn->params);
1962 /****************************************************************************
1963 Reply to a TRANS2_FINDNEXT.
1964 ****************************************************************************/
1966 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1967 char **pparams, int total_params, char **ppdata, int total_data,
1968 unsigned int max_data_bytes)
1970 /* We must be careful here that we don't return more than the
1971 allowed number of data bytes. If this means returning fewer than
1972 maxentries then so be it. We assume that the redirector has
1973 enough room for the fixed number of parameter bytes it has
1975 char *params = *pparams;
1976 char *pdata = *ppdata;
1981 uint16 findnext_flags;
1982 BOOL close_after_request;
1984 BOOL requires_resume_key;
1986 BOOL mask_contains_wcard = False;
1987 pstring resume_name;
1993 int i, last_entry_off=0;
1994 BOOL finished = False;
1995 BOOL dont_descend = False;
1996 BOOL out_of_space = False;
1997 int space_remaining;
1998 TALLOC_CTX *ea_ctx = NULL;
1999 struct ea_list *ea_list = NULL;
2000 NTSTATUS ntstatus = NT_STATUS_OK;
2002 if (total_params < 13) {
2003 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2006 dptr_num = SVAL(params,0);
2007 maxentries = SVAL(params,2);
2008 info_level = SVAL(params,4);
2009 resume_key = IVAL(params,6);
2010 findnext_flags = SVAL(params,10);
2011 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2012 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2013 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2014 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2016 *mask = *directory = *resume_name = 0;
2018 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), resume_name,
2019 params+12, sizeof(resume_name),
2020 total_params - 12, STR_TERMINATE, &ntstatus,
2021 &mask_contains_wcard);
2022 if (!NT_STATUS_IS_OK(ntstatus)) {
2023 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2024 complain (it thinks we're asking for the directory above the shared
2025 path or an invalid name). Catch this as the resume name is only compared, never used in
2026 a file access. JRA. */
2027 srvstr_pull(inbuf, SVAL(inbuf,smb_flg2),
2028 resume_name, params+12,
2029 sizeof(resume_name), total_params - 12,
2032 if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2033 return ERROR_NT(ntstatus);
2037 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2038 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2039 resume_key = %d resume name = %s continue=%d level = %d\n",
2040 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2041 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2044 /* W2K3 seems to treat zero as 1. */
2048 switch (info_level) {
2049 case SMB_FIND_INFO_STANDARD:
2050 case SMB_FIND_EA_SIZE:
2051 case SMB_FIND_EA_LIST:
2052 case SMB_FIND_FILE_DIRECTORY_INFO:
2053 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2054 case SMB_FIND_FILE_NAMES_INFO:
2055 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2056 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2057 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2059 case SMB_FIND_FILE_UNIX:
2060 case SMB_FIND_FILE_UNIX_INFO2:
2061 if (!lp_unix_extensions()) {
2062 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2066 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2069 if (info_level == SMB_FIND_EA_LIST) {
2072 if (total_data < 4) {
2073 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2076 ea_size = IVAL(pdata,0);
2077 if (ea_size != total_data) {
2078 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2079 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2080 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2083 if (!lp_ea_support(SNUM(conn))) {
2084 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2087 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2088 return ERROR_NT(NT_STATUS_NO_MEMORY);
2091 /* Pull out the list of names. */
2092 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2094 talloc_destroy(ea_ctx);
2095 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2099 *ppdata = (char *)SMB_REALLOC(
2100 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2101 if(*ppdata == NULL) {
2102 talloc_destroy(ea_ctx);
2103 return ERROR_NT(NT_STATUS_NO_MEMORY);
2108 /* Realloc the params space */
2109 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2110 if(*pparams == NULL ) {
2111 talloc_destroy(ea_ctx);
2112 return ERROR_NT(NT_STATUS_NO_MEMORY);
2117 /* Check that the dptr is valid */
2118 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2119 talloc_destroy(ea_ctx);
2120 return ERROR_DOS(ERRDOS,ERRnofiles);
2123 string_set(&conn->dirpath,dptr_path(dptr_num));
2125 /* Get the wildcard mask from the dptr */
2126 if((p = dptr_wcard(dptr_num))== NULL) {
2127 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2128 talloc_destroy(ea_ctx);
2129 return ERROR_DOS(ERRDOS,ERRnofiles);
2133 pstrcpy(directory,conn->dirpath);
2135 /* Get the attr mask from the dptr */
2136 dirtype = dptr_attr(dptr_num);
2138 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2139 dptr_num, mask, dirtype,
2141 dptr_TellDir(conn->dirptr)));
2143 /* We don't need to check for VOL here as this is returned by
2144 a different TRANS2 call. */
2146 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2147 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2148 dont_descend = True;
2151 space_remaining = max_data_bytes;
2152 out_of_space = False;
2155 * Seek to the correct position. We no longer use the resume key but
2156 * depend on the last file name instead.
2159 if(*resume_name && !continue_bit) {
2162 long current_pos = 0;
2164 * Remember, mangle_map is called by
2165 * get_lanman2_dir_entry(), so the resume name
2166 * could be mangled. Ensure we check the unmangled name.
2169 if (mangle_is_mangled(resume_name, conn->params)) {
2170 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2175 * Fix for NT redirector problem triggered by resume key indexes
2176 * changing between directory scans. We now return a resume key of 0
2177 * and instead look for the filename to continue from (also given
2178 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2179 * findfirst/findnext (as is usual) then the directory pointer
2180 * should already be at the correct place.
2183 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2184 } /* end if resume_name && !continue_bit */
2186 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2187 BOOL got_exact_match = False;
2189 /* this is a heuristic to avoid seeking the dirptr except when
2190 absolutely necessary. It allows for a filename of about 40 chars */
2191 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2192 out_of_space = True;
2195 finished = !get_lanman2_dir_entry(conn,
2197 mask,dirtype,info_level,
2198 requires_resume_key,dont_descend,
2199 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2200 &last_entry_off, ea_list, ea_ctx);
2203 if (finished && out_of_space)
2206 if (!finished && !out_of_space)
2210 * As an optimisation if we know we aren't looking
2211 * for a wildcard name (ie. the name matches the wildcard exactly)
2212 * then we can finish on any (first) match.
2213 * This speeds up large directory searches. JRA.
2219 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2222 talloc_destroy(ea_ctx);
2224 /* Check if we can close the dirptr */
2225 if(close_after_request || (finished && close_if_end)) {
2226 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2227 dptr_close(&dptr_num); /* This frees up the saved mask */
2230 /* Set up the return parameter block */
2231 SSVAL(params,0,numentries);
2232 SSVAL(params,2,finished);
2233 SSVAL(params,4,0); /* Never an EA error */
2234 SSVAL(params,6,last_entry_off);
2236 send_trans2_replies(inbuf, outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2238 if ((! *directory) && dptr_path(dptr_num))
2239 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2241 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2242 smb_fn_name(CVAL(inbuf,smb_com)),
2243 mask, directory, dirtype, numentries ) );
2248 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2250 E_md4hash(lp_servicename(SNUM(conn)),objid);
2254 /****************************************************************************
2255 Reply to a TRANS2_QFSINFO (query filesystem info).
2256 ****************************************************************************/
2258 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2259 char **pparams, int total_params, char **ppdata, int total_data,
2260 unsigned int max_data_bytes)
2263 char *params = *pparams;
2267 const char *vname = volume_label(SNUM(conn));
2268 int snum = SNUM(conn);
2269 char *fstype = lp_fstype(SNUM(conn));
2272 if (total_params < 2) {
2273 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2276 info_level = SVAL(params,0);
2278 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2280 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2281 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2282 return ERROR_DOS(ERRSRV,ERRinvdevice);
2285 *ppdata = (char *)SMB_REALLOC(
2286 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2287 if (*ppdata == NULL ) {
2288 return ERROR_NT(NT_STATUS_NO_MEMORY);
2292 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2294 switch (info_level) {
2295 case SMB_INFO_ALLOCATION:
2297 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2299 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2300 return(UNIXERROR(ERRHRD,ERRgeneral));
2303 block_size = lp_block_size(snum);
2304 if (bsize < block_size) {
2305 SMB_BIG_UINT factor = block_size/bsize;
2310 if (bsize > block_size) {
2311 SMB_BIG_UINT factor = bsize/block_size;
2316 bytes_per_sector = 512;
2317 sectors_per_unit = bsize/bytes_per_sector;
2319 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2320 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2321 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2323 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2324 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2325 SIVAL(pdata,l1_cUnit,dsize);
2326 SIVAL(pdata,l1_cUnitAvail,dfree);
2327 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2331 case SMB_INFO_VOLUME:
2332 /* Return volume name */
2334 * Add volume serial number - hash of a combination of
2335 * the called hostname and the service name.
2337 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2339 * Win2k3 and previous mess this up by sending a name length
2340 * one byte short. I believe only older clients (OS/2 Win9x) use
2341 * this call so try fixing this by adding a terminating null to
2342 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2344 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2345 SCVAL(pdata,l2_vol_cch,len);
2346 data_len = l2_vol_szVolLabel + len;
2347 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2348 (unsigned)st.st_ctime, len, vname));
2351 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2352 case SMB_FS_ATTRIBUTE_INFORMATION:
2355 #if defined(HAVE_SYS_QUOTAS)
2356 quota_flag = FILE_VOLUME_QUOTAS;
2359 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2360 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2361 FILE_SUPPORTS_OBJECT_IDS|
2362 FILE_UNICODE_ON_DISK|
2363 quota_flag); /* FS ATTRIBUTES */
2365 SIVAL(pdata,4,255); /* Max filename component length */
2366 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2367 and will think we can't do long filenames */
2368 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2370 data_len = 12 + len;
2373 case SMB_QUERY_FS_LABEL_INFO:
2374 case SMB_FS_LABEL_INFORMATION:
2375 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2380 case SMB_QUERY_FS_VOLUME_INFO:
2381 case SMB_FS_VOLUME_INFORMATION:
2384 * Add volume serial number - hash of a combination of
2385 * the called hostname and the service name.
2387 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2388 (str_checksum(get_local_machine_name())<<16));
2390 /* Max label len is 32 characters. */
2391 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2392 SIVAL(pdata,12,len);
2395 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2396 (int)strlen(vname),vname, lp_servicename(snum)));
2399 case SMB_QUERY_FS_SIZE_INFO:
2400 case SMB_FS_SIZE_INFORMATION:
2402 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2404 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2405 return(UNIXERROR(ERRHRD,ERRgeneral));
2407 block_size = lp_block_size(snum);
2408 if (bsize < block_size) {
2409 SMB_BIG_UINT factor = block_size/bsize;
2414 if (bsize > block_size) {
2415 SMB_BIG_UINT factor = bsize/block_size;
2420 bytes_per_sector = 512;
2421 sectors_per_unit = bsize/bytes_per_sector;
2422 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2423 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2424 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2425 SBIG_UINT(pdata,0,dsize);
2426 SBIG_UINT(pdata,8,dfree);
2427 SIVAL(pdata,16,sectors_per_unit);
2428 SIVAL(pdata,20,bytes_per_sector);
2432 case SMB_FS_FULL_SIZE_INFORMATION:
2434 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2436 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2437 return(UNIXERROR(ERRHRD,ERRgeneral));
2439 block_size = lp_block_size(snum);
2440 if (bsize < block_size) {
2441 SMB_BIG_UINT factor = block_size/bsize;
2446 if (bsize > block_size) {
2447 SMB_BIG_UINT factor = bsize/block_size;
2452 bytes_per_sector = 512;
2453 sectors_per_unit = bsize/bytes_per_sector;
2454 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2455 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2456 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2457 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2458 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2459 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2460 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2461 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2465 case SMB_QUERY_FS_DEVICE_INFO:
2466 case SMB_FS_DEVICE_INFORMATION:
2468 SIVAL(pdata,0,0); /* dev type */
2469 SIVAL(pdata,4,0); /* characteristics */
2472 #ifdef HAVE_SYS_QUOTAS
2473 case SMB_FS_QUOTA_INFORMATION:
2475 * what we have to send --metze:
2477 * Unknown1: 24 NULL bytes
2478 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2479 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2480 * Quota Flags: 2 byte :
2481 * Unknown3: 6 NULL bytes
2485 * details for Quota Flags:
2487 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2488 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2489 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2490 * 0x0001 Enable Quotas: enable quota for this fs
2494 /* we need to fake up a fsp here,
2495 * because its not send in this call
2498 SMB_NTQUOTA_STRUCT quotas;
2501 ZERO_STRUCT(quotas);
2507 if (current_user.ut.uid != 0) {
2508 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2509 lp_servicename(SNUM(conn)),conn->user));
2510 return ERROR_DOS(ERRDOS,ERRnoaccess);
2513 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2514 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2515 return ERROR_DOS(ERRSRV,ERRerror);
2520 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2522 /* Unknown1 24 NULL bytes*/
2523 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2524 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2525 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2527 /* Default Soft Quota 8 bytes */
2528 SBIG_UINT(pdata,24,quotas.softlim);
2530 /* Default Hard Quota 8 bytes */
2531 SBIG_UINT(pdata,32,quotas.hardlim);
2533 /* Quota flag 2 bytes */
2534 SSVAL(pdata,40,quotas.qflags);
2536 /* Unknown3 6 NULL bytes */
2542 #endif /* HAVE_SYS_QUOTAS */
2543 case SMB_FS_OBJECTID_INFORMATION:
2545 unsigned char objid[16];
2546 memcpy(pdata,create_volume_objectid(conn, objid),16);
2552 * Query the version and capabilities of the CIFS UNIX extensions
2556 case SMB_QUERY_CIFS_UNIX_INFO:
2557 if (!lp_unix_extensions()) {
2558 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2561 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2562 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2563 /* We have POSIX ACLs, pathname and locking capability. */
2564 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2565 CIFS_UNIX_POSIX_ACLS_CAP|
2566 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2567 CIFS_UNIX_FCNTL_LOCKS_CAP|
2568 CIFS_UNIX_EXTATTR_CAP|
2569 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2570 /* Ensure we don't do this on signed or sealed data. */
2571 (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2575 case SMB_QUERY_POSIX_FS_INFO:
2578 vfs_statvfs_struct svfs;
2580 if (!lp_unix_extensions()) {
2581 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2584 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2588 SIVAL(pdata,0,svfs.OptimalTransferSize);
2589 SIVAL(pdata,4,svfs.BlockSize);
2590 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2591 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2592 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2593 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2594 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2595 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2596 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2598 } else if (rc == EOPNOTSUPP) {
2599 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2600 #endif /* EOPNOTSUPP */
2602 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2603 return ERROR_DOS(ERRSRV,ERRerror);
2608 case SMB_QUERY_POSIX_WHOAMI:
2614 if (!lp_unix_extensions()) {
2615 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2618 if (max_data_bytes < 40) {
2619 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2622 /* We ARE guest if global_sid_Builtin_Guests is
2623 * in our list of SIDs.
2625 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2626 current_user.nt_user_token)) {
2627 flags |= SMB_WHOAMI_GUEST;
2630 /* We are NOT guest if global_sid_Authenticated_Users
2631 * is in our list of SIDs.
2633 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2634 current_user.nt_user_token)) {
2635 flags &= ~SMB_WHOAMI_GUEST;
2638 /* NOTE: 8 bytes for UID/GID, irrespective of native
2639 * platform size. This matches
2640 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2642 data_len = 4 /* flags */
2649 + 4 /* pad/reserved */
2650 + (current_user.ut.ngroups * 8)
2652 + (current_user.nt_user_token->num_sids *
2656 SIVAL(pdata, 0, flags);
2657 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2658 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2659 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2662 if (data_len >= max_data_bytes) {
2663 /* Potential overflow, skip the GIDs and SIDs. */
2665 SIVAL(pdata, 24, 0); /* num_groups */
2666 SIVAL(pdata, 28, 0); /* num_sids */
2667 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2668 SIVAL(pdata, 36, 0); /* reserved */
2674 SIVAL(pdata, 24, current_user.ut.ngroups);
2676 current_user.nt_user_token->num_sids);
2678 /* We walk the SID list twice, but this call is fairly
2679 * infrequent, and I don't expect that it's performance
2680 * sensitive -- jpeach
2682 for (i = 0, sid_bytes = 0;
2683 i < current_user.nt_user_token->num_sids; ++i) {
2685 sid_size(¤t_user.nt_user_token->user_sids[i]);
2688 /* SID list byte count */
2689 SIVAL(pdata, 32, sid_bytes);
2691 /* 4 bytes pad/reserved - must be zero */
2692 SIVAL(pdata, 36, 0);
2696 for (i = 0; i < current_user.ut.ngroups; ++i) {
2697 SBIG_UINT(pdata, data_len,
2698 (SMB_BIG_UINT)current_user.ut.groups[i]);
2704 i < current_user.nt_user_token->num_sids; ++i) {
2706 sid_size(¤t_user.nt_user_token->user_sids[i]);
2708 sid_linearize(pdata + data_len, sid_len,
2709 ¤t_user.nt_user_token->user_sids[i]);
2710 data_len += sid_len;
2716 case SMB_MAC_QUERY_FS_INFO:
2718 * Thursby MAC extension... ONLY on NTFS filesystems
2719 * once we do streams then we don't need this
2721 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2723 SIVAL(pdata,84,0x100); /* Don't support mac... */
2728 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2732 send_trans2_replies(inbuf, outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2734 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2739 /****************************************************************************
2740 Reply to a TRANS2_SETFSINFO (set filesystem info).
2741 ****************************************************************************/
2743 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2744 char **pparams, int total_params, char **ppdata, int total_data,
2745 unsigned int max_data_bytes)
2747 char *pdata = *ppdata;
2748 char *params = *pparams;
2752 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2755 if (total_params < 4) {
2756 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2758 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2761 info_level = SVAL(params,2);
2763 switch(info_level) {
2764 case SMB_SET_CIFS_UNIX_INFO:
2766 uint16 client_unix_major;
2767 uint16 client_unix_minor;
2768 uint32 client_unix_cap_low;
2769 uint32 client_unix_cap_high;
2771 if (!lp_unix_extensions()) {
2772 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2775 /* There should be 12 bytes of capabilities set. */
2776 if (total_data < 8) {
2777 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2779 client_unix_major = SVAL(pdata,0);
2780 client_unix_minor = SVAL(pdata,2);
2781 client_unix_cap_low = IVAL(pdata,4);
2782 client_unix_cap_high = IVAL(pdata,8);
2783 /* Just print these values for now. */
2784 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2785 cap_low = 0x%x, cap_high = 0x%x\n",
2786 (unsigned int)client_unix_major,
2787 (unsigned int)client_unix_minor,
2788 (unsigned int)client_unix_cap_low,
2789 (unsigned int)client_unix_cap_high ));
2791 /* Here is where we must switch to posix pathname processing... */
2792 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2793 lp_set_posix_pathnames();
2794 mangle_change_to_posix();
2797 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2798 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2799 /* Client that knows how to do posix locks,
2800 * but not posix open/mkdir operations. Set a
2801 * default type for read/write checks. */
2803 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2808 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2811 size_t param_len = 0;
2812 size_t data_len = total_data;
2814 if (!lp_unix_extensions()) {
2815 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2818 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2820 status = srv_request_encryption_setup(conn,
2821 (unsigned char **)ppdata,
2823 (unsigned char **)pparams,
2827 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2828 error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
2829 } else if (!NT_STATUS_IS_OK(status)) {
2830 return ERROR_NT(status);
2833 send_trans2_replies(inbuf, outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes);
2835 if (NT_STATUS_IS_OK(status)) {
2836 /* Server-side transport encryption is now *on*. */
2837 status = srv_encryption_start(conn);
2838 if (!NT_STATUS_IS_OK(status)) {
2839 exit_server_cleanly("Failure in setting up encrypted transport");
2844 case SMB_FS_QUOTA_INFORMATION:
2846 files_struct *fsp = NULL;
2847 SMB_NTQUOTA_STRUCT quotas;
2849 ZERO_STRUCT(quotas);
2852 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2853 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2854 lp_servicename(SNUM(conn)),conn->user));
2855 return ERROR_DOS(ERRSRV,ERRaccess);
2858 /* note: normaly there're 48 bytes,
2859 * but we didn't use the last 6 bytes for now
2862 fsp = file_fsp(SVAL(params,0));
2863 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2864 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2865 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2868 if (total_data < 42) {
2869 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2871 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2874 /* unknown_1 24 NULL bytes in pdata*/
2876 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2877 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2878 #ifdef LARGE_SMB_OFF_T
2879 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2880 #else /* LARGE_SMB_OFF_T */
2881 if ((IVAL(pdata,28) != 0)&&
2882 ((quotas.softlim != 0xFFFFFFFF)||
2883 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2884 /* more than 32 bits? */
2885 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2887 #endif /* LARGE_SMB_OFF_T */
2889 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2890 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2891 #ifdef LARGE_SMB_OFF_T
2892 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2893 #else /* LARGE_SMB_OFF_T */
2894 if ((IVAL(pdata,36) != 0)&&
2895 ((quotas.hardlim != 0xFFFFFFFF)||
2896 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2897 /* more than 32 bits? */
2898 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2900 #endif /* LARGE_SMB_OFF_T */
2902 /* quota_flags 2 bytes **/
2903 quotas.qflags = SVAL(pdata,40);
2905 /* unknown_2 6 NULL bytes follow*/
2907 /* now set the quotas */
2908 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2909 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2910 return ERROR_DOS(ERRSRV,ERRerror);
2916 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2918 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2923 * sending this reply works fine,
2924 * but I'm not sure it's the same
2925 * like windows do...
2928 outsize = set_message(inbuf, outbuf,10,0,True);
2933 #if defined(HAVE_POSIX_ACLS)
2934 /****************************************************************************
2935 Utility function to count the number of entries in a POSIX acl.
2936 ****************************************************************************/
2938 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2940 unsigned int ace_count = 0;
2941 int entry_id = SMB_ACL_FIRST_ENTRY;
2942 SMB_ACL_ENTRY_T entry;
2944 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2946 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2947 entry_id = SMB_ACL_NEXT_ENTRY;
2954 /****************************************************************************
2955 Utility function to marshall a POSIX acl into wire format.
2956 ****************************************************************************/
2958 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2960 int entry_id = SMB_ACL_FIRST_ENTRY;
2961 SMB_ACL_ENTRY_T entry;
2963 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2964 SMB_ACL_TAG_T tagtype;
2965 SMB_ACL_PERMSET_T permset;
2966 unsigned char perms = 0;
2967 unsigned int own_grp;
2970 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2971 entry_id = SMB_ACL_NEXT_ENTRY;
2974 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2975 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2979 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2980 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2984 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2985 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2986 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2988 SCVAL(pdata,1,perms);
2991 case SMB_ACL_USER_OBJ:
2992 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2993 own_grp = (unsigned int)pst->st_uid;
2994 SIVAL(pdata,2,own_grp);
2999 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3001 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3004 own_grp = (unsigned int)*puid;
3005 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3006 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3007 SIVAL(pdata,2,own_grp);
3011 case SMB_ACL_GROUP_OBJ:
3012 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3013 own_grp = (unsigned int)pst->st_gid;
3014 SIVAL(pdata,2,own_grp);
3019 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3021 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3024 own_grp = (unsigned int)*pgid;
3025 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3026 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3027 SIVAL(pdata,2,own_grp);
3032 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3033 SIVAL(pdata,2,0xFFFFFFFF);
3034 SIVAL(pdata,6,0xFFFFFFFF);
3037 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3038 SIVAL(pdata,2,0xFFFFFFFF);
3039 SIVAL(pdata,6,0xFFFFFFFF);
3042 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3045 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3052 /****************************************************************************
3053 Store the FILE_UNIX_BASIC info.
3054 ****************************************************************************/
3056 static char *store_file_unix_basic(connection_struct *conn,
3059 const SMB_STRUCT_STAT *psbuf)
3061 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3062 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3064 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3067 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3070 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3071 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3072 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3075 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3079 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3083 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3086 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3090 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3094 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3097 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3101 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3108 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3109 * the chflags(2) (or equivalent) flags.
3111 * XXX: this really should be behind the VFS interface. To do this, we would
3112 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3113 * Each VFS module could then implement it's own mapping as appropriate for the
3114 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3116 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3120 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3124 { UF_IMMUTABLE, EXT_IMMUTABLE },
3128 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3132 { UF_HIDDEN, EXT_HIDDEN },
3135 /* Do not remove. We need to guarantee that this array has at least one
3136 * entry to build on HP-UX.
3142 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3143 uint32 *smb_fflags, uint32 *smb_fmask)
3145 #ifdef HAVE_STAT_ST_FLAGS
3148 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3149 *smb_fmask |= info2_flags_map[i].smb_fflag;
3150 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3151 *smb_fflags |= info2_flags_map[i].smb_fflag;
3154 #endif /* HAVE_STAT_ST_FLAGS */
3157 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3158 const uint32 smb_fflags,
3159 const uint32 smb_fmask,
3162 #ifdef HAVE_STAT_ST_FLAGS
3163 uint32 max_fmask = 0;
3166 *stat_fflags = psbuf->st_flags;
3168 /* For each flags requested in smb_fmask, check the state of the
3169 * corresponding flag in smb_fflags and set or clear the matching
3173 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3174 max_fmask |= info2_flags_map[i].smb_fflag;
3175 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3176 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3177 *stat_fflags |= info2_flags_map[i].stat_fflag;
3179 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3184 /* If smb_fmask is asking to set any bits that are not supported by
3185 * our flag mappings, we should fail.
3187 if ((smb_fmask & max_fmask) != smb_fmask) {
3194 #endif /* HAVE_STAT_ST_FLAGS */
3198 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3199 * of file flags and birth (create) time.
3201 static char *store_file_unix_basic_info2(connection_struct *conn,
3204 const SMB_STRUCT_STAT *psbuf)
3206 uint32 file_flags = 0;
3207 uint32 flags_mask = 0;
3209 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3211 /* Create (birth) time 64 bit */
3212 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3215 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3216 SIVAL(pdata, 0, file_flags); /* flags */
3217 SIVAL(pdata, 4, flags_mask); /* mask */
3223 /****************************************************************************
3224 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3225 ****************************************************************************/
3227 static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3228 unsigned int tran_call,
3229 char **pparams, int total_params, char **ppdata, int total_data,
3230 unsigned int max_data_bytes)
3232 char *params = *pparams;
3233 char *pdata = *ppdata;
3234 unsigned int data_size = 0;
3235 unsigned int param_size = 2;
3237 smb_np_struct *p_pipe = NULL;
3240 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3243 if (total_params < 4) {
3244 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3247 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3248 if (p_pipe == NULL) {
3249 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3252 info_level = SVAL(params,2);
3254 *pparams = (char *)SMB_REALLOC(*pparams,2);
3255 if (*pparams == NULL) {
3256 return ERROR_NT(NT_STATUS_NO_MEMORY);
3260 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3261 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3262 if (*ppdata == NULL ) {
3263 return ERROR_NT(NT_STATUS_NO_MEMORY);
3267 switch (info_level) {
3268 case SMB_FILE_STANDARD_INFORMATION:
3270 SOFF_T(pdata,0,4096LL);
3277 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3280 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3285 /****************************************************************************
3286 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3287 file name or file id).
3288 ****************************************************************************/
3290 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3291 unsigned int tran_call,
3292 char **pparams, int total_params, char **ppdata, int total_data,
3293 unsigned int max_data_bytes)
3295 char *params = *pparams;
3296 char *pdata = *ppdata;
3300 SMB_OFF_T file_size=0;
3301 SMB_BIG_UINT allocation_size=0;
3302 unsigned int data_size = 0;
3303 unsigned int param_size = 2;
3304 SMB_STRUCT_STAT sbuf;
3305 pstring fname, dos_fname;
3310 BOOL delete_pending = False;
3312 time_t create_time, mtime, atime;
3313 struct timespec create_time_ts, mtime_ts, atime_ts;
3314 files_struct *fsp = NULL;
3315 struct file_id fileid;
3316 TALLOC_CTX *data_ctx = NULL;
3317 struct ea_list *ea_list = NULL;
3318 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3319 char *lock_data = NULL;
3322 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3326 if (tran_call == TRANSACT2_QFILEINFO) {
3327 if (total_params < 4) {
3328 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3332 return call_trans2qpipeinfo(conn,
3345 fsp = file_fsp(SVAL(params,0));
3346 info_level = SVAL(params,2);
3348 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3350 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3351 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3354 if(fsp && (fsp->fake_file_handle)) {
3356 * This is actually for the QUOTA_FAKE_FILE --metze
3359 pstrcpy(fname, fsp->fsp_name);
3360 /* We know this name is ok, it's already passed the checks. */
3362 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3364 * This is actually a QFILEINFO on a directory
3365 * handle (returned from an NT SMB). NT5.0 seems
3366 * to do this call. JRA.
3368 /* We know this name is ok, it's already passed the checks. */
3369 pstrcpy(fname, fsp->fsp_name);
3371 if (INFO_LEVEL_IS_UNIX(info_level)) {
3372 /* Always do lstat for UNIX calls. */
3373 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3374 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3375 return UNIXERROR(ERRDOS,ERRbadpath);
3377 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3378 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3379 return UNIXERROR(ERRDOS,ERRbadpath);
3382 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3383 delete_pending = get_delete_on_close_flag(fileid);
3386 * Original code - this is an open file.
3388 CHECK_FSP(fsp,conn);
3390 pstrcpy(fname, fsp->fsp_name);
3391 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3392 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3393 return(UNIXERROR(ERRDOS,ERRbadfid));
3395 pos = fsp->fh->position_information;
3396 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3397 delete_pending = get_delete_on_close_flag(fileid);
3398 access_mask = fsp->access_mask;
3401 NTSTATUS status = NT_STATUS_OK;
3404 if (total_params < 7) {
3405 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3408 info_level = SVAL(params,0);
3410 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3412 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3413 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3416 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, ¶ms[6],
3417 sizeof(fname), total_params - 6,
3418 STR_TERMINATE, &status);
3419 if (!NT_STATUS_IS_OK(status)) {
3420 return ERROR_NT(status);
3423 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3424 if (!NT_STATUS_IS_OK(status)) {
3425 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3426 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3428 return ERROR_NT(status);
3431 status = unix_convert(conn, fname, False, NULL, &sbuf);
3432 if (!NT_STATUS_IS_OK(status)) {
3433 return ERROR_NT(status);
3435 status = check_name(conn, fname);
3436 if (!NT_STATUS_IS_OK(status)) {
3437 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3438 return ERROR_NT(status);
3441 if (INFO_LEVEL_IS_UNIX(info_level)) {
3442 /* Always do lstat for UNIX calls. */
3443 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3444 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3445 return UNIXERROR(ERRDOS,ERRbadpath);
3447 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3448 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3449 return UNIXERROR(ERRDOS,ERRbadpath);
3452 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3453 delete_pending = get_delete_on_close_flag(fileid);
3454 if (delete_pending) {
3455 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3459 nlink = sbuf.st_nlink;
3461 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3462 /* NTFS does not seem to count ".." */
3466 if ((nlink > 0) && delete_pending) {
3470 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3471 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3474 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3475 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3477 p = strrchr_m(fname,'/');
3483 mode = dos_mode(conn,fname,&sbuf);
3485 mode = FILE_ATTRIBUTE_NORMAL;
3487 fullpathname = fname;
3489 file_size = get_file_size(sbuf);
3491 /* Pull out any data sent here before we realloc. */
3492 switch (info_level) {
3493 case SMB_INFO_QUERY_EAS_FROM_LIST:
3495 /* Pull any EA list from the data portion. */
3498 if (total_data < 4) {
3499 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3501 ea_size = IVAL(pdata,0);
3503 if (total_data > 0 && ea_size != total_data) {
3504 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3505 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3506 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3509 if (!lp_ea_support(SNUM(conn))) {
3510 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3513 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3514 return ERROR_NT(NT_STATUS_NO_MEMORY);
3517 /* Pull out the list of names. */
3518 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3520 talloc_destroy(data_ctx);
3521 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3526 case SMB_QUERY_POSIX_LOCK:
3528 if (fsp == NULL || fsp->fh->fd == -1) {
3529 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3532 if (total_data != POSIX_LOCK_DATA_SIZE) {
3533 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3536 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3537 return ERROR_NT(NT_STATUS_NO_MEMORY);
3540 /* Copy the lock range data. */
3541 lock_data = (char *)TALLOC_MEMDUP(
3542 data_ctx, pdata, total_data);
3544 talloc_destroy(data_ctx);
3545 return ERROR_NT(NT_STATUS_NO_MEMORY);
3552 *pparams = (char *)SMB_REALLOC(*pparams,2);
3553 if (*pparams == NULL) {
3554 talloc_destroy(data_ctx);
3555 return ERROR_NT(NT_STATUS_NO_MEMORY);
3559 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3560 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3561 if (*ppdata == NULL ) {
3562 talloc_destroy(data_ctx);
3563 return ERROR_NT(NT_STATUS_NO_MEMORY);
3567 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3568 mtime_ts = get_mtimespec(&sbuf);
3569 atime_ts = get_atimespec(&sbuf);
3571 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3574 if (!null_timespec(fsp->pending_modtime)) {
3575 /* the pending modtime overrides the current modtime */
3576 mtime_ts = fsp->pending_modtime;
3580 /* Do we have this path open ? */
3581 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3582 fsp1 = file_find_di_first(fileid);
3583 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3584 /* the pending modtime overrides the current modtime */
3585 mtime_ts = fsp1->pending_modtime;
3587 if (fsp1 && fsp1->initial_allocation_size) {
3588 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3592 if (lp_dos_filetime_resolution(SNUM(conn))) {
3593 dos_filetime_timespec(&create_time_ts);
3594 dos_filetime_timespec(&mtime_ts);
3595 dos_filetime_timespec(&atime_ts);
3598 create_time = convert_timespec_to_time_t(create_time_ts);
3599 mtime = convert_timespec_to_time_t(mtime_ts);
3600 atime = convert_timespec_to_time_t(atime_ts);
3602 /* NT expects the name to be in an exact form of the *full*
3603 filename. See the trans2 torture test */
3604 if (strequal(base_name,".")) {
3605 pstrcpy(dos_fname, "\\");
3607 pstr_sprintf(dos_fname, "\\%s", fname);
3608 string_replace(dos_fname, '/', '\\');
3611 switch (info_level) {
3612 case SMB_INFO_STANDARD:
3613 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3615 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3616 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3617 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3618 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3619 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3620 SSVAL(pdata,l1_attrFile,mode);
3623 case SMB_INFO_QUERY_EA_SIZE:
3625 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3626 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3628 srv_put_dos_date2(pdata,0,create_time);
3629 srv_put_dos_date2(pdata,4,atime);
3630 srv_put_dos_date2(pdata,8,mtime); /* write time */
3631 SIVAL(pdata,12,(uint32)file_size);
3632 SIVAL(pdata,16,(uint32)allocation_size);
3633 SSVAL(pdata,20,mode);
3634 SIVAL(pdata,22,ea_size);
3638 case SMB_INFO_IS_NAME_VALID:
3639 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3640 if (tran_call == TRANSACT2_QFILEINFO) {
3641 /* os/2 needs this ? really ?*/
3642 return ERROR_DOS(ERRDOS,ERRbadfunc);
3648 case SMB_INFO_QUERY_EAS_FROM_LIST:
3650 size_t total_ea_len = 0;
3651 struct ea_list *ea_file_list = NULL;
3653 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3655 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3656 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3658 if (!ea_list || (total_ea_len > data_size)) {
3659 talloc_destroy(data_ctx);
3661 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3665 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3666 talloc_destroy(data_ctx);
3670 case SMB_INFO_QUERY_ALL_EAS:
3672 /* We have data_size bytes to put EA's into. */
3673 size_t total_ea_len = 0;
3675 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3677 data_ctx = talloc_init("ea_ctx");
3679 return ERROR_NT(NT_STATUS_NO_MEMORY);
3682 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3683 if (!ea_list || (total_ea_len > data_size)) {
3684 talloc_destroy(data_ctx);
3686 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3690 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3691 talloc_destroy(data_ctx);
3695 case SMB_FILE_BASIC_INFORMATION:
3696 case SMB_QUERY_FILE_BASIC_INFO:
3698 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3699 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3700 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3702 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3706 put_long_date_timespec(pdata,create_time_ts);
3707 put_long_date_timespec(pdata+8,atime_ts);
3708 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3709 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3710 SIVAL(pdata,32,mode);
3712 DEBUG(5,("SMB_QFBI - "));
3713 DEBUG(5,("create: %s ", ctime(&create_time)));
3714 DEBUG(5,("access: %s ", ctime(&atime)));
3715 DEBUG(5,("write: %s ", ctime(&mtime)));
3716 DEBUG(5,("change: %s ", ctime(&mtime)));
3717 DEBUG(5,("mode: %x\n", mode));
3720 case SMB_FILE_STANDARD_INFORMATION:
3721 case SMB_QUERY_FILE_STANDARD_INFO:
3723 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3725 SOFF_T(pdata,0,allocation_size);
3726 SOFF_T(pdata,8,file_size);
3727 SIVAL(pdata,16,nlink);
3728 SCVAL(pdata,20,delete_pending?1:0);
3729 SCVAL(pdata,21,(mode&aDIR)?1:0);
3730 SSVAL(pdata,22,0); /* Padding. */
3733 case SMB_FILE_EA_INFORMATION:
3734 case SMB_QUERY_FILE_EA_INFO:
3736 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3737 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3739 SIVAL(pdata,0,ea_size);
3743 /* Get the 8.3 name - used if NT SMB was negotiated. */
3744 case SMB_QUERY_FILE_ALT_NAME_INFO:
3745 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3749 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3750 pstrcpy(short_name,base_name);
3751 /* Mangle if not already 8.3 */
3752 if(!mangle_is_8_3(short_name, True, conn->params)) {
3753 mangle_map(short_name,True,True,conn->params);
3755 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3756 data_size = 4 + len;
3761 case SMB_QUERY_FILE_NAME_INFO:
3763 this must be *exactly* right for ACLs on mapped drives to work
3765 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3766 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3767 data_size = 4 + len;
3771 case SMB_FILE_ALLOCATION_INFORMATION:
3772 case SMB_QUERY_FILE_ALLOCATION_INFO:
3773 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3775 SOFF_T(pdata,0,allocation_size);
3778 case SMB_FILE_END_OF_FILE_INFORMATION:
3779 case SMB_QUERY_FILE_END_OF_FILEINFO:
3780 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3782 SOFF_T(pdata,0,file_size);
3785 case SMB_QUERY_FILE_ALL_INFO:
3786 case SMB_FILE_ALL_INFORMATION:
3788 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3789 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3790 put_long_date_timespec(pdata,create_time_ts);
3791 put_long_date_timespec(pdata+8,atime_ts);
3792 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3793 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3794 SIVAL(pdata,32,mode);
3795 SIVAL(pdata,36,0); /* padding. */
3797 SOFF_T(pdata,0,allocation_size);
3798 SOFF_T(pdata,8,file_size);
3799 SIVAL(pdata,16,nlink);
3800 SCVAL(pdata,20,delete_pending);
3801 SCVAL(pdata,21,(mode&aDIR)?1:0);
3804 SIVAL(pdata,0,ea_size);
3805 pdata += 4; /* EA info */
3806 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3809 data_size = PTR_DIFF(pdata,(*ppdata));
3812 case SMB_FILE_INTERNAL_INFORMATION:
3813 /* This should be an index number - looks like
3816 I think this causes us to fail the IFSKIT
3817 BasicFileInformationTest. -tpot */
3819 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3820 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3821 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3825 case SMB_FILE_ACCESS_INFORMATION:
3826 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3827 SIVAL(pdata,0,access_mask);
3831 case SMB_FILE_NAME_INFORMATION:
3832 /* Pathname with leading '\'. */
3835 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3836 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3837 SIVAL(pdata,0,byte_len);
3838 data_size = 4 + byte_len;
3842 case SMB_FILE_DISPOSITION_INFORMATION:
3843 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3845 SCVAL(pdata,0,delete_pending);
3848 case SMB_FILE_POSITION_INFORMATION:
3849 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3851 SOFF_T(pdata,0,pos);
3854 case SMB_FILE_MODE_INFORMATION:
3855 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3856 SIVAL(pdata,0,mode);
3860 case SMB_FILE_ALIGNMENT_INFORMATION:
3861 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3862 SIVAL(pdata,0,0); /* No alignment needed. */
3868 * NT4 server just returns "invalid query" to this - if we try to answer
3869 * it then NTws gets a BSOD! (tridge).
3870 * W2K seems to want this. JRA.
3872 case SMB_QUERY_FILE_STREAM_INFO:
3874 case SMB_FILE_STREAM_INFORMATION:
3875 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3879 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3880 SIVAL(pdata,0,0); /* ??? */
3881 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3882 SOFF_T(pdata,8,file_size);
3883 SOFF_T(pdata,16,allocation_size);
3884 data_size = 24 + byte_len;
3888 case SMB_QUERY_COMPRESSION_INFO:
3889 case SMB_FILE_COMPRESSION_INFORMATION:
3890 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3891 SOFF_T(pdata,0,file_size);
3892 SIVAL(pdata,8,0); /* ??? */
3893 SIVAL(pdata,12,0); /* ??? */
3897 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3898 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3899 put_long_date_timespec(pdata,create_time_ts);
3900 put_long_date_timespec(pdata+8,atime_ts);
3901 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3902 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3903 SOFF_T(pdata,32,allocation_size);
3904 SOFF_T(pdata,40,file_size);
3905 SIVAL(pdata,48,mode);
3906 SIVAL(pdata,52,0); /* ??? */
3910 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3911 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3912 SIVAL(pdata,0,mode);
3918 * CIFS UNIX Extensions.
3921 case SMB_QUERY_FILE_UNIX_BASIC:
3923 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3924 data_size = PTR_DIFF(pdata,(*ppdata));
3928 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3930 for (i=0; i<100; i++)
3931 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3937 case SMB_QUERY_FILE_UNIX_INFO2:
3939 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3940 data_size = PTR_DIFF(pdata,(*ppdata));
3944 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3946 for (i=0; i<100; i++)
3947 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3953 case SMB_QUERY_FILE_UNIX_LINK:
3957 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3959 if(!S_ISLNK(sbuf.st_mode))
3960 return(UNIXERROR(ERRSRV,ERRbadlink));
3962 return(UNIXERROR(ERRDOS,ERRbadlink));
3964 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3966 return(UNIXERROR(ERRDOS,ERRnoaccess));
3968 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3970 data_size = PTR_DIFF(pdata,(*ppdata));
3975 #if defined(HAVE_POSIX_ACLS)
3976 case SMB_QUERY_POSIX_ACL:
3978 SMB_ACL_T file_acl = NULL;
3979 SMB_ACL_T def_acl = NULL;
3980 uint16 num_file_acls = 0;
3981 uint16 num_def_acls = 0;
3983 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3984 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3986 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3989 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3990 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3992 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3995 if (S_ISDIR(sbuf.st_mode)) {
3996 if (fsp && fsp->is_directory) {
3997 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3999 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4001 def_acl = free_empty_sys_acl(conn, def_acl);
4004 num_file_acls = count_acl_entries(conn, file_acl);
4005 num_def_acls = count_acl_entries(conn, def_acl);
4007 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4008 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4010 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4011 SMB_POSIX_ACL_HEADER_SIZE) ));
4013 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4016 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4018 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
4021 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4022 SSVAL(pdata,2,num_file_acls);
4023 SSVAL(pdata,4,num_def_acls);
4024 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4026 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4029 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4031 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4033 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4035 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4038 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4040 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4044 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4047 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4049 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4055 case SMB_QUERY_POSIX_LOCK:
4057 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4059 SMB_BIG_UINT offset;
4061 enum brl_type lock_type;
4063 if (total_data != POSIX_LOCK_DATA_SIZE) {
4064 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4067 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4068 case POSIX_LOCK_TYPE_READ:
4069 lock_type = READ_LOCK;
4071 case POSIX_LOCK_TYPE_WRITE:
4072 lock_type = WRITE_LOCK;
4074 case POSIX_LOCK_TYPE_UNLOCK:
4076 /* There's no point in asking for an unlock... */
4077 talloc_destroy(data_ctx);
4078 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4081 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4082 #if defined(HAVE_LONGLONG)
4083 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4084 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4085 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4086 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4087 #else /* HAVE_LONGLONG */
4088 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4089 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4090 #endif /* HAVE_LONGLONG */
4092 status = query_lock(fsp,
4099 if (ERROR_WAS_LOCK_DENIED(status)) {
4100 /* Here we need to report who has it locked... */
4101 data_size = POSIX_LOCK_DATA_SIZE;
4103 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4104 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4105 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4106 #if defined(HAVE_LONGLONG)
4107 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4108 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4109 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4110 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4111 #else /* HAVE_LONGLONG */
4112 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4113 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4114 #endif /* HAVE_LONGLONG */
4116 } else if (NT_STATUS_IS_OK(status)) {
4117 /* For success we just return a copy of what we sent
4118 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4119 data_size = POSIX_LOCK_DATA_SIZE;
4120 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4121 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4123 return ERROR_NT(status);
4129 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4132 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
4137 /****************************************************************************
4138 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4140 ****************************************************************************/
4142 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4144 SMB_STRUCT_STAT sbuf1, sbuf2;
4145 pstring last_component_oldname;
4146 pstring last_component_newname;
4147 NTSTATUS status = NT_STATUS_OK;
4152 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4153 if (!NT_STATUS_IS_OK(status)) {
4157 status = check_name(conn, oldname);
4158 if (!NT_STATUS_IS_OK(status)) {
4162 /* source must already exist. */
4163 if (!VALID_STAT(sbuf1)) {
4164 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4167 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4168 if (!NT_STATUS_IS_OK(status)) {
4172 status = check_name(conn, newname);
4173 if (!NT_STATUS_IS_OK(status)) {
4177 /* Disallow if newname already exists. */
4178 if (VALID_STAT(sbuf2)) {
4179 return NT_STATUS_OBJECT_NAME_COLLISION;
4182 /* No links from a directory. */
4183 if (S_ISDIR(sbuf1.st_mode)) {
4184 return NT_STATUS_FILE_IS_A_DIRECTORY;
4187 /* Ensure this is within the share. */
4188 status = check_reduced_name(conn, oldname);
4189 if (!NT_STATUS_IS_OK(status)) {
4193 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4195 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4196 status = map_nt_error_from_unix(errno);
4197 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4198 nt_errstr(status), newname, oldname));
4204 /****************************************************************************
4205 Deal with setting the time from any of the setfilepathinfo functions.
4206 ****************************************************************************/
4208 static NTSTATUS smb_set_file_time(connection_struct *conn,
4211 const SMB_STRUCT_STAT *psbuf,
4212 struct timespec ts[2])
4215 FILE_NOTIFY_CHANGE_LAST_ACCESS
4216 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4219 if (!VALID_STAT(*psbuf)) {
4220 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4223 /* get some defaults (no modifications) if any info is zero or -1. */
4224 if (null_timespec(ts[0])) {
4225 ts[0] = get_atimespec(psbuf);
4226 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4229 if (null_timespec(ts[1])) {
4230 ts[1] = get_mtimespec(psbuf);
4231 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4234 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4235 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4238 * Try and set the times of this file if
4239 * they are different from the current values.
4243 struct timespec mts = get_mtimespec(psbuf);
4244 struct timespec ats = get_atimespec(psbuf);
4245 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4246 return NT_STATUS_OK;
4252 * This was a setfileinfo on an open file.
4253 * NT does this a lot. We also need to
4254 * set the time here, as it can be read by
4255 * FindFirst/FindNext and with the patch for bug #2045
4256 * in smbd/fileio.c it ensures that this timestamp is
4257 * kept sticky even after a write. We save the request
4258 * away and will set it on file close and after a write. JRA.
4261 if (!null_timespec(ts[1])) {
4262 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4263 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4264 fsp_set_pending_modtime(fsp, ts[1]);
4268 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4270 if(file_ntimes(conn, fname, ts)!=0) {
4271 return map_nt_error_from_unix(errno);
4274 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4276 return NT_STATUS_OK;
4279 /****************************************************************************
4280 Deal with setting the dosmode from any of the setfilepathinfo functions.
4281 ****************************************************************************/
4283 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4285 SMB_STRUCT_STAT *psbuf,
4288 if (!VALID_STAT(*psbuf)) {
4289 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4293 if (S_ISDIR(psbuf->st_mode)) {
4300 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4302 /* check the mode isn't different, before changing it */
4303 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4305 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4306 fname, (unsigned int)dosmode ));
4308 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4309 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4310 fname, strerror(errno)));
4311 return map_nt_error_from_unix(errno);
4314 return NT_STATUS_OK;
4317 /****************************************************************************
4318 Deal with setting the size from any of the setfilepathinfo functions.
4319 ****************************************************************************/
4321 static NTSTATUS smb_set_file_size(connection_struct *conn,
4322 struct smb_request *req,
4325 SMB_STRUCT_STAT *psbuf,
4328 NTSTATUS status = NT_STATUS_OK;
4329 files_struct *new_fsp = NULL;
4331 if (!VALID_STAT(*psbuf)) {
4332 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4335 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4337 if (size == get_file_size(*psbuf)) {
4338 return NT_STATUS_OK;
4341 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4342 fname, (double)size ));
4344 if (fsp && fsp->fh->fd != -1) {
4345 /* Handle based call. */
4346 if (vfs_set_filelen(fsp, size) == -1) {
4347 return map_nt_error_from_unix(errno);
4349 return NT_STATUS_OK;
4352 status = open_file_ntcreate(conn, req, fname, psbuf,
4354 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4357 FILE_ATTRIBUTE_NORMAL,
4358 FORCE_OPLOCK_BREAK_TO_NONE,
4361 if (!NT_STATUS_IS_OK(status)) {
4362 /* NB. We check for open_was_deferred in the caller. */
4366 if (vfs_set_filelen(new_fsp, size) == -1) {
4367 status = map_nt_error_from_unix(errno);
4368 close_file(new_fsp,NORMAL_CLOSE);
4372 close_file(new_fsp,NORMAL_CLOSE);
4373 return NT_STATUS_OK;
4376 /****************************************************************************
4377 Deal with SMB_INFO_SET_EA.
4378 ****************************************************************************/
4380 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4386 struct ea_list *ea_list = NULL;
4387 TALLOC_CTX *ctx = NULL;
4388 NTSTATUS status = NT_STATUS_OK;
4390 if (total_data < 10) {
4392 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4393 length. They seem to have no effect. Bug #3212. JRA */
4395 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4396 /* We're done. We only get EA info in this call. */
4397 return NT_STATUS_OK;
4400 return NT_STATUS_INVALID_PARAMETER;
4403 if (IVAL(pdata,0) > total_data) {
4404 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4405 IVAL(pdata,0), (unsigned int)total_data));
4406 return NT_STATUS_INVALID_PARAMETER;
4409 ctx = talloc_init("SMB_INFO_SET_EA");
4411 return NT_STATUS_NO_MEMORY;
4413 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4415 talloc_destroy(ctx);
4416 return NT_STATUS_INVALID_PARAMETER;
4418 status = set_ea(conn, fsp, fname, ea_list);
4419 talloc_destroy(ctx);
4424 /****************************************************************************
4425 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4426 ****************************************************************************/
4428 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4433 SMB_STRUCT_STAT *psbuf)
4435 NTSTATUS status = NT_STATUS_OK;
4436 BOOL delete_on_close;
4439 if (total_data < 1) {
4440 return NT_STATUS_INVALID_PARAMETER;
4444 return NT_STATUS_INVALID_HANDLE;
4447 delete_on_close = (CVAL(pdata,0) ? True : False);
4448 dosmode = dos_mode(conn, fname, psbuf);
4450 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4451 "delete_on_close = %u\n",
4453 (unsigned int)dosmode,
4454 (unsigned int)delete_on_close ));
4456 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4458 if (!NT_STATUS_IS_OK(status)) {
4462 /* The set is across all open files on this dev/inode pair. */
4463 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4464 return NT_STATUS_ACCESS_DENIED;
4466 return NT_STATUS_OK;
4469 /****************************************************************************
4470 Deal with SMB_FILE_POSITION_INFORMATION.
4471 ****************************************************************************/
4473 static NTSTATUS smb_file_position_information(connection_struct *conn,
4478 SMB_BIG_UINT position_information;
4480 if (total_data < 8) {
4481 return NT_STATUS_INVALID_PARAMETER;
4485 /* Ignore on pathname based set. */
4486 return NT_STATUS_OK;
4489 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4490 #ifdef LARGE_SMB_OFF_T
4491 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4492 #else /* LARGE_SMB_OFF_T */
4493 if (IVAL(pdata,4) != 0) {
4494 /* more than 32 bits? */
4495 return NT_STATUS_INVALID_PARAMETER;
4497 #endif /* LARGE_SMB_OFF_T */
4499 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4500 fsp->fsp_name, (double)position_information ));
4501 fsp->fh->position_information = position_information;
4502 return NT_STATUS_OK;
4505 /****************************************************************************
4506 Deal with SMB_FILE_MODE_INFORMATION.
4507 ****************************************************************************/
4509 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4515 if (total_data < 4) {
4516 return NT_STATUS_INVALID_PARAMETER;
4518 mode = IVAL(pdata,0);
4519 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4520 return NT_STATUS_INVALID_PARAMETER;
4522 return NT_STATUS_OK;
4525 /****************************************************************************
4526 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4527 ****************************************************************************/
4529 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4535 pstring link_target;
4536 const char *newname = fname;
4537 NTSTATUS status = NT_STATUS_OK;
4539 /* Set a symbolic link. */
4540 /* Don't allow this if follow links is false. */
4542 if (total_data == 0) {
4543 return NT_STATUS_INVALID_PARAMETER;
4546 if (!lp_symlinks(SNUM(conn))) {
4547 return NT_STATUS_ACCESS_DENIED;
4550 srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), link_target, pdata,
4551 sizeof(link_target), total_data, STR_TERMINATE);
4553 /* !widelinks forces the target path to be within the share. */
4554 /* This means we can interpret the target as a pathname. */
4555 if (!lp_widelinks(SNUM(conn))) {
4557 char *last_dirp = NULL;
4559 if (*link_target == '/') {
4560 /* No absolute paths allowed. */
4561 return NT_STATUS_ACCESS_DENIED;
4563 pstrcpy(rel_name, newname);
4564 last_dirp = strrchr_m(rel_name, '/');
4566 last_dirp[1] = '\0';
4568 pstrcpy(rel_name, "./");
4570 pstrcat(rel_name, link_target);
4572 status = check_name(conn, rel_name);
4573 if (!NT_STATUS_IS_OK(status)) {
4578 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4579 newname, link_target ));
4581 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4582 return map_nt_error_from_unix(errno);
4585 return NT_STATUS_OK;
4588 /****************************************************************************
4589 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4590 ****************************************************************************/
4592 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4600 NTSTATUS status = NT_STATUS_OK;
4602 /* Set a hard link. */
4603 if (total_data == 0) {
4604 return NT_STATUS_INVALID_PARAMETER;
4607 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), oldname, pdata,
4608 sizeof(oldname), total_data, STR_TERMINATE, &status);
4609 if (!NT_STATUS_IS_OK(status)) {
4613 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4614 if (!NT_STATUS_IS_OK(status)) {
4618 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4621 return hardlink_internals(conn, oldname, fname);
4624 /****************************************************************************
4625 Deal with SMB_FILE_RENAME_INFORMATION.
4626 ****************************************************************************/
4628 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4629 struct smb_request *req,
4642 BOOL dest_has_wcard = False;
4643 NTSTATUS status = NT_STATUS_OK;
4646 if (total_data < 13) {
4647 return NT_STATUS_INVALID_PARAMETER;
4650 overwrite = (CVAL(pdata,0) ? True : False);
4651 root_fid = IVAL(pdata,4);
4652 len = IVAL(pdata,8);
4654 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4655 return NT_STATUS_INVALID_PARAMETER;
4658 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, &pdata[12],
4659 sizeof(newname), len, 0, &status,
4661 if (!NT_STATUS_IS_OK(status)) {
4665 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4666 if (!NT_STATUS_IS_OK(status)) {
4670 /* Check the new name has no '/' characters. */
4671 if (strchr_m(newname, '/')) {
4672 return NT_STATUS_NOT_SUPPORTED;
4675 /* Create the base directory. */
4676 pstrcpy(base_name, fname);
4677 p = strrchr_m(base_name, '/');
4681 pstrcpy(base_name, "./");
4683 /* Append the new name. */
4684 pstrcat(base_name, newname);
4687 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4688 fsp->fnum, fsp->fsp_name, base_name ));
4689 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4691 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4693 status = rename_internals(conn, req, fname, base_name, 0,
4694 overwrite, False, dest_has_wcard);
4700 /****************************************************************************
4701 Deal with SMB_SET_POSIX_ACL.
4702 ****************************************************************************/
4704 #if defined(HAVE_POSIX_ACLS)
4705 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4710 SMB_STRUCT_STAT *psbuf)
4712 uint16 posix_acl_version;
4713 uint16 num_file_acls;
4714 uint16 num_def_acls;
4715 BOOL valid_file_acls = True;
4716 BOOL valid_def_acls = True;
4718 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4719 return NT_STATUS_INVALID_PARAMETER;
4721 posix_acl_version = SVAL(pdata,0);
4722 num_file_acls = SVAL(pdata,2);
4723 num_def_acls = SVAL(pdata,4);
4725 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4726 valid_file_acls = False;
4730 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4731 valid_def_acls = False;
4735 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4736 return NT_STATUS_INVALID_PARAMETER;
4739 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4740 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4741 return NT_STATUS_INVALID_PARAMETER;
4744 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4745 fname ? fname : fsp->fsp_name,
4746 (unsigned int)num_file_acls,
4747 (unsigned int)num_def_acls));
4749 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4750 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4751 return map_nt_error_from_unix(errno);
4754 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4755 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4756 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4757 return map_nt_error_from_unix(errno);
4759 return NT_STATUS_OK;
4763 /****************************************************************************
4764 Deal with SMB_SET_POSIX_LOCK.
4765 ****************************************************************************/
4767 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4775 SMB_BIG_UINT offset;
4777 BOOL blocking_lock = False;
4778 enum brl_type lock_type;
4779 NTSTATUS status = NT_STATUS_OK;
4781 if (fsp == NULL || fsp->fh->fd == -1) {
4782 return NT_STATUS_INVALID_HANDLE;
4785 if (total_data != POSIX_LOCK_DATA_SIZE) {
4786 return NT_STATUS_INVALID_PARAMETER;
4789 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4790 case POSIX_LOCK_TYPE_READ:
4791 lock_type = READ_LOCK;
4793 case POSIX_LOCK_TYPE_WRITE:
4794 /* Return the right POSIX-mappable error code for files opened read-only. */
4795 if (!fsp->can_write) {
4796 return NT_STATUS_INVALID_HANDLE;
4798 lock_type = WRITE_LOCK;
4800 case POSIX_LOCK_TYPE_UNLOCK:
4801 lock_type = UNLOCK_LOCK;
4804 return NT_STATUS_INVALID_PARAMETER;
4807 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4808 blocking_lock = False;
4809 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4810 blocking_lock = True;
4812 return NT_STATUS_INVALID_PARAMETER;
4815 if (!lp_blocking_locks(SNUM(conn))) {
4816 blocking_lock = False;
4819 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4820 #if defined(HAVE_LONGLONG)
4821 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4822 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4823 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4824 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4825 #else /* HAVE_LONGLONG */
4826 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4827 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4828 #endif /* HAVE_LONGLONG */
4830 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4831 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4833 (unsigned int)lock_type,
4834 (unsigned int)lock_pid,
4838 if (lock_type == UNLOCK_LOCK) {
4839 status = do_unlock(smbd_messaging_context(),
4846 uint32 block_smbpid;
4848 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
4859 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4861 * A blocking lock was requested. Package up
4862 * this smb into a queued request and push it
4863 * onto the blocking lock queue.
4865 if(push_blocking_lock_request(br_lck,
4868 -1, /* infinite timeout. */
4876 TALLOC_FREE(br_lck);
4880 TALLOC_FREE(br_lck);
4886 /****************************************************************************
4887 Deal with SMB_INFO_STANDARD.
4888 ****************************************************************************/
4890 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4895 const SMB_STRUCT_STAT *psbuf)
4897 struct timespec ts[2];
4899 if (total_data < 12) {
4900 return NT_STATUS_INVALID_PARAMETER;
4904 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4906 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4908 DEBUG(10,("smb_set_info_standard: file %s\n",
4909 fname ? fname : fsp->fsp_name ));
4911 return smb_set_file_time(conn,
4918 /****************************************************************************
4919 Deal with SMB_SET_FILE_BASIC_INFO.
4920 ****************************************************************************/
4922 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4927 SMB_STRUCT_STAT *psbuf)
4929 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4930 struct timespec write_time;
4931 struct timespec changed_time;
4933 struct timespec ts[2];
4934 NTSTATUS status = NT_STATUS_OK;
4936 if (total_data < 36) {
4937 return NT_STATUS_INVALID_PARAMETER;
4940 /* Set the attributes */
4941 dosmode = IVAL(pdata,32);
4942 status = smb_set_file_dosmode(conn,
4946 if (!NT_STATUS_IS_OK(status)) {
4950 /* Ignore create time at offset pdata. */
4953 ts[0] = interpret_long_date(pdata+8);
4955 write_time = interpret_long_date(pdata+16);
4956 changed_time = interpret_long_date(pdata+24);
4959 ts[1] = timespec_min(&write_time, &changed_time);
4961 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4965 /* Prefer a defined time to an undefined one. */
4966 if (null_timespec(ts[1])) {
4967 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4970 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4971 fname ? fname : fsp->fsp_name ));
4973 return smb_set_file_time(conn,
4980 /****************************************************************************
4981 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4982 ****************************************************************************/
4984 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4985 struct smb_request *req,
4990 SMB_STRUCT_STAT *psbuf)
4992 SMB_BIG_UINT allocation_size = 0;
4993 NTSTATUS status = NT_STATUS_OK;
4994 files_struct *new_fsp = NULL;
4996 if (!VALID_STAT(*psbuf)) {
4997 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5000 if (total_data < 8) {
5001 return NT_STATUS_INVALID_PARAMETER;
5004 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5005 #ifdef LARGE_SMB_OFF_T
5006 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5007 #else /* LARGE_SMB_OFF_T */
5008 if (IVAL(pdata,4) != 0) {
5009 /* more than 32 bits? */
5010 return NT_STATUS_INVALID_PARAMETER;
5012 #endif /* LARGE_SMB_OFF_T */
5014 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5015 fname, (double)allocation_size ));
5017 if (allocation_size) {
5018 allocation_size = smb_roundup(conn, allocation_size);
5021 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5022 fname, (double)allocation_size ));
5024 if (fsp && fsp->fh->fd != -1) {
5025 /* Open file handle. */
5026 /* Only change if needed. */
5027 if (allocation_size != get_file_size(*psbuf)) {
5028 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5029 return map_nt_error_from_unix(errno);
5032 /* But always update the time. */
5033 if (null_timespec(fsp->pending_modtime)) {
5035 * This is equivalent to a write. Ensure it's seen immediately
5036 * if there are no pending writes.
5038 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
5040 return NT_STATUS_OK;
5043 /* Pathname or stat or directory file. */
5045 status = open_file_ntcreate(conn, req, fname, psbuf,
5047 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5050 FILE_ATTRIBUTE_NORMAL,
5051 FORCE_OPLOCK_BREAK_TO_NONE,
5054 if (!NT_STATUS_IS_OK(status)) {
5055 /* NB. We check for open_was_deferred in the caller. */
5059 /* Only change if needed. */
5060 if (allocation_size != get_file_size(*psbuf)) {
5061 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5062 status = map_nt_error_from_unix(errno);
5063 close_file(new_fsp,NORMAL_CLOSE);
5068 /* Changing the allocation size should set the last mod time. */
5069 /* Don't need to call set_filetime as this will be flushed on
5072 fsp_set_pending_modtime(new_fsp, timespec_current());
5074 close_file(new_fsp,NORMAL_CLOSE);
5075 return NT_STATUS_OK;
5078 /****************************************************************************
5079 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5080 ****************************************************************************/
5082 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5083 struct smb_request *req,
5088 SMB_STRUCT_STAT *psbuf)
5092 if (total_data < 8) {
5093 return NT_STATUS_INVALID_PARAMETER;
5096 size = IVAL(pdata,0);
5097 #ifdef LARGE_SMB_OFF_T
5098 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5099 #else /* LARGE_SMB_OFF_T */
5100 if (IVAL(pdata,4) != 0) {
5101 /* more than 32 bits? */
5102 return NT_STATUS_INVALID_PARAMETER;
5104 #endif /* LARGE_SMB_OFF_T */
5105 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5106 "file %s to %.0f\n", fname, (double)size ));
5108 return smb_set_file_size(conn, req,
5115 /****************************************************************************
5116 Allow a UNIX info mknod.
5117 ****************************************************************************/
5119 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5123 SMB_STRUCT_STAT *psbuf)
5125 uint32 file_type = IVAL(pdata,56);
5126 #if defined(HAVE_MAKEDEV)
5127 uint32 dev_major = IVAL(pdata,60);
5128 uint32 dev_minor = IVAL(pdata,68);
5130 SMB_DEV_T dev = (SMB_DEV_T)0;
5131 uint32 raw_unixmode = IVAL(pdata,84);
5135 if (total_data < 100) {
5136 return NT_STATUS_INVALID_PARAMETER;
5139 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5140 if (!NT_STATUS_IS_OK(status)) {
5144 #if defined(HAVE_MAKEDEV)
5145 dev = makedev(dev_major, dev_minor);
5148 switch (file_type) {
5149 #if defined(S_IFIFO)
5150 case UNIX_TYPE_FIFO:
5151 unixmode |= S_IFIFO;
5154 #if defined(S_IFSOCK)
5155 case UNIX_TYPE_SOCKET:
5156 unixmode |= S_IFSOCK;
5159 #if defined(S_IFCHR)
5160 case UNIX_TYPE_CHARDEV:
5161 unixmode |= S_IFCHR;
5164 #if defined(S_IFBLK)
5165 case UNIX_TYPE_BLKDEV:
5166 unixmode |= S_IFBLK;
5170 return NT_STATUS_INVALID_PARAMETER;
5173 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5174 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5176 /* Ok - do the mknod. */
5177 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5178 return map_nt_error_from_unix(errno);
5181 /* If any of the other "set" calls fail we
5182 * don't want to end up with a half-constructed mknod.
5185 if (lp_inherit_perms(SNUM(conn))) {
5187 conn, parent_dirname(fname),
5191 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5192 status = map_nt_error_from_unix(errno);
5193 SMB_VFS_UNLINK(conn,fname);
5196 return NT_STATUS_OK;
5199 /****************************************************************************
5200 Deal with SMB_SET_FILE_UNIX_BASIC.
5201 ****************************************************************************/
5203 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5204 struct smb_request *req,
5209 SMB_STRUCT_STAT *psbuf)
5211 struct timespec ts[2];
5212 uint32 raw_unixmode;
5215 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5216 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5217 NTSTATUS status = NT_STATUS_OK;
5218 BOOL delete_on_fail = False;
5219 enum perm_type ptype;
5221 if (total_data < 100) {
5222 return NT_STATUS_INVALID_PARAMETER;
5225 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5226 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5227 size=IVAL(pdata,0); /* first 8 Bytes are size */
5228 #ifdef LARGE_SMB_OFF_T
5229 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5230 #else /* LARGE_SMB_OFF_T */
5231 if (IVAL(pdata,4) != 0) {
5232 /* more than 32 bits? */
5233 return NT_STATUS_INVALID_PARAMETER;
5235 #endif /* LARGE_SMB_OFF_T */
5238 ts[0] = interpret_long_date(pdata+24); /* access_time */
5239 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5240 set_owner = (uid_t)IVAL(pdata,40);
5241 set_grp = (gid_t)IVAL(pdata,48);
5242 raw_unixmode = IVAL(pdata,84);
5244 if (VALID_STAT(*psbuf)) {
5245 if (S_ISDIR(psbuf->st_mode)) {
5246 ptype = PERM_EXISTING_DIR;
5248 ptype = PERM_EXISTING_FILE;
5251 ptype = PERM_NEW_FILE;
5254 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5255 if (!NT_STATUS_IS_OK(status)) {
5259 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5260 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5261 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5263 if (!VALID_STAT(*psbuf)) {
5265 * The only valid use of this is to create character and block
5266 * devices, and named pipes. This is deprecated (IMHO) and
5267 * a new info level should be used for mknod. JRA.
5270 status = smb_unix_mknod(conn,
5275 if (!NT_STATUS_IS_OK(status)) {
5279 /* Ensure we don't try and change anything else. */
5280 raw_unixmode = SMB_MODE_NO_CHANGE;
5281 size = get_file_size(*psbuf);
5282 ts[0] = get_atimespec(psbuf);
5283 ts[1] = get_mtimespec(psbuf);
5285 * We continue here as we might want to change the
5288 delete_on_fail = True;
5292 /* Horrible backwards compatibility hack as an old server bug
5293 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5297 size = get_file_size(*psbuf);
5302 * Deal with the UNIX specific mode set.
5305 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5306 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5307 (unsigned int)unixmode, fname ));
5308 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5309 return map_nt_error_from_unix(errno);
5314 * Deal with the UNIX specific uid set.
5317 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5320 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5321 (unsigned int)set_owner, fname ));
5323 if (S_ISLNK(psbuf->st_mode)) {
5324 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5326 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5330 status = map_nt_error_from_unix(errno);
5331 if (delete_on_fail) {
5332 SMB_VFS_UNLINK(conn,fname);
5339 * Deal with the UNIX specific gid set.
5342 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5343 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5344 (unsigned int)set_owner, fname ));
5345 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5346 status = map_nt_error_from_unix(errno);
5347 if (delete_on_fail) {
5348 SMB_VFS_UNLINK(conn,fname);
5354 /* Deal with any size changes. */
5356 status = smb_set_file_size(conn, req,
5361 if (!NT_STATUS_IS_OK(status)) {
5365 /* Deal with any time changes. */
5367 return smb_set_file_time(conn,
5374 /****************************************************************************
5375 Deal with SMB_SET_FILE_UNIX_INFO2.
5376 ****************************************************************************/
5378 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5379 struct smb_request *req,
5384 SMB_STRUCT_STAT *psbuf)
5390 if (total_data < 116) {
5391 return NT_STATUS_INVALID_PARAMETER;
5394 /* Start by setting all the fields that are common between UNIX_BASIC
5397 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5399 if (!NT_STATUS_IS_OK(status)) {
5403 smb_fflags = IVAL(pdata, 108);
5404 smb_fmask = IVAL(pdata, 112);
5406 /* NB: We should only attempt to alter the file flags if the client
5407 * sends a non-zero mask.
5409 if (smb_fmask != 0) {
5410 int stat_fflags = 0;
5412 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5414 /* Client asked to alter a flag we don't understand. */
5415 return NT_STATUS_INVALID_PARAMETER;
5418 if (fsp && fsp->fh->fd != -1) {
5419 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5420 return NT_STATUS_NOT_SUPPORTED;
5422 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5423 return map_nt_error_from_unix(errno);
5428 /* XXX: need to add support for changing the create_time here. You
5429 * can do this for paths on Darwin with setattrlist(2). The right way
5430 * to hook this up is probably by extending the VFS utimes interface.
5433 return NT_STATUS_OK;
5436 /****************************************************************************
5437 Create a directory with POSIX semantics.
5438 ****************************************************************************/
5440 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5441 struct smb_request *req,
5445 SMB_STRUCT_STAT *psbuf,
5446 int *pdata_return_size)
5448 NTSTATUS status = NT_STATUS_OK;
5449 uint32 raw_unixmode = 0;
5450 uint32 mod_unixmode = 0;
5451 mode_t unixmode = (mode_t)0;
5452 files_struct *fsp = NULL;
5453 uint16 info_level_return = 0;
5455 char *pdata = *ppdata;
5457 if (total_data < 18) {
5458 return NT_STATUS_INVALID_PARAMETER;
5461 raw_unixmode = IVAL(pdata,8);
5462 /* Next 4 bytes are not yet defined. */
5464 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5465 if (!NT_STATUS_IS_OK(status)) {
5469 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5471 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5472 fname, (unsigned int)unixmode ));
5474 status = open_directory(conn, req,
5477 FILE_READ_ATTRIBUTES, /* Just a stat open */
5478 FILE_SHARE_NONE, /* Ignored for stat opens */
5485 if (NT_STATUS_IS_OK(status)) {
5486 close_file(fsp, NORMAL_CLOSE);
5489 info_level_return = SVAL(pdata,16);
5491 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5492 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5493 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5494 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5496 *pdata_return_size = 12;
5499 /* Realloc the data size */
5500 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5501 if (*ppdata == NULL) {
5502 *pdata_return_size = 0;
5503 return NT_STATUS_NO_MEMORY;
5507 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5508 SSVAL(pdata,2,0); /* No fnum. */
5509 SIVAL(pdata,4,info); /* Was directory created. */
5511 switch (info_level_return) {
5512 case SMB_QUERY_FILE_UNIX_BASIC:
5513 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5514 SSVAL(pdata,10,0); /* Padding. */
5515 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5517 case SMB_QUERY_FILE_UNIX_INFO2:
5518 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5519 SSVAL(pdata,10,0); /* Padding. */
5520 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5523 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5524 SSVAL(pdata,10,0); /* Padding. */
5531 /****************************************************************************
5532 Open/Create a file with POSIX semantics.
5533 ****************************************************************************/
5535 static NTSTATUS smb_posix_open(connection_struct *conn,
5536 struct smb_request *req,
5540 SMB_STRUCT_STAT *psbuf,
5541 int *pdata_return_size)
5543 BOOL extended_oplock_granted = False;
5544 char *pdata = *ppdata;
5546 uint32 wire_open_mode = 0;
5547 uint32 raw_unixmode = 0;
5548 uint32 mod_unixmode = 0;
5549 uint32 create_disp = 0;
5550 uint32 access_mask = 0;
5551 uint32 create_options = 0;
5552 NTSTATUS status = NT_STATUS_OK;
5553 mode_t unixmode = (mode_t)0;
5554 files_struct *fsp = NULL;
5555 int oplock_request = 0;
5557 uint16 info_level_return = 0;
5559 if (total_data < 18) {
5560 return NT_STATUS_INVALID_PARAMETER;
5563 flags = IVAL(pdata,0);
5564 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5565 if (oplock_request) {
5566 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5569 wire_open_mode = IVAL(pdata,4);
5571 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5572 return smb_posix_mkdir(conn, req,
5580 switch (wire_open_mode & SMB_ACCMODE) {
5582 access_mask = FILE_READ_DATA;
5585 access_mask = FILE_WRITE_DATA;
5588 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5591 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5592 (unsigned int)wire_open_mode ));
5593 return NT_STATUS_INVALID_PARAMETER;
5596 wire_open_mode &= ~SMB_ACCMODE;
5598 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5599 create_disp = FILE_CREATE;
5600 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5601 create_disp = FILE_OVERWRITE_IF;
5602 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5603 create_disp = FILE_OPEN_IF;
5605 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5606 (unsigned int)wire_open_mode ));
5607 return NT_STATUS_INVALID_PARAMETER;
5610 raw_unixmode = IVAL(pdata,8);
5611 /* Next 4 bytes are not yet defined. */
5613 status = unix_perms_from_wire(conn,
5616 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5619 if (!NT_STATUS_IS_OK(status)) {
5623 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5625 if (wire_open_mode & SMB_O_SYNC) {
5626 create_options |= FILE_WRITE_THROUGH;
5628 if (wire_open_mode & SMB_O_APPEND) {
5629 access_mask |= FILE_APPEND_DATA;
5631 if (wire_open_mode & SMB_O_DIRECT) {
5632 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5635 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5637 (unsigned int)wire_open_mode,
5638 (unsigned int)unixmode ));
5640 status = open_file_ntcreate(conn, req,
5644 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5646 0, /* no create options yet. */
5652 if (!NT_STATUS_IS_OK(status)) {
5656 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5657 extended_oplock_granted = True;
5660 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5661 extended_oplock_granted = True;
5664 info_level_return = SVAL(pdata,16);
5666 /* Allocate the correct return size. */
5668 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5669 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5670 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5671 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5673 *pdata_return_size = 12;
5676 /* Realloc the data size */
5677 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5678 if (*ppdata == NULL) {
5679 close_file(fsp,ERROR_CLOSE);
5680 *pdata_return_size = 0;
5681 return NT_STATUS_NO_MEMORY;
5685 if (extended_oplock_granted) {
5686 if (flags & REQUEST_BATCH_OPLOCK) {
5687 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5689 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5691 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5692 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5694 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5697 SSVAL(pdata,2,fsp->fnum);
5698 SIVAL(pdata,4,info); /* Was file created etc. */
5700 switch (info_level_return) {
5701 case SMB_QUERY_FILE_UNIX_BASIC:
5702 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5703 SSVAL(pdata,10,0); /* padding. */
5704 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5706 case SMB_QUERY_FILE_UNIX_INFO2:
5707 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5708 SSVAL(pdata,10,0); /* padding. */
5709 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5712 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5713 SSVAL(pdata,10,0); /* padding. */
5716 return NT_STATUS_OK;
5719 /****************************************************************************
5720 Delete a file with POSIX semantics.
5721 ****************************************************************************/
5723 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5724 struct smb_request *req,
5728 SMB_STRUCT_STAT *psbuf)
5730 NTSTATUS status = NT_STATUS_OK;
5731 files_struct *fsp = NULL;
5736 struct share_mode_lock *lck = NULL;
5738 if (total_data < 2) {
5739 return NT_STATUS_INVALID_PARAMETER;
5742 flags = SVAL(pdata,0);
5744 if (!VALID_STAT(*psbuf)) {
5745 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5748 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5749 !VALID_STAT_OF_DIR(*psbuf)) {
5750 return NT_STATUS_NOT_A_DIRECTORY;
5753 DEBUG(10,("smb_posix_unlink: %s %s\n",
5754 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5757 if (VALID_STAT_OF_DIR(*psbuf)) {
5758 status = open_directory(conn, req,
5762 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5765 FILE_FLAG_POSIX_SEMANTICS|0777,
5770 status = open_file_ntcreate(conn, req,
5774 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5777 FILE_FLAG_POSIX_SEMANTICS|0777,
5778 0, /* No oplock, but break existing ones. */
5783 if (!NT_STATUS_IS_OK(status)) {
5788 * Don't lie to client. If we can't really delete due to
5789 * non-POSIX opens return SHARING_VIOLATION.
5792 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
5794 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
5795 "lock for file %s\n", fsp->fsp_name));
5796 close_file(fsp, NORMAL_CLOSE);
5797 return NT_STATUS_INVALID_PARAMETER;
5801 * See if others still have the file open. If this is the case, then
5802 * don't delete. If all opens are POSIX delete we can set the delete
5803 * on close disposition.
5805 for (i=0; i<lck->num_share_modes; i++) {
5806 struct share_mode_entry *e = &lck->share_modes[i];
5807 if (is_valid_share_mode_entry(e)) {
5808 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
5811 /* Fail with sharing violation. */
5812 close_file(fsp, NORMAL_CLOSE);
5814 return NT_STATUS_SHARING_VIOLATION;
5819 * Set the delete on close.
5821 status = smb_set_file_disposition_info(conn,
5828 if (!NT_STATUS_IS_OK(status)) {
5829 close_file(fsp, NORMAL_CLOSE);
5834 return close_file(fsp, NORMAL_CLOSE);
5837 /****************************************************************************
5838 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5839 ****************************************************************************/
5841 static int call_trans2setfilepathinfo(connection_struct *conn,
5842 struct smb_request *req,
5843 char *inbuf, char *outbuf, int length,
5845 unsigned int tran_call,
5846 char **pparams, int total_params, char **ppdata, int total_data,
5847 unsigned int max_data_bytes)
5849 char *params = *pparams;
5850 char *pdata = *ppdata;
5852 SMB_STRUCT_STAT sbuf;
5854 files_struct *fsp = NULL;
5855 NTSTATUS status = NT_STATUS_OK;
5856 int data_return_size = 0;
5859 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5864 if (tran_call == TRANSACT2_SETFILEINFO) {
5865 if (total_params < 4) {
5866 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5869 fsp = file_fsp(SVAL(params,0));
5870 info_level = SVAL(params,2);
5872 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5874 * This is actually a SETFILEINFO on a directory
5875 * handle (returned from an NT SMB). NT5.0 seems
5876 * to do this call. JRA.
5878 pstrcpy(fname, fsp->fsp_name);
5879 if (INFO_LEVEL_IS_UNIX(info_level)) {
5880 /* Always do lstat for UNIX calls. */
5881 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
5882 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
5883 return UNIXERROR(ERRDOS,ERRbadpath);
5886 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5887 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5888 return UNIXERROR(ERRDOS,ERRbadpath);
5891 } else if (fsp && fsp->print_file) {
5893 * Doing a DELETE_ON_CLOSE should cancel a print job.
5895 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5896 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5898 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5901 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5904 return (UNIXERROR(ERRDOS,ERRbadpath));
5907 * Original code - this is an open file.
5909 CHECK_FSP(fsp,conn);
5911 pstrcpy(fname, fsp->fsp_name);
5913 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5914 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5915 return(UNIXERROR(ERRDOS,ERRbadfid));
5920 if (total_params < 7) {
5921 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5924 info_level = SVAL(params,0);
5925 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, ¶ms[6],
5926 sizeof(fname), total_params - 6, STR_TERMINATE,
5928 if (!NT_STATUS_IS_OK(status)) {
5929 return ERROR_NT(status);
5932 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5933 if (!NT_STATUS_IS_OK(status)) {
5934 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5935 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5937 return ERROR_NT(status);
5940 status = unix_convert(conn, fname, False, NULL, &sbuf);
5941 if (!NT_STATUS_IS_OK(status)) {
5942 return ERROR_NT(status);
5945 status = check_name(conn, fname);
5946 if (!NT_STATUS_IS_OK(status)) {
5947 return ERROR_NT(status);
5950 if (INFO_LEVEL_IS_UNIX(info_level)) {
5952 * For CIFS UNIX extensions the target name may not exist.
5955 /* Always do lstat for UNIX calls. */
5956 SMB_VFS_LSTAT(conn,fname,&sbuf);
5958 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
5959 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
5960 return UNIXERROR(ERRDOS,ERRbadpath);
5964 if (!CAN_WRITE(conn)) {
5965 return ERROR_DOS(ERRSRV,ERRaccess);
5968 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5969 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5972 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5973 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5975 /* Realloc the parameter size */
5976 *pparams = (char *)SMB_REALLOC(*pparams,2);
5977 if (*pparams == NULL) {
5978 return ERROR_NT(NT_STATUS_NO_MEMORY);
5984 if (fsp && !null_timespec(fsp->pending_modtime)) {
5985 /* the pending modtime overrides the current modtime */
5986 set_mtimespec(&sbuf, fsp->pending_modtime);
5989 switch (info_level) {
5991 case SMB_INFO_STANDARD:
5993 status = smb_set_info_standard(conn,
6002 case SMB_INFO_SET_EA:
6004 status = smb_info_set_ea(conn,
6012 case SMB_SET_FILE_BASIC_INFO:
6013 case SMB_FILE_BASIC_INFORMATION:
6015 status = smb_set_file_basic_info(conn,
6024 case SMB_FILE_ALLOCATION_INFORMATION:
6025 case SMB_SET_FILE_ALLOCATION_INFO:
6027 status = smb_set_file_allocation_info(conn, req,
6036 case SMB_FILE_END_OF_FILE_INFORMATION:
6037 case SMB_SET_FILE_END_OF_FILE_INFO:
6039 status = smb_set_file_end_of_file_info(conn, req,
6048 case SMB_FILE_DISPOSITION_INFORMATION:
6049 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6052 /* JRA - We used to just ignore this on a path ?
6053 * Shouldn't this be invalid level on a pathname
6056 if (tran_call != TRANSACT2_SETFILEINFO) {
6057 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6060 status = smb_set_file_disposition_info(conn,
6069 case SMB_FILE_POSITION_INFORMATION:
6071 status = smb_file_position_information(conn,
6078 /* From tridge Samba4 :
6079 * MODE_INFORMATION in setfileinfo (I have no
6080 * idea what "mode information" on a file is - it takes a value of 0,
6081 * 2, 4 or 6. What could it be?).
6084 case SMB_FILE_MODE_INFORMATION:
6086 status = smb_file_mode_information(conn,
6093 * CIFS UNIX extensions.
6096 case SMB_SET_FILE_UNIX_BASIC:
6098 status = smb_set_file_unix_basic(conn, req,
6107 case SMB_SET_FILE_UNIX_INFO2:
6109 status = smb_set_file_unix_info2(conn, req,
6118 case SMB_SET_FILE_UNIX_LINK:
6120 if (tran_call != TRANSACT2_SETPATHINFO) {
6121 /* We must have a pathname for this. */
6122 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6124 status = smb_set_file_unix_link(conn,
6132 case SMB_SET_FILE_UNIX_HLINK:
6134 if (tran_call != TRANSACT2_SETPATHINFO) {
6135 /* We must have a pathname for this. */
6136 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6138 status = smb_set_file_unix_hlink(conn,
6147 case SMB_FILE_RENAME_INFORMATION:
6149 status = smb_file_rename_information(conn, req,
6159 #if defined(HAVE_POSIX_ACLS)
6160 case SMB_SET_POSIX_ACL:
6162 status = smb_set_posix_acl(conn,
6172 case SMB_SET_POSIX_LOCK:
6174 if (tran_call != TRANSACT2_SETFILEINFO) {
6175 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6177 status = smb_set_posix_lock(conn,
6186 case SMB_POSIX_PATH_OPEN:
6188 if (tran_call != TRANSACT2_SETPATHINFO) {
6189 /* We must have a pathname for this. */
6190 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6193 status = smb_posix_open(conn, req,
6202 case SMB_POSIX_PATH_UNLINK:
6204 if (tran_call != TRANSACT2_SETPATHINFO) {
6205 /* We must have a pathname for this. */
6206 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6209 status = smb_posix_unlink(conn, req,
6218 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6222 if (!NT_STATUS_IS_OK(status)) {
6223 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6224 /* We have re-scheduled this call. */
6227 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6228 /* We have re-scheduled this call. */
6231 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6232 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6234 return ERROR_NT(status);
6238 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6243 /****************************************************************************
6244 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6245 ****************************************************************************/
6247 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6248 char **pparams, int total_params, char **ppdata, int total_data,
6249 unsigned int max_data_bytes)
6251 char *params = *pparams;
6252 char *pdata = *ppdata;
6254 SMB_STRUCT_STAT sbuf;
6255 NTSTATUS status = NT_STATUS_OK;
6256 struct ea_list *ea_list = NULL;
6258 if (!CAN_WRITE(conn))
6259 return ERROR_DOS(ERRSRV,ERRaccess);
6261 if (total_params < 5) {
6262 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6265 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory, ¶ms[4],
6266 sizeof(directory), total_params - 4, STR_TERMINATE,
6268 if (!NT_STATUS_IS_OK(status)) {
6269 return ERROR_NT(status);
6272 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6274 status = unix_convert(conn, directory, False, NULL, &sbuf);
6275 if (!NT_STATUS_IS_OK(status)) {
6276 return ERROR_NT(status);
6279 status = check_name(conn, directory);
6280 if (!NT_STATUS_IS_OK(status)) {
6281 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6282 return ERROR_NT(status);
6285 /* Any data in this call is an EA list. */
6286 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6287 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6291 * OS/2 workplace shell seems to send SET_EA requests of "null"
6292 * length (4 bytes containing IVAL 4).
6293 * They seem to have no effect. Bug #3212. JRA.
6296 if (total_data != 4) {
6297 if (total_data < 10) {
6298 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6301 if (IVAL(pdata,0) > total_data) {
6302 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6303 IVAL(pdata,0), (unsigned int)total_data));
6304 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6307 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6310 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6312 } else if (IVAL(pdata,0) != 4) {
6313 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6316 status = create_directory(conn, directory);
6318 if (!NT_STATUS_IS_OK(status)) {
6319 return ERROR_NT(status);
6322 /* Try and set any given EA. */
6324 status = set_ea(conn, NULL, directory, ea_list);
6325 if (!NT_STATUS_IS_OK(status)) {
6326 return ERROR_NT(status);
6330 /* Realloc the parameter and data sizes */
6331 *pparams = (char *)SMB_REALLOC(*pparams,2);
6332 if(*pparams == NULL) {
6333 return ERROR_NT(NT_STATUS_NO_MEMORY);
6339 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6344 /****************************************************************************
6345 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6346 We don't actually do this - we just send a null response.
6347 ****************************************************************************/
6349 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6350 char **pparams, int total_params, char **ppdata, int total_data,
6351 unsigned int max_data_bytes)
6353 static uint16 fnf_handle = 257;
6354 char *params = *pparams;
6357 if (total_params < 6) {
6358 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6361 info_level = SVAL(params,4);
6362 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6364 switch (info_level) {
6369 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6372 /* Realloc the parameter and data sizes */
6373 *pparams = (char *)SMB_REALLOC(*pparams,6);
6374 if (*pparams == NULL) {
6375 return ERROR_NT(NT_STATUS_NO_MEMORY);
6379 SSVAL(params,0,fnf_handle);
6380 SSVAL(params,2,0); /* No changes */
6381 SSVAL(params,4,0); /* No EA errors */
6388 send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6393 /****************************************************************************
6394 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6395 changes). Currently this does nothing.
6396 ****************************************************************************/
6398 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6399 char **pparams, int total_params, char **ppdata, int total_data,
6400 unsigned int max_data_bytes)
6402 char *params = *pparams;
6404 DEBUG(3,("call_trans2findnotifynext\n"));
6406 /* Realloc the parameter and data sizes */
6407 *pparams = (char *)SMB_REALLOC(*pparams,4);
6408 if (*pparams == NULL) {
6409 return ERROR_NT(NT_STATUS_NO_MEMORY);
6413 SSVAL(params,0,0); /* No changes */
6414 SSVAL(params,2,0); /* No EA errors */
6416 send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6421 /****************************************************************************
6422 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6423 ****************************************************************************/
6425 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6426 char **pparams, int total_params, char **ppdata, int total_data,
6427 unsigned int max_data_bytes)
6429 char *params = *pparams;
6432 int max_referral_level;
6433 NTSTATUS status = NT_STATUS_OK;
6435 DEBUG(10,("call_trans2getdfsreferral\n"));
6437 if (total_params < 3) {
6438 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6441 max_referral_level = SVAL(params,0);
6443 if(!lp_host_msdfs())
6444 return ERROR_DOS(ERRDOS,ERRbadfunc);
6446 srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), pathname, ¶ms[2],
6447 sizeof(pathname), total_params - 2, STR_TERMINATE);
6448 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6449 return ERROR_NT(status);
6451 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6452 send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6457 #define LMCAT_SPL 0x53
6458 #define LMFUNC_GETJOBID 0x60
6460 /****************************************************************************
6461 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6462 ****************************************************************************/
6464 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6465 char **pparams, int total_params, char **ppdata, int total_data,
6466 unsigned int max_data_bytes)
6468 char *pdata = *ppdata;
6469 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv15));
6471 /* check for an invalid fid before proceeding */
6474 return(ERROR_DOS(ERRDOS,ERRbadfid));
6476 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6477 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6478 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6479 if (*ppdata == NULL) {
6480 return ERROR_NT(NT_STATUS_NO_MEMORY);
6484 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6485 CAN ACCEPT THIS IN UNICODE. JRA. */
6487 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6488 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6489 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6490 send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6493 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6494 return ERROR_DOS(ERRSRV,ERRerror);
6498 /****************************************************************************
6499 Reply to a SMBfindclose (stop trans2 directory search).
6500 ****************************************************************************/
6502 int reply_findclose(connection_struct *conn,
6503 char *inbuf,char *outbuf,int length,int bufsize)
6506 int dptr_num=SVALS(inbuf,smb_vwv0);
6507 START_PROFILE(SMBfindclose);
6509 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6511 dptr_close(&dptr_num);
6513 outsize = set_message(inbuf, outbuf,0,0,False);
6515 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6517 END_PROFILE(SMBfindclose);
6521 /****************************************************************************
6522 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6523 ****************************************************************************/
6525 int reply_findnclose(connection_struct *conn,
6526 char *inbuf,char *outbuf,int length,int bufsize)
6530 START_PROFILE(SMBfindnclose);
6532 dptr_num = SVAL(inbuf,smb_vwv0);
6534 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6536 /* We never give out valid handles for a
6537 findnotifyfirst - so any dptr_num is ok here.
6540 outsize = set_message(inbuf, outbuf,0,0,False);
6542 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6544 END_PROFILE(SMBfindnclose);
6548 static int handle_trans2(connection_struct *conn, struct smb_request *req,
6549 struct trans_state *state,
6550 char *inbuf, char *outbuf, int size, int bufsize)
6554 if (Protocol >= PROTOCOL_NT1) {
6555 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6558 /* Now we must call the relevant TRANS2 function */
6559 switch(state->call) {
6560 case TRANSACT2_OPEN:
6562 START_PROFILE(Trans2_open);
6563 outsize = call_trans2open(
6564 conn, req, inbuf, outbuf, bufsize,
6565 &state->param, state->total_param,
6566 &state->data, state->total_data,
6567 state->max_data_return);
6568 END_PROFILE(Trans2_open);
6572 case TRANSACT2_FINDFIRST:
6574 START_PROFILE(Trans2_findfirst);
6575 outsize = call_trans2findfirst(
6576 conn, inbuf, outbuf, bufsize,
6577 &state->param, state->total_param,
6578 &state->data, state->total_data,
6579 state->max_data_return);
6580 END_PROFILE(Trans2_findfirst);
6584 case TRANSACT2_FINDNEXT:
6586 START_PROFILE(Trans2_findnext);
6587 outsize = call_trans2findnext(
6588 conn, inbuf, outbuf, size, bufsize,
6589 &state->param, state->total_param,
6590 &state->data, state->total_data,
6591 state->max_data_return);
6592 END_PROFILE(Trans2_findnext);
6596 case TRANSACT2_QFSINFO:
6598 START_PROFILE(Trans2_qfsinfo);
6599 outsize = call_trans2qfsinfo(
6600 conn, inbuf, outbuf, size, bufsize,
6601 &state->param, state->total_param,
6602 &state->data, state->total_data,
6603 state->max_data_return);
6604 END_PROFILE(Trans2_qfsinfo);
6608 case TRANSACT2_SETFSINFO:
6610 START_PROFILE(Trans2_setfsinfo);
6611 outsize = call_trans2setfsinfo(
6612 conn, inbuf, outbuf, size, bufsize,
6613 &state->param, state->total_param,
6614 &state->data, state->total_data,
6615 state->max_data_return);
6616 END_PROFILE(Trans2_setfsinfo);
6620 case TRANSACT2_QPATHINFO:
6621 case TRANSACT2_QFILEINFO:
6623 START_PROFILE(Trans2_qpathinfo);
6624 outsize = call_trans2qfilepathinfo(
6625 conn, inbuf, outbuf, size, bufsize, state->call,
6626 &state->param, state->total_param,
6627 &state->data, state->total_data,
6628 state->max_data_return);
6629 END_PROFILE(Trans2_qpathinfo);
6633 case TRANSACT2_SETPATHINFO:
6634 case TRANSACT2_SETFILEINFO:
6636 START_PROFILE(Trans2_setpathinfo);
6637 outsize = call_trans2setfilepathinfo(
6638 conn, req, inbuf, outbuf, size, bufsize, state->call,
6639 &state->param, state->total_param,
6640 &state->data, state->total_data,
6641 state->max_data_return);
6642 END_PROFILE(Trans2_setpathinfo);
6646 case TRANSACT2_FINDNOTIFYFIRST:
6648 START_PROFILE(Trans2_findnotifyfirst);
6649 outsize = call_trans2findnotifyfirst(
6650 conn, inbuf, outbuf, size, bufsize,
6651 &state->param, state->total_param,
6652 &state->data, state->total_data,
6653 state->max_data_return);
6654 END_PROFILE(Trans2_findnotifyfirst);
6658 case TRANSACT2_FINDNOTIFYNEXT:
6660 START_PROFILE(Trans2_findnotifynext);
6661 outsize = call_trans2findnotifynext(
6662 conn, inbuf, outbuf, size, bufsize,
6663 &state->param, state->total_param,
6664 &state->data, state->total_data,
6665 state->max_data_return);
6666 END_PROFILE(Trans2_findnotifynext);
6670 case TRANSACT2_MKDIR:
6672 START_PROFILE(Trans2_mkdir);
6673 outsize = call_trans2mkdir(
6674 conn, inbuf, outbuf, size, bufsize,
6675 &state->param, state->total_param,
6676 &state->data, state->total_data,
6677 state->max_data_return);
6678 END_PROFILE(Trans2_mkdir);
6682 case TRANSACT2_GET_DFS_REFERRAL:
6684 START_PROFILE(Trans2_get_dfs_referral);
6685 outsize = call_trans2getdfsreferral(
6686 conn, inbuf, outbuf, size, bufsize,
6687 &state->param, state->total_param,
6688 &state->data, state->total_data,
6689 state->max_data_return);
6690 END_PROFILE(Trans2_get_dfs_referral);
6694 case TRANSACT2_IOCTL:
6696 START_PROFILE(Trans2_ioctl);
6697 outsize = call_trans2ioctl(
6698 conn, inbuf, outbuf, size, bufsize,
6699 &state->param, state->total_param,
6700 &state->data, state->total_data,
6701 state->max_data_return);
6702 END_PROFILE(Trans2_ioctl);
6707 /* Error in request */
6708 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6709 outsize = ERROR_DOS(ERRSRV,ERRerror);
6715 /****************************************************************************
6716 Reply to a SMBtrans2.
6717 ****************************************************************************/
6719 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6720 int size, int bufsize)
6723 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6724 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6725 unsigned int psoff = SVAL(inbuf, smb_psoff);
6726 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6727 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6728 struct trans_state *state;
6731 START_PROFILE(SMBtrans2);
6733 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6734 if (!NT_STATUS_IS_OK(result)) {
6735 DEBUG(2, ("Got invalid trans2 request: %s\n",
6736 nt_errstr(result)));
6737 END_PROFILE(SMBtrans2);
6738 return ERROR_NT(result);
6741 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6742 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
6743 && (tran_call != TRANSACT2_QFILEINFO)) {
6744 END_PROFILE(SMBtrans2);
6745 return ERROR_DOS(ERRSRV,ERRaccess);
6748 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6749 DEBUG(0, ("talloc failed\n"));
6750 END_PROFILE(SMBtrans2);
6751 return ERROR_NT(NT_STATUS_NO_MEMORY);
6754 state->cmd = SMBtrans2;
6756 state->mid = SVAL(inbuf, smb_mid);
6757 state->vuid = SVAL(inbuf, smb_uid);
6758 state->setup_count = SVAL(inbuf, smb_suwcnt);
6759 state->setup = NULL;
6760 state->total_param = SVAL(inbuf, smb_tpscnt);
6761 state->param = NULL;
6762 state->total_data = SVAL(inbuf, smb_tdscnt);
6764 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6765 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6766 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6767 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6768 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6770 state->call = tran_call;
6772 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6773 is so as a sanity check */
6774 if (state->setup_count != 1) {
6776 * Need to have rc=0 for ioctl to get job id for OS/2.
6777 * Network printing will fail if function is not successful.
6778 * Similar function in reply.c will be used if protocol
6779 * is LANMAN1.0 instead of LM1.2X002.
6780 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6781 * outbuf doesn't have to be set(only job id is used).
6783 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6784 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6785 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6786 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6788 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6789 DEBUG(2,("Transaction is %d\n",tran_call));
6791 END_PROFILE(SMBtrans2);
6792 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6796 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6799 if (state->total_data) {
6800 /* Can't use talloc here, the core routines do realloc on the
6801 * params and data. */
6802 state->data = (char *)SMB_MALLOC(state->total_data);
6803 if (state->data == NULL) {
6804 DEBUG(0,("reply_trans2: data malloc fail for %u "
6805 "bytes !\n", (unsigned int)state->total_data));
6807 END_PROFILE(SMBtrans2);
6808 return(ERROR_DOS(ERRDOS,ERRnomem));
6810 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6812 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6813 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6816 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6819 if (state->total_param) {
6820 /* Can't use talloc here, the core routines do realloc on the
6821 * params and data. */
6822 state->param = (char *)SMB_MALLOC(state->total_param);
6823 if (state->param == NULL) {
6824 DEBUG(0,("reply_trans: param malloc fail for %u "
6825 "bytes !\n", (unsigned int)state->total_param));
6826 SAFE_FREE(state->data);
6828 END_PROFILE(SMBtrans2);
6829 return(ERROR_DOS(ERRDOS,ERRnomem));
6831 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6833 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6834 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6837 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6840 state->received_data = dscnt;
6841 state->received_param = pscnt;
6843 if ((state->received_param == state->total_param) &&
6844 (state->received_data == state->total_data)) {
6846 struct smb_request req;
6847 init_smb_request(&req, (uint8 *)inbuf);
6849 outsize = handle_trans2(conn, &req, state, inbuf, outbuf,
6851 SAFE_FREE(state->data);
6852 SAFE_FREE(state->param);
6854 END_PROFILE(SMBtrans2);
6858 DLIST_ADD(conn->pending_trans, state);
6860 /* We need to send an interim response then receive the rest
6861 of the parameter/data bytes */
6862 outsize = set_message(inbuf, outbuf,0,0,False);
6864 END_PROFILE(SMBtrans2);
6869 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6870 SAFE_FREE(state->data);
6871 SAFE_FREE(state->param);
6873 END_PROFILE(SMBtrans2);
6874 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6878 /****************************************************************************
6879 Reply to a SMBtranss2
6880 ****************************************************************************/
6882 int reply_transs2(connection_struct *conn,
6883 char *inbuf,char *outbuf,int size,int bufsize)
6886 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6887 struct trans_state *state;
6888 struct smb_request req;
6890 START_PROFILE(SMBtranss2);
6894 for (state = conn->pending_trans; state != NULL;
6895 state = state->next) {
6896 if (state->mid == SVAL(inbuf,smb_mid)) {
6901 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6902 END_PROFILE(SMBtranss2);
6903 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6906 /* Revise state->total_param and state->total_data in case they have
6907 changed downwards */
6909 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6910 state->total_param = SVAL(inbuf, smb_tpscnt);
6911 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6912 state->total_data = SVAL(inbuf, smb_tdscnt);
6914 pcnt = SVAL(inbuf, smb_spscnt);
6915 poff = SVAL(inbuf, smb_spsoff);
6916 pdisp = SVAL(inbuf, smb_spsdisp);
6918 dcnt = SVAL(inbuf, smb_sdscnt);
6919 doff = SVAL(inbuf, smb_sdsoff);
6920 ddisp = SVAL(inbuf, smb_sdsdisp);
6922 state->received_param += pcnt;
6923 state->received_data += dcnt;
6925 if ((state->received_data > state->total_data) ||
6926 (state->received_param > state->total_param))
6930 if (pdisp+pcnt > state->total_param)
6932 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6934 if (pdisp > state->total_param)
6936 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6937 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6939 if (state->param + pdisp < state->param)
6942 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6947 if (ddisp+dcnt > state->total_data)
6949 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6951 if (ddisp > state->total_data)
6953 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6954 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6956 if (state->data + ddisp < state->data)
6959 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6963 if ((state->received_param < state->total_param) ||
6964 (state->received_data < state->total_data)) {
6965 END_PROFILE(SMBtranss2);
6969 /* construct_reply_common has done us the favor to pre-fill the
6970 * command field with SMBtranss2 which is wrong :-)
6972 SCVAL(outbuf,smb_com,SMBtrans2);
6974 init_smb_request(&req, (uint8 *)inbuf);
6976 outsize = handle_trans2(conn, &req, state, inbuf, outbuf, size,
6979 DLIST_REMOVE(conn->pending_trans, state);
6980 SAFE_FREE(state->data);
6981 SAFE_FREE(state->param);
6985 END_PROFILE(SMBtranss2);
6986 return(ERROR_DOS(ERRSRV,ERRnosupport));
6989 END_PROFILE(SMBtranss2);
6994 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6995 DLIST_REMOVE(conn->pending_trans, state);
6996 SAFE_FREE(state->data);
6997 SAFE_FREE(state->param);
6999 END_PROFILE(SMBtranss2);
7000 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);