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 static const char *prohibited_ea_names[] = {
94 SAMBA_POSIX_INHERITANCE_EA_NAME,
95 SAMBA_XATTR_DOS_ATTRIB,
99 /****************************************************************************
100 Refuse to allow clients to overwrite our private xattrs.
101 ****************************************************************************/
103 static BOOL samba_private_attr_name(const char *unix_ea_name)
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 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
2028 pstrcpy(resume_name, "..");
2029 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
2030 pstrcpy(resume_name, ".");
2032 return ERROR_NT(ntstatus);
2036 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2037 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2038 resume_key = %d resume name = %s continue=%d level = %d\n",
2039 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2040 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2043 /* W2K3 seems to treat zero as 1. */
2047 switch (info_level) {
2048 case SMB_FIND_INFO_STANDARD:
2049 case SMB_FIND_EA_SIZE:
2050 case SMB_FIND_EA_LIST:
2051 case SMB_FIND_FILE_DIRECTORY_INFO:
2052 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2053 case SMB_FIND_FILE_NAMES_INFO:
2054 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2055 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2056 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2058 case SMB_FIND_FILE_UNIX:
2059 case SMB_FIND_FILE_UNIX_INFO2:
2060 if (!lp_unix_extensions()) {
2061 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2065 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2068 if (info_level == SMB_FIND_EA_LIST) {
2071 if (total_data < 4) {
2072 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2075 ea_size = IVAL(pdata,0);
2076 if (ea_size != total_data) {
2077 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2078 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2079 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2082 if (!lp_ea_support(SNUM(conn))) {
2083 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2086 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2087 return ERROR_NT(NT_STATUS_NO_MEMORY);
2090 /* Pull out the list of names. */
2091 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2093 talloc_destroy(ea_ctx);
2094 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2098 *ppdata = (char *)SMB_REALLOC(
2099 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2100 if(*ppdata == NULL) {
2101 talloc_destroy(ea_ctx);
2102 return ERROR_NT(NT_STATUS_NO_MEMORY);
2107 /* Realloc the params space */
2108 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2109 if(*pparams == NULL ) {
2110 talloc_destroy(ea_ctx);
2111 return ERROR_NT(NT_STATUS_NO_MEMORY);
2116 /* Check that the dptr is valid */
2117 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2118 talloc_destroy(ea_ctx);
2119 return ERROR_DOS(ERRDOS,ERRnofiles);
2122 string_set(&conn->dirpath,dptr_path(dptr_num));
2124 /* Get the wildcard mask from the dptr */
2125 if((p = dptr_wcard(dptr_num))== NULL) {
2126 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2127 talloc_destroy(ea_ctx);
2128 return ERROR_DOS(ERRDOS,ERRnofiles);
2132 pstrcpy(directory,conn->dirpath);
2134 /* Get the attr mask from the dptr */
2135 dirtype = dptr_attr(dptr_num);
2137 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2138 dptr_num, mask, dirtype,
2140 dptr_TellDir(conn->dirptr)));
2142 /* We don't need to check for VOL here as this is returned by
2143 a different TRANS2 call. */
2145 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2146 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2147 dont_descend = True;
2150 space_remaining = max_data_bytes;
2151 out_of_space = False;
2154 * Seek to the correct position. We no longer use the resume key but
2155 * depend on the last file name instead.
2158 if(*resume_name && !continue_bit) {
2161 long current_pos = 0;
2163 * Remember, mangle_map is called by
2164 * get_lanman2_dir_entry(), so the resume name
2165 * could be mangled. Ensure we check the unmangled name.
2168 if (mangle_is_mangled(resume_name, conn->params)) {
2169 mangle_check_cache(resume_name, sizeof(resume_name)-1,
2174 * Fix for NT redirector problem triggered by resume key indexes
2175 * changing between directory scans. We now return a resume key of 0
2176 * and instead look for the filename to continue from (also given
2177 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2178 * findfirst/findnext (as is usual) then the directory pointer
2179 * should already be at the correct place.
2182 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2183 } /* end if resume_name && !continue_bit */
2185 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2186 BOOL got_exact_match = False;
2188 /* this is a heuristic to avoid seeking the dirptr except when
2189 absolutely necessary. It allows for a filename of about 40 chars */
2190 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2191 out_of_space = True;
2194 finished = !get_lanman2_dir_entry(conn,
2196 mask,dirtype,info_level,
2197 requires_resume_key,dont_descend,
2198 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2199 &last_entry_off, ea_list, ea_ctx);
2202 if (finished && out_of_space)
2205 if (!finished && !out_of_space)
2209 * As an optimisation if we know we aren't looking
2210 * for a wildcard name (ie. the name matches the wildcard exactly)
2211 * then we can finish on any (first) match.
2212 * This speeds up large directory searches. JRA.
2218 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2221 talloc_destroy(ea_ctx);
2223 /* Check if we can close the dirptr */
2224 if(close_after_request || (finished && close_if_end)) {
2225 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2226 dptr_close(&dptr_num); /* This frees up the saved mask */
2229 /* Set up the return parameter block */
2230 SSVAL(params,0,numentries);
2231 SSVAL(params,2,finished);
2232 SSVAL(params,4,0); /* Never an EA error */
2233 SSVAL(params,6,last_entry_off);
2235 send_trans2_replies(inbuf, outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2237 if ((! *directory) && dptr_path(dptr_num))
2238 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2240 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2241 smb_fn_name(CVAL(inbuf,smb_com)),
2242 mask, directory, dirtype, numentries ) );
2247 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2249 E_md4hash(lp_servicename(SNUM(conn)),objid);
2253 /****************************************************************************
2254 Reply to a TRANS2_QFSINFO (query filesystem info).
2255 ****************************************************************************/
2257 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2258 char **pparams, int total_params, char **ppdata, int total_data,
2259 unsigned int max_data_bytes)
2262 char *params = *pparams;
2266 const char *vname = volume_label(SNUM(conn));
2267 int snum = SNUM(conn);
2268 char *fstype = lp_fstype(SNUM(conn));
2271 if (total_params < 2) {
2272 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2275 info_level = SVAL(params,0);
2277 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2279 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2280 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2281 return ERROR_DOS(ERRSRV,ERRinvdevice);
2284 *ppdata = (char *)SMB_REALLOC(
2285 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2286 if (*ppdata == NULL ) {
2287 return ERROR_NT(NT_STATUS_NO_MEMORY);
2291 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2293 switch (info_level) {
2294 case SMB_INFO_ALLOCATION:
2296 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2298 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2299 return(UNIXERROR(ERRHRD,ERRgeneral));
2302 block_size = lp_block_size(snum);
2303 if (bsize < block_size) {
2304 SMB_BIG_UINT factor = block_size/bsize;
2309 if (bsize > block_size) {
2310 SMB_BIG_UINT factor = bsize/block_size;
2315 bytes_per_sector = 512;
2316 sectors_per_unit = bsize/bytes_per_sector;
2318 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2319 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2320 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2322 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2323 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2324 SIVAL(pdata,l1_cUnit,dsize);
2325 SIVAL(pdata,l1_cUnitAvail,dfree);
2326 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2330 case SMB_INFO_VOLUME:
2331 /* Return volume name */
2333 * Add volume serial number - hash of a combination of
2334 * the called hostname and the service name.
2336 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2338 * Win2k3 and previous mess this up by sending a name length
2339 * one byte short. I believe only older clients (OS/2 Win9x) use
2340 * this call so try fixing this by adding a terminating null to
2341 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2343 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2344 SCVAL(pdata,l2_vol_cch,len);
2345 data_len = l2_vol_szVolLabel + len;
2346 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2347 (unsigned)st.st_ctime, len, vname));
2350 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2351 case SMB_FS_ATTRIBUTE_INFORMATION:
2354 #if defined(HAVE_SYS_QUOTAS)
2355 quota_flag = FILE_VOLUME_QUOTAS;
2358 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2359 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2360 FILE_SUPPORTS_OBJECT_IDS|
2361 FILE_UNICODE_ON_DISK|
2362 quota_flag); /* FS ATTRIBUTES */
2364 SIVAL(pdata,4,255); /* Max filename component length */
2365 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2366 and will think we can't do long filenames */
2367 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2369 data_len = 12 + len;
2372 case SMB_QUERY_FS_LABEL_INFO:
2373 case SMB_FS_LABEL_INFORMATION:
2374 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2379 case SMB_QUERY_FS_VOLUME_INFO:
2380 case SMB_FS_VOLUME_INFORMATION:
2383 * Add volume serial number - hash of a combination of
2384 * the called hostname and the service name.
2386 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2387 (str_checksum(get_local_machine_name())<<16));
2389 /* Max label len is 32 characters. */
2390 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2391 SIVAL(pdata,12,len);
2394 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2395 (int)strlen(vname),vname, lp_servicename(snum)));
2398 case SMB_QUERY_FS_SIZE_INFO:
2399 case SMB_FS_SIZE_INFORMATION:
2401 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2403 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2404 return(UNIXERROR(ERRHRD,ERRgeneral));
2406 block_size = lp_block_size(snum);
2407 if (bsize < block_size) {
2408 SMB_BIG_UINT factor = block_size/bsize;
2413 if (bsize > block_size) {
2414 SMB_BIG_UINT factor = bsize/block_size;
2419 bytes_per_sector = 512;
2420 sectors_per_unit = bsize/bytes_per_sector;
2421 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2422 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2423 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2424 SBIG_UINT(pdata,0,dsize);
2425 SBIG_UINT(pdata,8,dfree);
2426 SIVAL(pdata,16,sectors_per_unit);
2427 SIVAL(pdata,20,bytes_per_sector);
2431 case SMB_FS_FULL_SIZE_INFORMATION:
2433 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2435 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2436 return(UNIXERROR(ERRHRD,ERRgeneral));
2438 block_size = lp_block_size(snum);
2439 if (bsize < block_size) {
2440 SMB_BIG_UINT factor = block_size/bsize;
2445 if (bsize > block_size) {
2446 SMB_BIG_UINT factor = bsize/block_size;
2451 bytes_per_sector = 512;
2452 sectors_per_unit = bsize/bytes_per_sector;
2453 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2454 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2455 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2456 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2457 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2458 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2459 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2460 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2464 case SMB_QUERY_FS_DEVICE_INFO:
2465 case SMB_FS_DEVICE_INFORMATION:
2467 SIVAL(pdata,0,0); /* dev type */
2468 SIVAL(pdata,4,0); /* characteristics */
2471 #ifdef HAVE_SYS_QUOTAS
2472 case SMB_FS_QUOTA_INFORMATION:
2474 * what we have to send --metze:
2476 * Unknown1: 24 NULL bytes
2477 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2478 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2479 * Quota Flags: 2 byte :
2480 * Unknown3: 6 NULL bytes
2484 * details for Quota Flags:
2486 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2487 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2488 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2489 * 0x0001 Enable Quotas: enable quota for this fs
2493 /* we need to fake up a fsp here,
2494 * because its not send in this call
2497 SMB_NTQUOTA_STRUCT quotas;
2500 ZERO_STRUCT(quotas);
2506 if (current_user.ut.uid != 0) {
2507 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2508 lp_servicename(SNUM(conn)),conn->user));
2509 return ERROR_DOS(ERRDOS,ERRnoaccess);
2512 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2513 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2514 return ERROR_DOS(ERRSRV,ERRerror);
2519 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2521 /* Unknown1 24 NULL bytes*/
2522 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2523 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2524 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2526 /* Default Soft Quota 8 bytes */
2527 SBIG_UINT(pdata,24,quotas.softlim);
2529 /* Default Hard Quota 8 bytes */
2530 SBIG_UINT(pdata,32,quotas.hardlim);
2532 /* Quota flag 2 bytes */
2533 SSVAL(pdata,40,quotas.qflags);
2535 /* Unknown3 6 NULL bytes */
2541 #endif /* HAVE_SYS_QUOTAS */
2542 case SMB_FS_OBJECTID_INFORMATION:
2544 unsigned char objid[16];
2545 memcpy(pdata,create_volume_objectid(conn, objid),16);
2551 * Query the version and capabilities of the CIFS UNIX extensions
2555 case SMB_QUERY_CIFS_UNIX_INFO:
2556 if (!lp_unix_extensions()) {
2557 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2560 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2561 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2562 /* We have POSIX ACLs, pathname and locking capability. */
2563 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2564 CIFS_UNIX_POSIX_ACLS_CAP|
2565 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2566 CIFS_UNIX_FCNTL_LOCKS_CAP|
2567 CIFS_UNIX_EXTATTR_CAP|
2568 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2569 /* Ensure we don't do this on signed or sealed data. */
2570 (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2574 case SMB_QUERY_POSIX_FS_INFO:
2577 vfs_statvfs_struct svfs;
2579 if (!lp_unix_extensions()) {
2580 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2583 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2587 SIVAL(pdata,0,svfs.OptimalTransferSize);
2588 SIVAL(pdata,4,svfs.BlockSize);
2589 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2590 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2591 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2592 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2593 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2594 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2595 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2597 } else if (rc == EOPNOTSUPP) {
2598 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2599 #endif /* EOPNOTSUPP */
2601 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2602 return ERROR_DOS(ERRSRV,ERRerror);
2607 case SMB_QUERY_POSIX_WHOAMI:
2613 if (!lp_unix_extensions()) {
2614 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2617 if (max_data_bytes < 40) {
2618 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2621 /* We ARE guest if global_sid_Builtin_Guests is
2622 * in our list of SIDs.
2624 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2625 current_user.nt_user_token)) {
2626 flags |= SMB_WHOAMI_GUEST;
2629 /* We are NOT guest if global_sid_Authenticated_Users
2630 * is in our list of SIDs.
2632 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2633 current_user.nt_user_token)) {
2634 flags &= ~SMB_WHOAMI_GUEST;
2637 /* NOTE: 8 bytes for UID/GID, irrespective of native
2638 * platform size. This matches
2639 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2641 data_len = 4 /* flags */
2648 + 4 /* pad/reserved */
2649 + (current_user.ut.ngroups * 8)
2651 + (current_user.nt_user_token->num_sids *
2655 SIVAL(pdata, 0, flags);
2656 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2657 SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2658 SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2661 if (data_len >= max_data_bytes) {
2662 /* Potential overflow, skip the GIDs and SIDs. */
2664 SIVAL(pdata, 24, 0); /* num_groups */
2665 SIVAL(pdata, 28, 0); /* num_sids */
2666 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2667 SIVAL(pdata, 36, 0); /* reserved */
2673 SIVAL(pdata, 24, current_user.ut.ngroups);
2675 current_user.nt_user_token->num_sids);
2677 /* We walk the SID list twice, but this call is fairly
2678 * infrequent, and I don't expect that it's performance
2679 * sensitive -- jpeach
2681 for (i = 0, sid_bytes = 0;
2682 i < current_user.nt_user_token->num_sids; ++i) {
2684 sid_size(¤t_user.nt_user_token->user_sids[i]);
2687 /* SID list byte count */
2688 SIVAL(pdata, 32, sid_bytes);
2690 /* 4 bytes pad/reserved - must be zero */
2691 SIVAL(pdata, 36, 0);
2695 for (i = 0; i < current_user.ut.ngroups; ++i) {
2696 SBIG_UINT(pdata, data_len,
2697 (SMB_BIG_UINT)current_user.ut.groups[i]);
2703 i < current_user.nt_user_token->num_sids; ++i) {
2705 sid_size(¤t_user.nt_user_token->user_sids[i]);
2707 sid_linearize(pdata + data_len, sid_len,
2708 ¤t_user.nt_user_token->user_sids[i]);
2709 data_len += sid_len;
2715 case SMB_MAC_QUERY_FS_INFO:
2717 * Thursby MAC extension... ONLY on NTFS filesystems
2718 * once we do streams then we don't need this
2720 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2722 SIVAL(pdata,84,0x100); /* Don't support mac... */
2727 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2731 send_trans2_replies(inbuf, outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2733 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2738 /****************************************************************************
2739 Reply to a TRANS2_SETFSINFO (set filesystem info).
2740 ****************************************************************************/
2742 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2743 char **pparams, int total_params, char **ppdata, int total_data,
2744 unsigned int max_data_bytes)
2746 char *pdata = *ppdata;
2747 char *params = *pparams;
2751 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2754 if (total_params < 4) {
2755 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2757 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2760 info_level = SVAL(params,2);
2762 switch(info_level) {
2763 case SMB_SET_CIFS_UNIX_INFO:
2765 uint16 client_unix_major;
2766 uint16 client_unix_minor;
2767 uint32 client_unix_cap_low;
2768 uint32 client_unix_cap_high;
2770 if (!lp_unix_extensions()) {
2771 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2774 /* There should be 12 bytes of capabilities set. */
2775 if (total_data < 8) {
2776 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2778 client_unix_major = SVAL(pdata,0);
2779 client_unix_minor = SVAL(pdata,2);
2780 client_unix_cap_low = IVAL(pdata,4);
2781 client_unix_cap_high = IVAL(pdata,8);
2782 /* Just print these values for now. */
2783 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2784 cap_low = 0x%x, cap_high = 0x%x\n",
2785 (unsigned int)client_unix_major,
2786 (unsigned int)client_unix_minor,
2787 (unsigned int)client_unix_cap_low,
2788 (unsigned int)client_unix_cap_high ));
2790 /* Here is where we must switch to posix pathname processing... */
2791 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2792 lp_set_posix_pathnames();
2793 mangle_change_to_posix();
2796 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2797 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2798 /* Client that knows how to do posix locks,
2799 * but not posix open/mkdir operations. Set a
2800 * default type for read/write checks. */
2802 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2807 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2810 size_t param_len = 0;
2811 size_t data_len = total_data;
2813 if (!lp_unix_extensions()) {
2814 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2817 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2819 status = srv_request_encryption_setup(conn,
2820 (unsigned char **)ppdata,
2822 (unsigned char **)pparams,
2826 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2827 error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
2828 } else if (!NT_STATUS_IS_OK(status)) {
2829 return ERROR_NT(status);
2832 send_trans2_replies(inbuf, outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes);
2834 if (NT_STATUS_IS_OK(status)) {
2835 /* Server-side transport encryption is now *on*. */
2836 status = srv_encryption_start(conn);
2837 if (!NT_STATUS_IS_OK(status)) {
2838 exit_server_cleanly("Failure in setting up encrypted transport");
2843 case SMB_FS_QUOTA_INFORMATION:
2845 files_struct *fsp = NULL;
2846 SMB_NTQUOTA_STRUCT quotas;
2848 ZERO_STRUCT(quotas);
2851 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2852 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2853 lp_servicename(SNUM(conn)),conn->user));
2854 return ERROR_DOS(ERRSRV,ERRaccess);
2857 /* note: normaly there're 48 bytes,
2858 * but we didn't use the last 6 bytes for now
2861 fsp = file_fsp(params,0);
2862 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2863 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2864 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2867 if (total_data < 42) {
2868 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2870 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2873 /* unknown_1 24 NULL bytes in pdata*/
2875 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2876 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2877 #ifdef LARGE_SMB_OFF_T
2878 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2879 #else /* LARGE_SMB_OFF_T */
2880 if ((IVAL(pdata,28) != 0)&&
2881 ((quotas.softlim != 0xFFFFFFFF)||
2882 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2883 /* more than 32 bits? */
2884 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2886 #endif /* LARGE_SMB_OFF_T */
2888 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2889 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2890 #ifdef LARGE_SMB_OFF_T
2891 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2892 #else /* LARGE_SMB_OFF_T */
2893 if ((IVAL(pdata,36) != 0)&&
2894 ((quotas.hardlim != 0xFFFFFFFF)||
2895 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2896 /* more than 32 bits? */
2897 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2899 #endif /* LARGE_SMB_OFF_T */
2901 /* quota_flags 2 bytes **/
2902 quotas.qflags = SVAL(pdata,40);
2904 /* unknown_2 6 NULL bytes follow*/
2906 /* now set the quotas */
2907 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2908 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2909 return ERROR_DOS(ERRSRV,ERRerror);
2915 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2917 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2922 * sending this reply works fine,
2923 * but I'm not sure it's the same
2924 * like windows do...
2927 outsize = set_message(inbuf, outbuf,10,0,True);
2932 #if defined(HAVE_POSIX_ACLS)
2933 /****************************************************************************
2934 Utility function to count the number of entries in a POSIX acl.
2935 ****************************************************************************/
2937 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2939 unsigned int ace_count = 0;
2940 int entry_id = SMB_ACL_FIRST_ENTRY;
2941 SMB_ACL_ENTRY_T entry;
2943 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2945 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2946 entry_id = SMB_ACL_NEXT_ENTRY;
2953 /****************************************************************************
2954 Utility function to marshall a POSIX acl into wire format.
2955 ****************************************************************************/
2957 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2959 int entry_id = SMB_ACL_FIRST_ENTRY;
2960 SMB_ACL_ENTRY_T entry;
2962 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2963 SMB_ACL_TAG_T tagtype;
2964 SMB_ACL_PERMSET_T permset;
2965 unsigned char perms = 0;
2966 unsigned int own_grp;
2969 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2970 entry_id = SMB_ACL_NEXT_ENTRY;
2973 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2974 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2978 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2979 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2983 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2984 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2985 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2987 SCVAL(pdata,1,perms);
2990 case SMB_ACL_USER_OBJ:
2991 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2992 own_grp = (unsigned int)pst->st_uid;
2993 SIVAL(pdata,2,own_grp);
2998 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3000 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3002 own_grp = (unsigned int)*puid;
3003 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3004 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3005 SIVAL(pdata,2,own_grp);
3009 case SMB_ACL_GROUP_OBJ:
3010 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3011 own_grp = (unsigned int)pst->st_gid;
3012 SIVAL(pdata,2,own_grp);
3017 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3019 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3021 own_grp = (unsigned int)*pgid;
3022 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3023 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3024 SIVAL(pdata,2,own_grp);
3029 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3030 SIVAL(pdata,2,0xFFFFFFFF);
3031 SIVAL(pdata,6,0xFFFFFFFF);
3034 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3035 SIVAL(pdata,2,0xFFFFFFFF);
3036 SIVAL(pdata,6,0xFFFFFFFF);
3039 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3042 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3049 /****************************************************************************
3050 Store the FILE_UNIX_BASIC info.
3051 ****************************************************************************/
3053 static char *store_file_unix_basic(connection_struct *conn,
3056 const SMB_STRUCT_STAT *psbuf)
3058 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3059 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3061 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3064 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3067 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3068 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3069 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3072 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3076 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3080 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3083 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3087 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3091 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3094 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3098 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3105 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3106 * the chflags(2) (or equivalent) flags.
3108 * XXX: this really should be behind the VFS interface. To do this, we would
3109 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3110 * Each VFS module could then implement it's own mapping as appropriate for the
3111 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3113 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3117 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3121 { UF_IMMUTABLE, EXT_IMMUTABLE },
3125 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3129 { UF_HIDDEN, EXT_HIDDEN },
3132 /* Do not remove. We need to guarantee that this array has at least one
3133 * entry to build on HP-UX.
3139 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3140 uint32 *smb_fflags, uint32 *smb_fmask)
3142 #ifdef HAVE_STAT_ST_FLAGS
3145 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3146 *smb_fmask |= info2_flags_map[i].smb_fflag;
3147 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3148 *smb_fflags |= info2_flags_map[i].smb_fflag;
3151 #endif /* HAVE_STAT_ST_FLAGS */
3154 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3155 const uint32 smb_fflags,
3156 const uint32 smb_fmask,
3159 #ifdef HAVE_STAT_ST_FLAGS
3160 uint32 max_fmask = 0;
3163 *stat_fflags = psbuf->st_flags;
3165 /* For each flags requested in smb_fmask, check the state of the
3166 * corresponding flag in smb_fflags and set or clear the matching
3170 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3171 max_fmask |= info2_flags_map[i].smb_fflag;
3172 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3173 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3174 *stat_fflags |= info2_flags_map[i].stat_fflag;
3176 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3181 /* If smb_fmask is asking to set any bits that are not supported by
3182 * our flag mappings, we should fail.
3184 if ((smb_fmask & max_fmask) != smb_fmask) {
3191 #endif /* HAVE_STAT_ST_FLAGS */
3195 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3196 * of file flags and birth (create) time.
3198 static char *store_file_unix_basic_info2(connection_struct *conn,
3201 const SMB_STRUCT_STAT *psbuf)
3203 uint32 file_flags = 0;
3204 uint32 flags_mask = 0;
3206 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3208 /* Create (birth) time 64 bit */
3209 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3212 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3213 SIVAL(pdata, 0, file_flags); /* flags */
3214 SIVAL(pdata, 4, flags_mask); /* mask */
3220 /****************************************************************************
3221 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3222 ****************************************************************************/
3224 static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3225 unsigned int tran_call,
3226 char **pparams, int total_params, char **ppdata, int total_data,
3227 unsigned int max_data_bytes)
3229 char *params = *pparams;
3230 char *pdata = *ppdata;
3231 unsigned int data_size = 0;
3232 unsigned int param_size = 2;
3234 smb_np_struct *p_pipe = NULL;
3237 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3240 if (total_params < 4) {
3241 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3244 p_pipe = get_rpc_pipe_p(params,0);
3245 if (p_pipe == NULL) {
3246 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3249 info_level = SVAL(params,2);
3251 *pparams = (char *)SMB_REALLOC(*pparams,2);
3252 if (*pparams == NULL) {
3253 return ERROR_NT(NT_STATUS_NO_MEMORY);
3257 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3258 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3259 if (*ppdata == NULL ) {
3260 return ERROR_NT(NT_STATUS_NO_MEMORY);
3264 switch (info_level) {
3265 case SMB_FILE_STANDARD_INFORMATION:
3267 SOFF_T(pdata,0,4096LL);
3274 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3277 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3282 /****************************************************************************
3283 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3284 file name or file id).
3285 ****************************************************************************/
3287 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3288 unsigned int tran_call,
3289 char **pparams, int total_params, char **ppdata, int total_data,
3290 unsigned int max_data_bytes)
3292 char *params = *pparams;
3293 char *pdata = *ppdata;
3297 SMB_OFF_T file_size=0;
3298 SMB_BIG_UINT allocation_size=0;
3299 unsigned int data_size = 0;
3300 unsigned int param_size = 2;
3301 SMB_STRUCT_STAT sbuf;
3302 pstring fname, dos_fname;
3307 BOOL delete_pending = False;
3309 time_t create_time, mtime, atime;
3310 struct timespec create_time_ts, mtime_ts, atime_ts;
3311 files_struct *fsp = NULL;
3312 TALLOC_CTX *data_ctx = NULL;
3313 struct ea_list *ea_list = NULL;
3314 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3315 char *lock_data = NULL;
3318 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3322 if (tran_call == TRANSACT2_QFILEINFO) {
3323 if (total_params < 4) {
3324 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3328 return call_trans2qpipeinfo(conn,
3341 fsp = file_fsp(params,0);
3342 info_level = SVAL(params,2);
3344 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3346 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3347 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3350 if(fsp && (fsp->fake_file_handle)) {
3352 * This is actually for the QUOTA_FAKE_FILE --metze
3355 pstrcpy(fname, fsp->fsp_name);
3356 /* We know this name is ok, it's already passed the checks. */
3358 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3360 * This is actually a QFILEINFO on a directory
3361 * handle (returned from an NT SMB). NT5.0 seems
3362 * to do this call. JRA.
3364 /* We know this name is ok, it's already passed the checks. */
3365 pstrcpy(fname, fsp->fsp_name);
3367 if (INFO_LEVEL_IS_UNIX(info_level)) {
3368 /* Always do lstat for UNIX calls. */
3369 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3370 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3371 return UNIXERROR(ERRDOS,ERRbadpath);
3373 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3374 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3375 return UNIXERROR(ERRDOS,ERRbadpath);
3378 delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf));
3381 * Original code - this is an open file.
3383 CHECK_FSP(fsp,conn);
3385 pstrcpy(fname, fsp->fsp_name);
3386 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3387 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3388 return(UNIXERROR(ERRDOS,ERRbadfid));
3390 pos = fsp->fh->position_information;
3391 delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf));
3392 access_mask = fsp->access_mask;
3395 NTSTATUS status = NT_STATUS_OK;
3398 if (total_params < 7) {
3399 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3402 info_level = SVAL(params,0);
3404 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3406 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3407 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3410 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, ¶ms[6],
3411 sizeof(fname), total_params - 6,
3412 STR_TERMINATE, &status);
3413 if (!NT_STATUS_IS_OK(status)) {
3414 return ERROR_NT(status);
3417 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3418 if (!NT_STATUS_IS_OK(status)) {
3419 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3420 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3422 return ERROR_NT(status);
3425 status = unix_convert(conn, fname, False, NULL, &sbuf);
3426 if (!NT_STATUS_IS_OK(status)) {
3427 return ERROR_NT(status);
3429 status = check_name(conn, fname);
3430 if (!NT_STATUS_IS_OK(status)) {
3431 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3432 return ERROR_NT(status);
3435 if (INFO_LEVEL_IS_UNIX(info_level)) {
3436 /* Always do lstat for UNIX calls. */
3437 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3438 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3439 return UNIXERROR(ERRDOS,ERRbadpath);
3441 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3442 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3443 return UNIXERROR(ERRDOS,ERRbadpath);
3446 delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf));
3447 if (delete_pending) {
3448 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3452 nlink = sbuf.st_nlink;
3454 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3455 /* NTFS does not seem to count ".." */
3459 if ((nlink > 0) && delete_pending) {
3463 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3464 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3467 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3468 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3470 p = strrchr_m(fname,'/');
3476 mode = dos_mode(conn,fname,&sbuf);
3478 mode = FILE_ATTRIBUTE_NORMAL;
3480 fullpathname = fname;
3482 file_size = get_file_size(sbuf);
3484 /* Pull out any data sent here before we realloc. */
3485 switch (info_level) {
3486 case SMB_INFO_QUERY_EAS_FROM_LIST:
3488 /* Pull any EA list from the data portion. */
3491 if (total_data < 4) {
3492 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3494 ea_size = IVAL(pdata,0);
3496 if (total_data > 0 && ea_size != total_data) {
3497 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3498 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3499 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3502 if (!lp_ea_support(SNUM(conn))) {
3503 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3506 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3507 return ERROR_NT(NT_STATUS_NO_MEMORY);
3510 /* Pull out the list of names. */
3511 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3513 talloc_destroy(data_ctx);
3514 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3519 case SMB_QUERY_POSIX_LOCK:
3521 if (fsp == NULL || fsp->fh->fd == -1) {
3522 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3525 if (total_data != POSIX_LOCK_DATA_SIZE) {
3526 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3529 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3530 return ERROR_NT(NT_STATUS_NO_MEMORY);
3533 /* Copy the lock range data. */
3534 lock_data = (char *)TALLOC_MEMDUP(
3535 data_ctx, pdata, total_data);
3537 talloc_destroy(data_ctx);
3538 return ERROR_NT(NT_STATUS_NO_MEMORY);
3545 *pparams = (char *)SMB_REALLOC(*pparams,2);
3546 if (*pparams == NULL) {
3547 talloc_destroy(data_ctx);
3548 return ERROR_NT(NT_STATUS_NO_MEMORY);
3552 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3553 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3554 if (*ppdata == NULL ) {
3555 talloc_destroy(data_ctx);
3556 return ERROR_NT(NT_STATUS_NO_MEMORY);
3560 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3561 mtime_ts = get_mtimespec(&sbuf);
3562 atime_ts = get_atimespec(&sbuf);
3564 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3567 if (!null_timespec(fsp->pending_modtime)) {
3568 /* the pending modtime overrides the current modtime */
3569 mtime_ts = fsp->pending_modtime;
3572 /* Do we have this path open ? */
3573 files_struct *fsp1 = file_find_di_first(file_id_sbuf(&sbuf));
3574 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3575 /* the pending modtime overrides the current modtime */
3576 mtime_ts = fsp1->pending_modtime;
3578 if (fsp1 && fsp1->initial_allocation_size) {
3579 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3583 if (lp_dos_filetime_resolution(SNUM(conn))) {
3584 dos_filetime_timespec(&create_time_ts);
3585 dos_filetime_timespec(&mtime_ts);
3586 dos_filetime_timespec(&atime_ts);
3589 create_time = convert_timespec_to_time_t(create_time_ts);
3590 mtime = convert_timespec_to_time_t(mtime_ts);
3591 atime = convert_timespec_to_time_t(atime_ts);
3593 /* NT expects the name to be in an exact form of the *full*
3594 filename. See the trans2 torture test */
3595 if (strequal(base_name,".")) {
3596 pstrcpy(dos_fname, "\\");
3598 pstr_sprintf(dos_fname, "\\%s", fname);
3599 string_replace(dos_fname, '/', '\\');
3602 switch (info_level) {
3603 case SMB_INFO_STANDARD:
3604 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3606 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3607 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3608 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3609 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3610 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3611 SSVAL(pdata,l1_attrFile,mode);
3614 case SMB_INFO_QUERY_EA_SIZE:
3616 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3617 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3619 srv_put_dos_date2(pdata,0,create_time);
3620 srv_put_dos_date2(pdata,4,atime);
3621 srv_put_dos_date2(pdata,8,mtime); /* write time */
3622 SIVAL(pdata,12,(uint32)file_size);
3623 SIVAL(pdata,16,(uint32)allocation_size);
3624 SSVAL(pdata,20,mode);
3625 SIVAL(pdata,22,ea_size);
3629 case SMB_INFO_IS_NAME_VALID:
3630 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3631 if (tran_call == TRANSACT2_QFILEINFO) {
3632 /* os/2 needs this ? really ?*/
3633 return ERROR_DOS(ERRDOS,ERRbadfunc);
3639 case SMB_INFO_QUERY_EAS_FROM_LIST:
3641 size_t total_ea_len = 0;
3642 struct ea_list *ea_file_list = NULL;
3644 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3646 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3647 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3649 if (!ea_list || (total_ea_len > data_size)) {
3650 talloc_destroy(data_ctx);
3652 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3656 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3657 talloc_destroy(data_ctx);
3661 case SMB_INFO_QUERY_ALL_EAS:
3663 /* We have data_size bytes to put EA's into. */
3664 size_t total_ea_len = 0;
3666 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3668 data_ctx = talloc_init("ea_ctx");
3670 return ERROR_NT(NT_STATUS_NO_MEMORY);
3673 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3674 if (!ea_list || (total_ea_len > data_size)) {
3675 talloc_destroy(data_ctx);
3677 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3681 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3682 talloc_destroy(data_ctx);
3686 case SMB_FILE_BASIC_INFORMATION:
3687 case SMB_QUERY_FILE_BASIC_INFO:
3689 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3690 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3691 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3693 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3697 put_long_date_timespec(pdata,create_time_ts);
3698 put_long_date_timespec(pdata+8,atime_ts);
3699 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3700 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3701 SIVAL(pdata,32,mode);
3703 DEBUG(5,("SMB_QFBI - "));
3704 DEBUG(5,("create: %s ", ctime(&create_time)));
3705 DEBUG(5,("access: %s ", ctime(&atime)));
3706 DEBUG(5,("write: %s ", ctime(&mtime)));
3707 DEBUG(5,("change: %s ", ctime(&mtime)));
3708 DEBUG(5,("mode: %x\n", mode));
3711 case SMB_FILE_STANDARD_INFORMATION:
3712 case SMB_QUERY_FILE_STANDARD_INFO:
3714 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3716 SOFF_T(pdata,0,allocation_size);
3717 SOFF_T(pdata,8,file_size);
3718 SIVAL(pdata,16,nlink);
3719 SCVAL(pdata,20,delete_pending?1:0);
3720 SCVAL(pdata,21,(mode&aDIR)?1:0);
3721 SSVAL(pdata,22,0); /* Padding. */
3724 case SMB_FILE_EA_INFORMATION:
3725 case SMB_QUERY_FILE_EA_INFO:
3727 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3728 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3730 SIVAL(pdata,0,ea_size);
3734 /* Get the 8.3 name - used if NT SMB was negotiated. */
3735 case SMB_QUERY_FILE_ALT_NAME_INFO:
3736 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3740 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3741 pstrcpy(short_name,base_name);
3742 /* Mangle if not already 8.3 */
3743 if(!mangle_is_8_3(short_name, True, conn->params)) {
3744 mangle_map(short_name,True,True,conn->params);
3746 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3747 data_size = 4 + len;
3752 case SMB_QUERY_FILE_NAME_INFO:
3754 this must be *exactly* right for ACLs on mapped drives to work
3756 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3757 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3758 data_size = 4 + len;
3762 case SMB_FILE_ALLOCATION_INFORMATION:
3763 case SMB_QUERY_FILE_ALLOCATION_INFO:
3764 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3766 SOFF_T(pdata,0,allocation_size);
3769 case SMB_FILE_END_OF_FILE_INFORMATION:
3770 case SMB_QUERY_FILE_END_OF_FILEINFO:
3771 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3773 SOFF_T(pdata,0,file_size);
3776 case SMB_QUERY_FILE_ALL_INFO:
3777 case SMB_FILE_ALL_INFORMATION:
3779 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3780 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3781 put_long_date_timespec(pdata,create_time_ts);
3782 put_long_date_timespec(pdata+8,atime_ts);
3783 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3784 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3785 SIVAL(pdata,32,mode);
3786 SIVAL(pdata,36,0); /* padding. */
3788 SOFF_T(pdata,0,allocation_size);
3789 SOFF_T(pdata,8,file_size);
3790 SIVAL(pdata,16,nlink);
3791 SCVAL(pdata,20,delete_pending);
3792 SCVAL(pdata,21,(mode&aDIR)?1:0);
3795 SIVAL(pdata,0,ea_size);
3796 pdata += 4; /* EA info */
3797 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3800 data_size = PTR_DIFF(pdata,(*ppdata));
3803 case SMB_FILE_INTERNAL_INFORMATION:
3804 /* This should be an index number - looks like
3807 I think this causes us to fail the IFSKIT
3808 BasicFileInformationTest. -tpot */
3810 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3811 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3812 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3816 case SMB_FILE_ACCESS_INFORMATION:
3817 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3818 SIVAL(pdata,0,access_mask);
3822 case SMB_FILE_NAME_INFORMATION:
3823 /* Pathname with leading '\'. */
3826 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3827 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3828 SIVAL(pdata,0,byte_len);
3829 data_size = 4 + byte_len;
3833 case SMB_FILE_DISPOSITION_INFORMATION:
3834 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3836 SCVAL(pdata,0,delete_pending);
3839 case SMB_FILE_POSITION_INFORMATION:
3840 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3842 SOFF_T(pdata,0,pos);
3845 case SMB_FILE_MODE_INFORMATION:
3846 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3847 SIVAL(pdata,0,mode);
3851 case SMB_FILE_ALIGNMENT_INFORMATION:
3852 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3853 SIVAL(pdata,0,0); /* No alignment needed. */
3859 * NT4 server just returns "invalid query" to this - if we try to answer
3860 * it then NTws gets a BSOD! (tridge).
3861 * W2K seems to want this. JRA.
3863 case SMB_QUERY_FILE_STREAM_INFO:
3865 case SMB_FILE_STREAM_INFORMATION:
3866 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3870 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3871 SIVAL(pdata,0,0); /* ??? */
3872 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3873 SOFF_T(pdata,8,file_size);
3874 SOFF_T(pdata,16,allocation_size);
3875 data_size = 24 + byte_len;
3879 case SMB_QUERY_COMPRESSION_INFO:
3880 case SMB_FILE_COMPRESSION_INFORMATION:
3881 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3882 SOFF_T(pdata,0,file_size);
3883 SIVAL(pdata,8,0); /* ??? */
3884 SIVAL(pdata,12,0); /* ??? */
3888 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3889 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3890 put_long_date_timespec(pdata,create_time_ts);
3891 put_long_date_timespec(pdata+8,atime_ts);
3892 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3893 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3894 SOFF_T(pdata,32,allocation_size);
3895 SOFF_T(pdata,40,file_size);
3896 SIVAL(pdata,48,mode);
3897 SIVAL(pdata,52,0); /* ??? */
3901 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3902 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3903 SIVAL(pdata,0,mode);
3909 * CIFS UNIX Extensions.
3912 case SMB_QUERY_FILE_UNIX_BASIC:
3914 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3915 data_size = PTR_DIFF(pdata,(*ppdata));
3919 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3921 for (i=0; i<100; i++)
3922 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3928 case SMB_QUERY_FILE_UNIX_INFO2:
3930 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3931 data_size = PTR_DIFF(pdata,(*ppdata));
3935 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3937 for (i=0; i<100; i++)
3938 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3944 case SMB_QUERY_FILE_UNIX_LINK:
3948 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3950 if(!S_ISLNK(sbuf.st_mode))
3951 return(UNIXERROR(ERRSRV,ERRbadlink));
3953 return(UNIXERROR(ERRDOS,ERRbadlink));
3955 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3957 return(UNIXERROR(ERRDOS,ERRnoaccess));
3959 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3961 data_size = PTR_DIFF(pdata,(*ppdata));
3966 #if defined(HAVE_POSIX_ACLS)
3967 case SMB_QUERY_POSIX_ACL:
3969 SMB_ACL_T file_acl = NULL;
3970 SMB_ACL_T def_acl = NULL;
3971 uint16 num_file_acls = 0;
3972 uint16 num_def_acls = 0;
3974 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3975 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3977 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3980 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3981 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3983 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3986 if (S_ISDIR(sbuf.st_mode)) {
3987 if (fsp && fsp->is_directory) {
3988 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3990 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3992 def_acl = free_empty_sys_acl(conn, def_acl);
3995 num_file_acls = count_acl_entries(conn, file_acl);
3996 num_def_acls = count_acl_entries(conn, def_acl);
3998 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3999 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4001 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4002 SMB_POSIX_ACL_HEADER_SIZE) ));
4004 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4007 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4009 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
4012 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4013 SSVAL(pdata,2,num_file_acls);
4014 SSVAL(pdata,4,num_def_acls);
4015 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4017 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4020 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4022 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4024 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_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);
4035 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4038 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4040 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4046 case SMB_QUERY_POSIX_LOCK:
4048 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4050 SMB_BIG_UINT offset;
4052 enum brl_type lock_type;
4054 if (total_data != POSIX_LOCK_DATA_SIZE) {
4055 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4058 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4059 case POSIX_LOCK_TYPE_READ:
4060 lock_type = READ_LOCK;
4062 case POSIX_LOCK_TYPE_WRITE:
4063 lock_type = WRITE_LOCK;
4065 case POSIX_LOCK_TYPE_UNLOCK:
4067 /* There's no point in asking for an unlock... */
4068 talloc_destroy(data_ctx);
4069 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4072 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4073 #if defined(HAVE_LONGLONG)
4074 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4075 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4076 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4077 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4078 #else /* HAVE_LONGLONG */
4079 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4080 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4081 #endif /* HAVE_LONGLONG */
4083 status = query_lock(fsp,
4090 if (ERROR_WAS_LOCK_DENIED(status)) {
4091 /* Here we need to report who has it locked... */
4092 data_size = POSIX_LOCK_DATA_SIZE;
4094 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4095 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4096 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4097 #if defined(HAVE_LONGLONG)
4098 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4099 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4100 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4101 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4102 #else /* HAVE_LONGLONG */
4103 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4104 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4105 #endif /* HAVE_LONGLONG */
4107 } else if (NT_STATUS_IS_OK(status)) {
4108 /* For success we just return a copy of what we sent
4109 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4110 data_size = POSIX_LOCK_DATA_SIZE;
4111 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4112 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4114 return ERROR_NT(status);
4120 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4123 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
4128 /****************************************************************************
4129 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4131 ****************************************************************************/
4133 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4135 SMB_STRUCT_STAT sbuf1, sbuf2;
4136 pstring last_component_oldname;
4137 pstring last_component_newname;
4138 NTSTATUS status = NT_STATUS_OK;
4143 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4144 if (!NT_STATUS_IS_OK(status)) {
4148 status = check_name(conn, oldname);
4149 if (!NT_STATUS_IS_OK(status)) {
4153 /* source must already exist. */
4154 if (!VALID_STAT(sbuf1)) {
4155 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4158 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4159 if (!NT_STATUS_IS_OK(status)) {
4163 status = check_name(conn, newname);
4164 if (!NT_STATUS_IS_OK(status)) {
4168 /* Disallow if newname already exists. */
4169 if (VALID_STAT(sbuf2)) {
4170 return NT_STATUS_OBJECT_NAME_COLLISION;
4173 /* No links from a directory. */
4174 if (S_ISDIR(sbuf1.st_mode)) {
4175 return NT_STATUS_FILE_IS_A_DIRECTORY;
4178 /* Ensure this is within the share. */
4179 status = check_reduced_name(conn, oldname);
4180 if (!NT_STATUS_IS_OK(status)) {
4184 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4186 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4187 status = map_nt_error_from_unix(errno);
4188 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4189 nt_errstr(status), newname, oldname));
4195 /****************************************************************************
4196 Deal with setting the time from any of the setfilepathinfo functions.
4197 ****************************************************************************/
4199 static NTSTATUS smb_set_file_time(connection_struct *conn,
4202 const SMB_STRUCT_STAT *psbuf,
4203 struct timespec ts[2])
4206 FILE_NOTIFY_CHANGE_LAST_ACCESS
4207 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4210 if (!VALID_STAT(*psbuf)) {
4211 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4214 /* get some defaults (no modifications) if any info is zero or -1. */
4215 if (null_timespec(ts[0])) {
4216 ts[0] = get_atimespec(psbuf);
4217 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4220 if (null_timespec(ts[1])) {
4221 ts[1] = get_mtimespec(psbuf);
4222 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4225 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4226 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4229 * Try and set the times of this file if
4230 * they are different from the current values.
4234 struct timespec mts = get_mtimespec(psbuf);
4235 struct timespec ats = get_atimespec(psbuf);
4236 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4237 return NT_STATUS_OK;
4243 * This was a setfileinfo on an open file.
4244 * NT does this a lot. We also need to
4245 * set the time here, as it can be read by
4246 * FindFirst/FindNext and with the patch for bug #2045
4247 * in smbd/fileio.c it ensures that this timestamp is
4248 * kept sticky even after a write. We save the request
4249 * away and will set it on file close and after a write. JRA.
4252 if (!null_timespec(ts[1])) {
4253 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4254 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4255 fsp_set_pending_modtime(fsp, ts[1]);
4259 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4261 if(file_ntimes(conn, fname, ts)!=0) {
4262 return map_nt_error_from_unix(errno);
4265 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4267 return NT_STATUS_OK;
4270 /****************************************************************************
4271 Deal with setting the dosmode from any of the setfilepathinfo functions.
4272 ****************************************************************************/
4274 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4276 SMB_STRUCT_STAT *psbuf,
4279 if (!VALID_STAT(*psbuf)) {
4280 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4284 if (S_ISDIR(psbuf->st_mode)) {
4291 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4293 /* check the mode isn't different, before changing it */
4294 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4296 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4297 fname, (unsigned int)dosmode ));
4299 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4300 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4301 fname, strerror(errno)));
4302 return map_nt_error_from_unix(errno);
4305 return NT_STATUS_OK;
4308 /****************************************************************************
4309 Deal with setting the size from any of the setfilepathinfo functions.
4310 ****************************************************************************/
4312 static NTSTATUS smb_set_file_size(connection_struct *conn,
4313 struct smb_request *req,
4316 SMB_STRUCT_STAT *psbuf,
4319 NTSTATUS status = NT_STATUS_OK;
4320 files_struct *new_fsp = NULL;
4322 if (!VALID_STAT(*psbuf)) {
4323 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4326 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4328 if (size == get_file_size(*psbuf)) {
4329 return NT_STATUS_OK;
4332 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4333 fname, (double)size ));
4335 if (fsp && fsp->fh->fd != -1) {
4336 /* Handle based call. */
4337 if (vfs_set_filelen(fsp, size) == -1) {
4338 return map_nt_error_from_unix(errno);
4340 return NT_STATUS_OK;
4343 status = open_file_ntcreate(conn, req, fname, psbuf,
4345 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4348 FILE_ATTRIBUTE_NORMAL,
4349 FORCE_OPLOCK_BREAK_TO_NONE,
4352 if (!NT_STATUS_IS_OK(status)) {
4353 /* NB. We check for open_was_deferred in the caller. */
4357 if (vfs_set_filelen(new_fsp, size) == -1) {
4358 status = map_nt_error_from_unix(errno);
4359 close_file(new_fsp,NORMAL_CLOSE);
4363 close_file(new_fsp,NORMAL_CLOSE);
4364 return NT_STATUS_OK;
4367 /****************************************************************************
4368 Deal with SMB_INFO_SET_EA.
4369 ****************************************************************************/
4371 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4377 struct ea_list *ea_list = NULL;
4378 TALLOC_CTX *ctx = NULL;
4379 NTSTATUS status = NT_STATUS_OK;
4381 if (total_data < 10) {
4383 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4384 length. They seem to have no effect. Bug #3212. JRA */
4386 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4387 /* We're done. We only get EA info in this call. */
4388 return NT_STATUS_OK;
4391 return NT_STATUS_INVALID_PARAMETER;
4394 if (IVAL(pdata,0) > total_data) {
4395 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4396 IVAL(pdata,0), (unsigned int)total_data));
4397 return NT_STATUS_INVALID_PARAMETER;
4400 ctx = talloc_init("SMB_INFO_SET_EA");
4402 return NT_STATUS_NO_MEMORY;
4404 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4406 talloc_destroy(ctx);
4407 return NT_STATUS_INVALID_PARAMETER;
4409 status = set_ea(conn, fsp, fname, ea_list);
4410 talloc_destroy(ctx);
4415 /****************************************************************************
4416 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4417 ****************************************************************************/
4419 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4424 SMB_STRUCT_STAT *psbuf)
4426 NTSTATUS status = NT_STATUS_OK;
4427 BOOL delete_on_close;
4430 if (total_data < 1) {
4431 return NT_STATUS_INVALID_PARAMETER;
4435 return NT_STATUS_INVALID_HANDLE;
4438 delete_on_close = (CVAL(pdata,0) ? True : False);
4439 dosmode = dos_mode(conn, fname, psbuf);
4441 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4442 "delete_on_close = %u\n",
4444 (unsigned int)dosmode,
4445 (unsigned int)delete_on_close ));
4447 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4449 if (!NT_STATUS_IS_OK(status)) {
4453 /* The set is across all open files on this dev/inode pair. */
4454 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4455 return NT_STATUS_ACCESS_DENIED;
4457 return NT_STATUS_OK;
4460 /****************************************************************************
4461 Deal with SMB_FILE_POSITION_INFORMATION.
4462 ****************************************************************************/
4464 static NTSTATUS smb_file_position_information(connection_struct *conn,
4469 SMB_BIG_UINT position_information;
4471 if (total_data < 8) {
4472 return NT_STATUS_INVALID_PARAMETER;
4476 /* Ignore on pathname based set. */
4477 return NT_STATUS_OK;
4480 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4481 #ifdef LARGE_SMB_OFF_T
4482 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4483 #else /* LARGE_SMB_OFF_T */
4484 if (IVAL(pdata,4) != 0) {
4485 /* more than 32 bits? */
4486 return NT_STATUS_INVALID_PARAMETER;
4488 #endif /* LARGE_SMB_OFF_T */
4490 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4491 fsp->fsp_name, (double)position_information ));
4492 fsp->fh->position_information = position_information;
4493 return NT_STATUS_OK;
4496 /****************************************************************************
4497 Deal with SMB_FILE_MODE_INFORMATION.
4498 ****************************************************************************/
4500 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4506 if (total_data < 4) {
4507 return NT_STATUS_INVALID_PARAMETER;
4509 mode = IVAL(pdata,0);
4510 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4511 return NT_STATUS_INVALID_PARAMETER;
4513 return NT_STATUS_OK;
4516 /****************************************************************************
4517 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4518 ****************************************************************************/
4520 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4526 pstring link_target;
4527 const char *newname = fname;
4528 NTSTATUS status = NT_STATUS_OK;
4530 /* Set a symbolic link. */
4531 /* Don't allow this if follow links is false. */
4533 if (total_data == 0) {
4534 return NT_STATUS_INVALID_PARAMETER;
4537 if (!lp_symlinks(SNUM(conn))) {
4538 return NT_STATUS_ACCESS_DENIED;
4541 srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), link_target, pdata,
4542 sizeof(link_target), total_data, STR_TERMINATE);
4544 /* !widelinks forces the target path to be within the share. */
4545 /* This means we can interpret the target as a pathname. */
4546 if (!lp_widelinks(SNUM(conn))) {
4548 char *last_dirp = NULL;
4550 if (*link_target == '/') {
4551 /* No absolute paths allowed. */
4552 return NT_STATUS_ACCESS_DENIED;
4554 pstrcpy(rel_name, newname);
4555 last_dirp = strrchr_m(rel_name, '/');
4557 last_dirp[1] = '\0';
4559 pstrcpy(rel_name, "./");
4561 pstrcat(rel_name, link_target);
4563 status = check_name(conn, rel_name);
4564 if (!NT_STATUS_IS_OK(status)) {
4569 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4570 newname, link_target ));
4572 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4573 return map_nt_error_from_unix(errno);
4576 return NT_STATUS_OK;
4579 /****************************************************************************
4580 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4581 ****************************************************************************/
4583 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4591 NTSTATUS status = NT_STATUS_OK;
4593 /* Set a hard link. */
4594 if (total_data == 0) {
4595 return NT_STATUS_INVALID_PARAMETER;
4598 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), oldname, pdata,
4599 sizeof(oldname), total_data, STR_TERMINATE, &status);
4600 if (!NT_STATUS_IS_OK(status)) {
4604 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4605 if (!NT_STATUS_IS_OK(status)) {
4609 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4612 return hardlink_internals(conn, oldname, fname);
4615 /****************************************************************************
4616 Deal with SMB_FILE_RENAME_INFORMATION.
4617 ****************************************************************************/
4619 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4620 struct smb_request *req,
4633 BOOL dest_has_wcard = False;
4634 NTSTATUS status = NT_STATUS_OK;
4637 if (total_data < 13) {
4638 return NT_STATUS_INVALID_PARAMETER;
4641 overwrite = (CVAL(pdata,0) ? True : False);
4642 root_fid = IVAL(pdata,4);
4643 len = IVAL(pdata,8);
4645 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4646 return NT_STATUS_INVALID_PARAMETER;
4649 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, &pdata[12],
4650 sizeof(newname), len, 0, &status,
4652 if (!NT_STATUS_IS_OK(status)) {
4656 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4657 if (!NT_STATUS_IS_OK(status)) {
4661 /* Check the new name has no '/' characters. */
4662 if (strchr_m(newname, '/')) {
4663 return NT_STATUS_NOT_SUPPORTED;
4666 /* Create the base directory. */
4667 pstrcpy(base_name, fname);
4668 p = strrchr_m(base_name, '/');
4672 pstrcpy(base_name, "./");
4674 /* Append the new name. */
4675 pstrcat(base_name, newname);
4678 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4679 fsp->fnum, fsp->fsp_name, base_name ));
4680 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4682 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4684 status = rename_internals(conn, req, fname, base_name, 0,
4685 overwrite, False, dest_has_wcard);
4691 /****************************************************************************
4692 Deal with SMB_SET_POSIX_ACL.
4693 ****************************************************************************/
4695 #if defined(HAVE_POSIX_ACLS)
4696 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4701 SMB_STRUCT_STAT *psbuf)
4703 uint16 posix_acl_version;
4704 uint16 num_file_acls;
4705 uint16 num_def_acls;
4706 BOOL valid_file_acls = True;
4707 BOOL valid_def_acls = True;
4709 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4710 return NT_STATUS_INVALID_PARAMETER;
4712 posix_acl_version = SVAL(pdata,0);
4713 num_file_acls = SVAL(pdata,2);
4714 num_def_acls = SVAL(pdata,4);
4716 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4717 valid_file_acls = False;
4721 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4722 valid_def_acls = False;
4726 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4727 return NT_STATUS_INVALID_PARAMETER;
4730 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4731 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4732 return NT_STATUS_INVALID_PARAMETER;
4735 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4736 fname ? fname : fsp->fsp_name,
4737 (unsigned int)num_file_acls,
4738 (unsigned int)num_def_acls));
4740 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4741 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4742 return map_nt_error_from_unix(errno);
4745 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4746 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4747 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4748 return map_nt_error_from_unix(errno);
4750 return NT_STATUS_OK;
4754 /****************************************************************************
4755 Deal with SMB_SET_POSIX_LOCK.
4756 ****************************************************************************/
4758 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4766 SMB_BIG_UINT offset;
4768 BOOL blocking_lock = False;
4769 enum brl_type lock_type;
4770 NTSTATUS status = NT_STATUS_OK;
4772 if (fsp == NULL || fsp->fh->fd == -1) {
4773 return NT_STATUS_INVALID_HANDLE;
4776 if (total_data != POSIX_LOCK_DATA_SIZE) {
4777 return NT_STATUS_INVALID_PARAMETER;
4780 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4781 case POSIX_LOCK_TYPE_READ:
4782 lock_type = READ_LOCK;
4784 case POSIX_LOCK_TYPE_WRITE:
4785 /* Return the right POSIX-mappable error code for files opened read-only. */
4786 if (!fsp->can_write) {
4787 return NT_STATUS_INVALID_HANDLE;
4789 lock_type = WRITE_LOCK;
4791 case POSIX_LOCK_TYPE_UNLOCK:
4792 lock_type = UNLOCK_LOCK;
4795 return NT_STATUS_INVALID_PARAMETER;
4798 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4799 blocking_lock = False;
4800 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4801 blocking_lock = True;
4803 return NT_STATUS_INVALID_PARAMETER;
4806 if (!lp_blocking_locks(SNUM(conn))) {
4807 blocking_lock = False;
4810 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4811 #if defined(HAVE_LONGLONG)
4812 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4813 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4814 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4815 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4816 #else /* HAVE_LONGLONG */
4817 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4818 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4819 #endif /* HAVE_LONGLONG */
4821 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4822 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4824 (unsigned int)lock_type,
4825 (unsigned int)lock_pid,
4829 if (lock_type == UNLOCK_LOCK) {
4830 status = do_unlock(smbd_messaging_context(),
4837 uint32 block_smbpid;
4839 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
4850 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4852 * A blocking lock was requested. Package up
4853 * this smb into a queued request and push it
4854 * onto the blocking lock queue.
4856 if(push_blocking_lock_request(br_lck,
4859 -1, /* infinite timeout. */
4867 TALLOC_FREE(br_lck);
4871 TALLOC_FREE(br_lck);
4877 /****************************************************************************
4878 Deal with SMB_INFO_STANDARD.
4879 ****************************************************************************/
4881 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4886 const SMB_STRUCT_STAT *psbuf)
4888 struct timespec ts[2];
4890 if (total_data < 12) {
4891 return NT_STATUS_INVALID_PARAMETER;
4895 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4897 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4899 DEBUG(10,("smb_set_info_standard: file %s\n",
4900 fname ? fname : fsp->fsp_name ));
4902 return smb_set_file_time(conn,
4909 /****************************************************************************
4910 Deal with SMB_SET_FILE_BASIC_INFO.
4911 ****************************************************************************/
4913 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4918 SMB_STRUCT_STAT *psbuf)
4920 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4921 struct timespec write_time;
4922 struct timespec changed_time;
4924 struct timespec ts[2];
4925 NTSTATUS status = NT_STATUS_OK;
4927 if (total_data < 36) {
4928 return NT_STATUS_INVALID_PARAMETER;
4931 /* Set the attributes */
4932 dosmode = IVAL(pdata,32);
4933 status = smb_set_file_dosmode(conn,
4937 if (!NT_STATUS_IS_OK(status)) {
4941 /* Ignore create time at offset pdata. */
4944 ts[0] = interpret_long_date(pdata+8);
4946 write_time = interpret_long_date(pdata+16);
4947 changed_time = interpret_long_date(pdata+24);
4950 ts[1] = timespec_min(&write_time, &changed_time);
4952 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4956 /* Prefer a defined time to an undefined one. */
4957 if (null_timespec(ts[1])) {
4958 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4961 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4962 fname ? fname : fsp->fsp_name ));
4964 return smb_set_file_time(conn,
4971 /****************************************************************************
4972 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4973 ****************************************************************************/
4975 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4976 struct smb_request *req,
4981 SMB_STRUCT_STAT *psbuf)
4983 SMB_BIG_UINT allocation_size = 0;
4984 NTSTATUS status = NT_STATUS_OK;
4985 files_struct *new_fsp = NULL;
4987 if (!VALID_STAT(*psbuf)) {
4988 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4991 if (total_data < 8) {
4992 return NT_STATUS_INVALID_PARAMETER;
4995 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4996 #ifdef LARGE_SMB_OFF_T
4997 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4998 #else /* LARGE_SMB_OFF_T */
4999 if (IVAL(pdata,4) != 0) {
5000 /* more than 32 bits? */
5001 return NT_STATUS_INVALID_PARAMETER;
5003 #endif /* LARGE_SMB_OFF_T */
5005 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5006 fname, (double)allocation_size ));
5008 if (allocation_size) {
5009 allocation_size = smb_roundup(conn, allocation_size);
5012 if(allocation_size == get_file_size(*psbuf)) {
5013 return NT_STATUS_OK;
5016 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5017 fname, (double)allocation_size ));
5019 if (fsp && fsp->fh->fd != -1) {
5020 /* Open file handle. */
5021 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5022 return map_nt_error_from_unix(errno);
5024 return NT_STATUS_OK;
5027 /* Pathname or stat or directory file. */
5029 status = open_file_ntcreate(conn, req, fname, psbuf,
5031 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5034 FILE_ATTRIBUTE_NORMAL,
5035 FORCE_OPLOCK_BREAK_TO_NONE,
5038 if (!NT_STATUS_IS_OK(status)) {
5039 /* NB. We check for open_was_deferred in the caller. */
5042 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5043 status = map_nt_error_from_unix(errno);
5044 close_file(new_fsp,NORMAL_CLOSE);
5048 close_file(new_fsp,NORMAL_CLOSE);
5049 return NT_STATUS_OK;
5052 /****************************************************************************
5053 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5054 ****************************************************************************/
5056 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5057 struct smb_request *req,
5062 SMB_STRUCT_STAT *psbuf)
5066 if (total_data < 8) {
5067 return NT_STATUS_INVALID_PARAMETER;
5070 size = IVAL(pdata,0);
5071 #ifdef LARGE_SMB_OFF_T
5072 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5073 #else /* LARGE_SMB_OFF_T */
5074 if (IVAL(pdata,4) != 0) {
5075 /* more than 32 bits? */
5076 return NT_STATUS_INVALID_PARAMETER;
5078 #endif /* LARGE_SMB_OFF_T */
5079 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5080 "file %s to %.0f\n", fname, (double)size ));
5082 return smb_set_file_size(conn, req,
5089 /****************************************************************************
5090 Allow a UNIX info mknod.
5091 ****************************************************************************/
5093 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5097 SMB_STRUCT_STAT *psbuf)
5099 uint32 file_type = IVAL(pdata,56);
5100 #if defined(HAVE_MAKEDEV)
5101 uint32 dev_major = IVAL(pdata,60);
5102 uint32 dev_minor = IVAL(pdata,68);
5104 SMB_DEV_T dev = (SMB_DEV_T)0;
5105 uint32 raw_unixmode = IVAL(pdata,84);
5109 if (total_data < 100) {
5110 return NT_STATUS_INVALID_PARAMETER;
5113 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5114 if (!NT_STATUS_IS_OK(status)) {
5118 #if defined(HAVE_MAKEDEV)
5119 dev = makedev(dev_major, dev_minor);
5122 switch (file_type) {
5123 #if defined(S_IFIFO)
5124 case UNIX_TYPE_FIFO:
5125 unixmode |= S_IFIFO;
5128 #if defined(S_IFSOCK)
5129 case UNIX_TYPE_SOCKET:
5130 unixmode |= S_IFSOCK;
5133 #if defined(S_IFCHR)
5134 case UNIX_TYPE_CHARDEV:
5135 unixmode |= S_IFCHR;
5138 #if defined(S_IFBLK)
5139 case UNIX_TYPE_BLKDEV:
5140 unixmode |= S_IFBLK;
5144 return NT_STATUS_INVALID_PARAMETER;
5147 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5148 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5150 /* Ok - do the mknod. */
5151 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5152 return map_nt_error_from_unix(errno);
5155 /* If any of the other "set" calls fail we
5156 * don't want to end up with a half-constructed mknod.
5159 if (lp_inherit_perms(SNUM(conn))) {
5161 conn, parent_dirname(fname),
5165 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5166 status = map_nt_error_from_unix(errno);
5167 SMB_VFS_UNLINK(conn,fname);
5170 return NT_STATUS_OK;
5173 /****************************************************************************
5174 Deal with SMB_SET_FILE_UNIX_BASIC.
5175 ****************************************************************************/
5177 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5178 struct smb_request *req,
5183 SMB_STRUCT_STAT *psbuf)
5185 struct timespec ts[2];
5186 uint32 raw_unixmode;
5189 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5190 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5191 NTSTATUS status = NT_STATUS_OK;
5192 BOOL delete_on_fail = False;
5193 enum perm_type ptype;
5195 if (total_data < 100) {
5196 return NT_STATUS_INVALID_PARAMETER;
5199 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5200 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5201 size=IVAL(pdata,0); /* first 8 Bytes are size */
5202 #ifdef LARGE_SMB_OFF_T
5203 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5204 #else /* LARGE_SMB_OFF_T */
5205 if (IVAL(pdata,4) != 0) {
5206 /* more than 32 bits? */
5207 return NT_STATUS_INVALID_PARAMETER;
5209 #endif /* LARGE_SMB_OFF_T */
5212 ts[0] = interpret_long_date(pdata+24); /* access_time */
5213 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5214 set_owner = (uid_t)IVAL(pdata,40);
5215 set_grp = (gid_t)IVAL(pdata,48);
5216 raw_unixmode = IVAL(pdata,84);
5218 if (VALID_STAT(*psbuf)) {
5219 if (S_ISDIR(psbuf->st_mode)) {
5220 ptype = PERM_EXISTING_DIR;
5222 ptype = PERM_EXISTING_FILE;
5225 ptype = PERM_NEW_FILE;
5228 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5229 if (!NT_STATUS_IS_OK(status)) {
5233 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5234 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5235 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5237 if (!VALID_STAT(*psbuf)) {
5239 * The only valid use of this is to create character and block
5240 * devices, and named pipes. This is deprecated (IMHO) and
5241 * a new info level should be used for mknod. JRA.
5244 status = smb_unix_mknod(conn,
5249 if (!NT_STATUS_IS_OK(status)) {
5253 /* Ensure we don't try and change anything else. */
5254 raw_unixmode = SMB_MODE_NO_CHANGE;
5255 size = get_file_size(*psbuf);
5256 ts[0] = get_atimespec(psbuf);
5257 ts[1] = get_mtimespec(psbuf);
5259 * We continue here as we might want to change the
5262 delete_on_fail = True;
5266 /* Horrible backwards compatibility hack as an old server bug
5267 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5271 size = get_file_size(*psbuf);
5276 * Deal with the UNIX specific mode set.
5279 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5280 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5281 (unsigned int)unixmode, fname ));
5282 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5283 return map_nt_error_from_unix(errno);
5288 * Deal with the UNIX specific uid set.
5291 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5294 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5295 (unsigned int)set_owner, fname ));
5297 if (S_ISLNK(psbuf->st_mode)) {
5298 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5300 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5304 status = map_nt_error_from_unix(errno);
5305 if (delete_on_fail) {
5306 SMB_VFS_UNLINK(conn,fname);
5313 * Deal with the UNIX specific gid set.
5316 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5317 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5318 (unsigned int)set_owner, fname ));
5319 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5320 status = map_nt_error_from_unix(errno);
5321 if (delete_on_fail) {
5322 SMB_VFS_UNLINK(conn,fname);
5328 /* Deal with any size changes. */
5330 status = smb_set_file_size(conn, req,
5335 if (!NT_STATUS_IS_OK(status)) {
5339 /* Deal with any time changes. */
5341 return smb_set_file_time(conn,
5348 /****************************************************************************
5349 Deal with SMB_SET_FILE_UNIX_INFO2.
5350 ****************************************************************************/
5352 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5353 struct smb_request *req,
5358 SMB_STRUCT_STAT *psbuf)
5364 if (total_data < 116) {
5365 return NT_STATUS_INVALID_PARAMETER;
5368 /* Start by setting all the fields that are common between UNIX_BASIC
5371 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5373 if (!NT_STATUS_IS_OK(status)) {
5377 smb_fflags = IVAL(pdata, 108);
5378 smb_fmask = IVAL(pdata, 112);
5380 /* NB: We should only attempt to alter the file flags if the client
5381 * sends a non-zero mask.
5383 if (smb_fmask != 0) {
5384 int stat_fflags = 0;
5386 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5388 /* Client asked to alter a flag we don't understand. */
5389 return NT_STATUS_INVALID_PARAMETER;
5392 if (fsp && fsp->fh->fd != -1) {
5393 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5394 return NT_STATUS_NOT_SUPPORTED;
5396 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5397 return map_nt_error_from_unix(errno);
5402 /* XXX: need to add support for changing the create_time here. You
5403 * can do this for paths on Darwin with setattrlist(2). The right way
5404 * to hook this up is probably by extending the VFS utimes interface.
5407 return NT_STATUS_OK;
5410 /****************************************************************************
5411 Create a directory with POSIX semantics.
5412 ****************************************************************************/
5414 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5415 struct smb_request *req,
5419 SMB_STRUCT_STAT *psbuf,
5420 int *pdata_return_size)
5422 NTSTATUS status = NT_STATUS_OK;
5423 uint32 raw_unixmode = 0;
5424 uint32 mod_unixmode = 0;
5425 mode_t unixmode = (mode_t)0;
5426 files_struct *fsp = NULL;
5427 uint16 info_level_return = 0;
5429 char *pdata = *ppdata;
5431 if (total_data < 18) {
5432 return NT_STATUS_INVALID_PARAMETER;
5435 raw_unixmode = IVAL(pdata,8);
5436 /* Next 4 bytes are not yet defined. */
5438 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5439 if (!NT_STATUS_IS_OK(status)) {
5443 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5445 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5446 fname, (unsigned int)unixmode ));
5448 status = open_directory(conn, req,
5451 FILE_READ_ATTRIBUTES, /* Just a stat open */
5452 FILE_SHARE_NONE, /* Ignored for stat opens */
5459 if (NT_STATUS_IS_OK(status)) {
5460 close_file(fsp, NORMAL_CLOSE);
5463 info_level_return = SVAL(pdata,16);
5465 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5466 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5467 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5468 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5470 *pdata_return_size = 12;
5473 /* Realloc the data size */
5474 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5475 if (*ppdata == NULL) {
5476 *pdata_return_size = 0;
5477 return NT_STATUS_NO_MEMORY;
5481 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5482 SSVAL(pdata,2,0); /* No fnum. */
5483 SIVAL(pdata,4,info); /* Was directory created. */
5485 switch (info_level_return) {
5486 case SMB_QUERY_FILE_UNIX_BASIC:
5487 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5488 SSVAL(pdata,10,0); /* Padding. */
5489 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5491 case SMB_QUERY_FILE_UNIX_INFO2:
5492 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5493 SSVAL(pdata,10,0); /* Padding. */
5494 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5497 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5498 SSVAL(pdata,10,0); /* Padding. */
5505 /****************************************************************************
5506 Open/Create a file with POSIX semantics.
5507 ****************************************************************************/
5509 static NTSTATUS smb_posix_open(connection_struct *conn,
5510 struct smb_request *req,
5514 SMB_STRUCT_STAT *psbuf,
5515 int *pdata_return_size)
5517 BOOL extended_oplock_granted = False;
5518 char *pdata = *ppdata;
5520 uint32 wire_open_mode = 0;
5521 uint32 raw_unixmode = 0;
5522 uint32 mod_unixmode = 0;
5523 uint32 create_disp = 0;
5524 uint32 access_mask = 0;
5525 uint32 create_options = 0;
5526 NTSTATUS status = NT_STATUS_OK;
5527 mode_t unixmode = (mode_t)0;
5528 files_struct *fsp = NULL;
5529 int oplock_request = 0;
5531 uint16 info_level_return = 0;
5533 if (total_data < 18) {
5534 return NT_STATUS_INVALID_PARAMETER;
5537 flags = IVAL(pdata,0);
5538 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5539 if (oplock_request) {
5540 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5543 wire_open_mode = IVAL(pdata,4);
5545 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5546 return smb_posix_mkdir(conn, req,
5554 switch (wire_open_mode & SMB_ACCMODE) {
5556 access_mask = FILE_READ_DATA;
5559 access_mask = FILE_WRITE_DATA;
5562 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5565 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5566 (unsigned int)wire_open_mode ));
5567 return NT_STATUS_INVALID_PARAMETER;
5570 wire_open_mode &= ~SMB_ACCMODE;
5572 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5573 create_disp = FILE_CREATE;
5574 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5575 create_disp = FILE_OVERWRITE_IF;
5576 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5577 create_disp = FILE_OPEN_IF;
5579 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5580 (unsigned int)wire_open_mode ));
5581 return NT_STATUS_INVALID_PARAMETER;
5584 raw_unixmode = IVAL(pdata,8);
5585 /* Next 4 bytes are not yet defined. */
5587 status = unix_perms_from_wire(conn,
5590 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5593 if (!NT_STATUS_IS_OK(status)) {
5597 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5599 if (wire_open_mode & SMB_O_SYNC) {
5600 create_options |= FILE_WRITE_THROUGH;
5602 if (wire_open_mode & SMB_O_APPEND) {
5603 access_mask |= FILE_APPEND_DATA;
5605 if (wire_open_mode & SMB_O_DIRECT) {
5606 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5609 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5611 (unsigned int)wire_open_mode,
5612 (unsigned int)unixmode ));
5614 status = open_file_ntcreate(conn, req,
5618 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5620 0, /* no create options yet. */
5626 if (!NT_STATUS_IS_OK(status)) {
5630 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5631 extended_oplock_granted = True;
5634 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5635 extended_oplock_granted = True;
5638 info_level_return = SVAL(pdata,16);
5640 /* Allocate the correct return size. */
5642 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5643 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5644 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5645 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5647 *pdata_return_size = 12;
5650 /* Realloc the data size */
5651 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5652 if (*ppdata == NULL) {
5653 close_file(fsp,ERROR_CLOSE);
5654 *pdata_return_size = 0;
5655 return NT_STATUS_NO_MEMORY;
5659 if (extended_oplock_granted) {
5660 if (flags & REQUEST_BATCH_OPLOCK) {
5661 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5663 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5665 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5666 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5668 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5671 SSVAL(pdata,2,fsp->fnum);
5672 SIVAL(pdata,4,info); /* Was file created etc. */
5674 switch (info_level_return) {
5675 case SMB_QUERY_FILE_UNIX_BASIC:
5676 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5677 SSVAL(pdata,10,0); /* padding. */
5678 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5680 case SMB_QUERY_FILE_UNIX_INFO2:
5681 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5682 SSVAL(pdata,10,0); /* padding. */
5683 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5686 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5687 SSVAL(pdata,10,0); /* padding. */
5690 return NT_STATUS_OK;
5693 /****************************************************************************
5694 Delete a file with POSIX semantics.
5695 ****************************************************************************/
5697 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5698 struct smb_request *req,
5702 SMB_STRUCT_STAT *psbuf)
5704 NTSTATUS status = NT_STATUS_OK;
5705 files_struct *fsp = NULL;
5709 if (total_data < 2) {
5710 return NT_STATUS_INVALID_PARAMETER;
5713 flags = SVAL(pdata,0);
5715 if (!VALID_STAT(*psbuf)) {
5716 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5719 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5720 !VALID_STAT_OF_DIR(*psbuf)) {
5721 return NT_STATUS_NOT_A_DIRECTORY;
5724 DEBUG(10,("smb_posix_unlink: %s %s\n",
5725 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5728 if (VALID_STAT_OF_DIR(*psbuf)) {
5729 status = open_directory(conn, req,
5733 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5735 FILE_DELETE_ON_CLOSE,
5736 FILE_FLAG_POSIX_SEMANTICS|0777,
5742 status = open_file_ntcreate(conn, req,
5746 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5749 FILE_FLAG_POSIX_SEMANTICS|0777,
5750 0, /* No oplock, but break existing ones. */
5754 * For file opens we must set the delete on close
5758 if (!NT_STATUS_IS_OK(status)) {
5762 status = smb_set_file_disposition_info(conn,
5770 if (!NT_STATUS_IS_OK(status)) {
5773 return close_file(fsp, NORMAL_CLOSE);
5776 /****************************************************************************
5777 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5778 ****************************************************************************/
5780 static int call_trans2setfilepathinfo(connection_struct *conn,
5781 struct smb_request *req,
5782 char *inbuf, char *outbuf, int length,
5784 unsigned int tran_call,
5785 char **pparams, int total_params, char **ppdata, int total_data,
5786 unsigned int max_data_bytes)
5788 char *params = *pparams;
5789 char *pdata = *ppdata;
5791 SMB_STRUCT_STAT sbuf;
5793 files_struct *fsp = NULL;
5794 NTSTATUS status = NT_STATUS_OK;
5795 int data_return_size = 0;
5798 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5803 if (tran_call == TRANSACT2_SETFILEINFO) {
5804 if (total_params < 4) {
5805 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5808 fsp = file_fsp(params,0);
5809 info_level = SVAL(params,2);
5811 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5813 * This is actually a SETFILEINFO on a directory
5814 * handle (returned from an NT SMB). NT5.0 seems
5815 * to do this call. JRA.
5817 pstrcpy(fname, fsp->fsp_name);
5818 if (INFO_LEVEL_IS_UNIX(info_level)) {
5819 /* Always do lstat for UNIX calls. */
5820 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
5821 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
5822 return UNIXERROR(ERRDOS,ERRbadpath);
5825 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5826 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5827 return UNIXERROR(ERRDOS,ERRbadpath);
5830 } else if (fsp && fsp->print_file) {
5832 * Doing a DELETE_ON_CLOSE should cancel a print job.
5834 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5835 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5837 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5840 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5843 return (UNIXERROR(ERRDOS,ERRbadpath));
5846 * Original code - this is an open file.
5848 CHECK_FSP(fsp,conn);
5850 pstrcpy(fname, fsp->fsp_name);
5852 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5853 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5854 return(UNIXERROR(ERRDOS,ERRbadfid));
5859 if (total_params < 7) {
5860 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5863 info_level = SVAL(params,0);
5864 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, ¶ms[6],
5865 sizeof(fname), total_params - 6, STR_TERMINATE,
5867 if (!NT_STATUS_IS_OK(status)) {
5868 return ERROR_NT(status);
5871 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5872 if (!NT_STATUS_IS_OK(status)) {
5873 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5874 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5876 return ERROR_NT(status);
5879 status = unix_convert(conn, fname, False, NULL, &sbuf);
5880 if (!NT_STATUS_IS_OK(status)) {
5881 return ERROR_NT(status);
5884 status = check_name(conn, fname);
5885 if (!NT_STATUS_IS_OK(status)) {
5886 return ERROR_NT(status);
5889 if (INFO_LEVEL_IS_UNIX(info_level)) {
5891 * For CIFS UNIX extensions the target name may not exist.
5894 /* Always do lstat for UNIX calls. */
5895 SMB_VFS_LSTAT(conn,fname,&sbuf);
5897 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
5898 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
5899 return UNIXERROR(ERRDOS,ERRbadpath);
5903 if (!CAN_WRITE(conn)) {
5904 return ERROR_DOS(ERRSRV,ERRaccess);
5907 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5908 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5911 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5912 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5914 /* Realloc the parameter size */
5915 *pparams = (char *)SMB_REALLOC(*pparams,2);
5916 if (*pparams == NULL) {
5917 return ERROR_NT(NT_STATUS_NO_MEMORY);
5923 if (fsp && !null_timespec(fsp->pending_modtime)) {
5924 /* the pending modtime overrides the current modtime */
5925 set_mtimespec(&sbuf, fsp->pending_modtime);
5928 switch (info_level) {
5930 case SMB_INFO_STANDARD:
5932 status = smb_set_info_standard(conn,
5941 case SMB_INFO_SET_EA:
5943 status = smb_info_set_ea(conn,
5951 case SMB_SET_FILE_BASIC_INFO:
5952 case SMB_FILE_BASIC_INFORMATION:
5954 status = smb_set_file_basic_info(conn,
5963 case SMB_FILE_ALLOCATION_INFORMATION:
5964 case SMB_SET_FILE_ALLOCATION_INFO:
5966 status = smb_set_file_allocation_info(conn, req,
5975 case SMB_FILE_END_OF_FILE_INFORMATION:
5976 case SMB_SET_FILE_END_OF_FILE_INFO:
5978 status = smb_set_file_end_of_file_info(conn, req,
5987 case SMB_FILE_DISPOSITION_INFORMATION:
5988 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5991 /* JRA - We used to just ignore this on a path ?
5992 * Shouldn't this be invalid level on a pathname
5995 if (tran_call != TRANSACT2_SETFILEINFO) {
5996 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5999 status = smb_set_file_disposition_info(conn,
6008 case SMB_FILE_POSITION_INFORMATION:
6010 status = smb_file_position_information(conn,
6017 /* From tridge Samba4 :
6018 * MODE_INFORMATION in setfileinfo (I have no
6019 * idea what "mode information" on a file is - it takes a value of 0,
6020 * 2, 4 or 6. What could it be?).
6023 case SMB_FILE_MODE_INFORMATION:
6025 status = smb_file_mode_information(conn,
6032 * CIFS UNIX extensions.
6035 case SMB_SET_FILE_UNIX_BASIC:
6037 status = smb_set_file_unix_basic(conn, req,
6046 case SMB_SET_FILE_UNIX_INFO2:
6048 status = smb_set_file_unix_info2(conn, req,
6057 case SMB_SET_FILE_UNIX_LINK:
6059 if (tran_call != TRANSACT2_SETPATHINFO) {
6060 /* We must have a pathname for this. */
6061 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6063 status = smb_set_file_unix_link(conn,
6071 case SMB_SET_FILE_UNIX_HLINK:
6073 if (tran_call != TRANSACT2_SETPATHINFO) {
6074 /* We must have a pathname for this. */
6075 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6077 status = smb_set_file_unix_hlink(conn,
6086 case SMB_FILE_RENAME_INFORMATION:
6088 status = smb_file_rename_information(conn, req,
6098 #if defined(HAVE_POSIX_ACLS)
6099 case SMB_SET_POSIX_ACL:
6101 status = smb_set_posix_acl(conn,
6111 case SMB_SET_POSIX_LOCK:
6113 if (tran_call != TRANSACT2_SETFILEINFO) {
6114 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6116 status = smb_set_posix_lock(conn,
6125 case SMB_POSIX_PATH_OPEN:
6127 if (tran_call != TRANSACT2_SETPATHINFO) {
6128 /* We must have a pathname for this. */
6129 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6132 status = smb_posix_open(conn, req,
6141 case SMB_POSIX_PATH_UNLINK:
6143 if (tran_call != TRANSACT2_SETPATHINFO) {
6144 /* We must have a pathname for this. */
6145 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6148 status = smb_posix_unlink(conn, req,
6157 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6161 if (!NT_STATUS_IS_OK(status)) {
6162 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6163 /* We have re-scheduled this call. */
6166 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6167 /* We have re-scheduled this call. */
6170 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6171 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6173 return ERROR_NT(status);
6177 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6182 /****************************************************************************
6183 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6184 ****************************************************************************/
6186 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6187 char **pparams, int total_params, char **ppdata, int total_data,
6188 unsigned int max_data_bytes)
6190 char *params = *pparams;
6191 char *pdata = *ppdata;
6193 SMB_STRUCT_STAT sbuf;
6194 NTSTATUS status = NT_STATUS_OK;
6195 struct ea_list *ea_list = NULL;
6197 if (!CAN_WRITE(conn))
6198 return ERROR_DOS(ERRSRV,ERRaccess);
6200 if (total_params < 5) {
6201 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6204 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory, ¶ms[4],
6205 sizeof(directory), total_params - 4, STR_TERMINATE,
6207 if (!NT_STATUS_IS_OK(status)) {
6208 return ERROR_NT(status);
6211 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6213 status = unix_convert(conn, directory, False, NULL, &sbuf);
6214 if (!NT_STATUS_IS_OK(status)) {
6215 return ERROR_NT(status);
6218 status = check_name(conn, directory);
6219 if (!NT_STATUS_IS_OK(status)) {
6220 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6221 return ERROR_NT(status);
6224 /* Any data in this call is an EA list. */
6225 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6226 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6230 * OS/2 workplace shell seems to send SET_EA requests of "null"
6231 * length (4 bytes containing IVAL 4).
6232 * They seem to have no effect. Bug #3212. JRA.
6235 if (total_data != 4) {
6236 if (total_data < 10) {
6237 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6240 if (IVAL(pdata,0) > total_data) {
6241 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6242 IVAL(pdata,0), (unsigned int)total_data));
6243 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6246 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6249 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6251 } else if (IVAL(pdata,0) != 4) {
6252 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6255 status = create_directory(conn, directory);
6257 if (!NT_STATUS_IS_OK(status)) {
6258 return ERROR_NT(status);
6261 /* Try and set any given EA. */
6263 status = set_ea(conn, NULL, directory, ea_list);
6264 if (!NT_STATUS_IS_OK(status)) {
6265 return ERROR_NT(status);
6269 /* Realloc the parameter and data sizes */
6270 *pparams = (char *)SMB_REALLOC(*pparams,2);
6271 if(*pparams == NULL) {
6272 return ERROR_NT(NT_STATUS_NO_MEMORY);
6278 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6283 /****************************************************************************
6284 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6285 We don't actually do this - we just send a null response.
6286 ****************************************************************************/
6288 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6289 char **pparams, int total_params, char **ppdata, int total_data,
6290 unsigned int max_data_bytes)
6292 static uint16 fnf_handle = 257;
6293 char *params = *pparams;
6296 if (total_params < 6) {
6297 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6300 info_level = SVAL(params,4);
6301 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6303 switch (info_level) {
6308 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6311 /* Realloc the parameter and data sizes */
6312 *pparams = (char *)SMB_REALLOC(*pparams,6);
6313 if (*pparams == NULL) {
6314 return ERROR_NT(NT_STATUS_NO_MEMORY);
6318 SSVAL(params,0,fnf_handle);
6319 SSVAL(params,2,0); /* No changes */
6320 SSVAL(params,4,0); /* No EA errors */
6327 send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6332 /****************************************************************************
6333 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6334 changes). Currently this does nothing.
6335 ****************************************************************************/
6337 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6338 char **pparams, int total_params, char **ppdata, int total_data,
6339 unsigned int max_data_bytes)
6341 char *params = *pparams;
6343 DEBUG(3,("call_trans2findnotifynext\n"));
6345 /* Realloc the parameter and data sizes */
6346 *pparams = (char *)SMB_REALLOC(*pparams,4);
6347 if (*pparams == NULL) {
6348 return ERROR_NT(NT_STATUS_NO_MEMORY);
6352 SSVAL(params,0,0); /* No changes */
6353 SSVAL(params,2,0); /* No EA errors */
6355 send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6360 /****************************************************************************
6361 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6362 ****************************************************************************/
6364 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6365 char **pparams, int total_params, char **ppdata, int total_data,
6366 unsigned int max_data_bytes)
6368 char *params = *pparams;
6371 int max_referral_level;
6372 NTSTATUS status = NT_STATUS_OK;
6374 DEBUG(10,("call_trans2getdfsreferral\n"));
6376 if (total_params < 3) {
6377 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6380 max_referral_level = SVAL(params,0);
6382 if(!lp_host_msdfs())
6383 return ERROR_DOS(ERRDOS,ERRbadfunc);
6385 srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), pathname, ¶ms[2],
6386 sizeof(pathname), total_params - 2, STR_TERMINATE);
6387 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6388 return ERROR_NT(status);
6390 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6391 send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6396 #define LMCAT_SPL 0x53
6397 #define LMFUNC_GETJOBID 0x60
6399 /****************************************************************************
6400 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6401 ****************************************************************************/
6403 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6404 char **pparams, int total_params, char **ppdata, int total_data,
6405 unsigned int max_data_bytes)
6407 char *pdata = *ppdata;
6408 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6410 /* check for an invalid fid before proceeding */
6413 return(ERROR_DOS(ERRDOS,ERRbadfid));
6415 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6416 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6417 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6418 if (*ppdata == NULL) {
6419 return ERROR_NT(NT_STATUS_NO_MEMORY);
6423 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6424 CAN ACCEPT THIS IN UNICODE. JRA. */
6426 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6427 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6428 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6429 send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6432 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6433 return ERROR_DOS(ERRSRV,ERRerror);
6437 /****************************************************************************
6438 Reply to a SMBfindclose (stop trans2 directory search).
6439 ****************************************************************************/
6441 int reply_findclose(connection_struct *conn,
6442 char *inbuf,char *outbuf,int length,int bufsize)
6445 int dptr_num=SVALS(inbuf,smb_vwv0);
6446 START_PROFILE(SMBfindclose);
6448 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6450 dptr_close(&dptr_num);
6452 outsize = set_message(inbuf, outbuf,0,0,False);
6454 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6456 END_PROFILE(SMBfindclose);
6460 /****************************************************************************
6461 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6462 ****************************************************************************/
6464 int reply_findnclose(connection_struct *conn,
6465 char *inbuf,char *outbuf,int length,int bufsize)
6469 START_PROFILE(SMBfindnclose);
6471 dptr_num = SVAL(inbuf,smb_vwv0);
6473 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6475 /* We never give out valid handles for a
6476 findnotifyfirst - so any dptr_num is ok here.
6479 outsize = set_message(inbuf, outbuf,0,0,False);
6481 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6483 END_PROFILE(SMBfindnclose);
6487 static int handle_trans2(connection_struct *conn, struct smb_request *req,
6488 struct trans_state *state,
6489 char *inbuf, char *outbuf, int size, int bufsize)
6493 if (Protocol >= PROTOCOL_NT1) {
6494 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6497 /* Now we must call the relevant TRANS2 function */
6498 switch(state->call) {
6499 case TRANSACT2_OPEN:
6501 START_PROFILE(Trans2_open);
6502 outsize = call_trans2open(
6503 conn, req, inbuf, outbuf, bufsize,
6504 &state->param, state->total_param,
6505 &state->data, state->total_data,
6506 state->max_data_return);
6507 END_PROFILE(Trans2_open);
6511 case TRANSACT2_FINDFIRST:
6513 START_PROFILE(Trans2_findfirst);
6514 outsize = call_trans2findfirst(
6515 conn, inbuf, outbuf, bufsize,
6516 &state->param, state->total_param,
6517 &state->data, state->total_data,
6518 state->max_data_return);
6519 END_PROFILE(Trans2_findfirst);
6523 case TRANSACT2_FINDNEXT:
6525 START_PROFILE(Trans2_findnext);
6526 outsize = call_trans2findnext(
6527 conn, inbuf, outbuf, size, bufsize,
6528 &state->param, state->total_param,
6529 &state->data, state->total_data,
6530 state->max_data_return);
6531 END_PROFILE(Trans2_findnext);
6535 case TRANSACT2_QFSINFO:
6537 START_PROFILE(Trans2_qfsinfo);
6538 outsize = call_trans2qfsinfo(
6539 conn, inbuf, outbuf, size, bufsize,
6540 &state->param, state->total_param,
6541 &state->data, state->total_data,
6542 state->max_data_return);
6543 END_PROFILE(Trans2_qfsinfo);
6547 case TRANSACT2_SETFSINFO:
6549 START_PROFILE(Trans2_setfsinfo);
6550 outsize = call_trans2setfsinfo(
6551 conn, inbuf, outbuf, size, bufsize,
6552 &state->param, state->total_param,
6553 &state->data, state->total_data,
6554 state->max_data_return);
6555 END_PROFILE(Trans2_setfsinfo);
6559 case TRANSACT2_QPATHINFO:
6560 case TRANSACT2_QFILEINFO:
6562 START_PROFILE(Trans2_qpathinfo);
6563 outsize = call_trans2qfilepathinfo(
6564 conn, inbuf, outbuf, size, bufsize, state->call,
6565 &state->param, state->total_param,
6566 &state->data, state->total_data,
6567 state->max_data_return);
6568 END_PROFILE(Trans2_qpathinfo);
6572 case TRANSACT2_SETPATHINFO:
6573 case TRANSACT2_SETFILEINFO:
6575 START_PROFILE(Trans2_setpathinfo);
6576 outsize = call_trans2setfilepathinfo(
6577 conn, req, inbuf, outbuf, size, bufsize, state->call,
6578 &state->param, state->total_param,
6579 &state->data, state->total_data,
6580 state->max_data_return);
6581 END_PROFILE(Trans2_setpathinfo);
6585 case TRANSACT2_FINDNOTIFYFIRST:
6587 START_PROFILE(Trans2_findnotifyfirst);
6588 outsize = call_trans2findnotifyfirst(
6589 conn, inbuf, outbuf, size, bufsize,
6590 &state->param, state->total_param,
6591 &state->data, state->total_data,
6592 state->max_data_return);
6593 END_PROFILE(Trans2_findnotifyfirst);
6597 case TRANSACT2_FINDNOTIFYNEXT:
6599 START_PROFILE(Trans2_findnotifynext);
6600 outsize = call_trans2findnotifynext(
6601 conn, inbuf, outbuf, size, bufsize,
6602 &state->param, state->total_param,
6603 &state->data, state->total_data,
6604 state->max_data_return);
6605 END_PROFILE(Trans2_findnotifynext);
6609 case TRANSACT2_MKDIR:
6611 START_PROFILE(Trans2_mkdir);
6612 outsize = call_trans2mkdir(
6613 conn, inbuf, outbuf, size, bufsize,
6614 &state->param, state->total_param,
6615 &state->data, state->total_data,
6616 state->max_data_return);
6617 END_PROFILE(Trans2_mkdir);
6621 case TRANSACT2_GET_DFS_REFERRAL:
6623 START_PROFILE(Trans2_get_dfs_referral);
6624 outsize = call_trans2getdfsreferral(
6625 conn, inbuf, outbuf, size, bufsize,
6626 &state->param, state->total_param,
6627 &state->data, state->total_data,
6628 state->max_data_return);
6629 END_PROFILE(Trans2_get_dfs_referral);
6633 case TRANSACT2_IOCTL:
6635 START_PROFILE(Trans2_ioctl);
6636 outsize = call_trans2ioctl(
6637 conn, inbuf, outbuf, size, bufsize,
6638 &state->param, state->total_param,
6639 &state->data, state->total_data,
6640 state->max_data_return);
6641 END_PROFILE(Trans2_ioctl);
6646 /* Error in request */
6647 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6648 outsize = ERROR_DOS(ERRSRV,ERRerror);
6654 /****************************************************************************
6655 Reply to a SMBtrans2.
6656 ****************************************************************************/
6658 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6659 int size, int bufsize)
6662 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6663 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6664 unsigned int psoff = SVAL(inbuf, smb_psoff);
6665 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6666 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6667 struct trans_state *state;
6670 START_PROFILE(SMBtrans2);
6672 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6673 if (!NT_STATUS_IS_OK(result)) {
6674 DEBUG(2, ("Got invalid trans2 request: %s\n",
6675 nt_errstr(result)));
6676 END_PROFILE(SMBtrans2);
6677 return ERROR_NT(result);
6680 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6681 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
6682 && (tran_call != TRANSACT2_QFILEINFO)) {
6683 END_PROFILE(SMBtrans2);
6684 return ERROR_DOS(ERRSRV,ERRaccess);
6687 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6688 DEBUG(0, ("talloc failed\n"));
6689 END_PROFILE(SMBtrans2);
6690 return ERROR_NT(NT_STATUS_NO_MEMORY);
6693 state->cmd = SMBtrans2;
6695 state->mid = SVAL(inbuf, smb_mid);
6696 state->vuid = SVAL(inbuf, smb_uid);
6697 state->setup_count = SVAL(inbuf, smb_suwcnt);
6698 state->setup = NULL;
6699 state->total_param = SVAL(inbuf, smb_tpscnt);
6700 state->param = NULL;
6701 state->total_data = SVAL(inbuf, smb_tdscnt);
6703 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6704 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6705 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6706 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6707 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6709 state->call = tran_call;
6711 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6712 is so as a sanity check */
6713 if (state->setup_count != 1) {
6715 * Need to have rc=0 for ioctl to get job id for OS/2.
6716 * Network printing will fail if function is not successful.
6717 * Similar function in reply.c will be used if protocol
6718 * is LANMAN1.0 instead of LM1.2X002.
6719 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6720 * outbuf doesn't have to be set(only job id is used).
6722 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6723 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6724 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6725 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6727 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6728 DEBUG(2,("Transaction is %d\n",tran_call));
6730 END_PROFILE(SMBtrans2);
6731 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6735 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6738 if (state->total_data) {
6739 /* Can't use talloc here, the core routines do realloc on the
6740 * params and data. */
6741 state->data = (char *)SMB_MALLOC(state->total_data);
6742 if (state->data == NULL) {
6743 DEBUG(0,("reply_trans2: data malloc fail for %u "
6744 "bytes !\n", (unsigned int)state->total_data));
6746 END_PROFILE(SMBtrans2);
6747 return(ERROR_DOS(ERRDOS,ERRnomem));
6749 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6751 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6752 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6755 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6758 if (state->total_param) {
6759 /* Can't use talloc here, the core routines do realloc on the
6760 * params and data. */
6761 state->param = (char *)SMB_MALLOC(state->total_param);
6762 if (state->param == NULL) {
6763 DEBUG(0,("reply_trans: param malloc fail for %u "
6764 "bytes !\n", (unsigned int)state->total_param));
6765 SAFE_FREE(state->data);
6767 END_PROFILE(SMBtrans2);
6768 return(ERROR_DOS(ERRDOS,ERRnomem));
6770 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6772 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6773 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6776 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6779 state->received_data = dscnt;
6780 state->received_param = pscnt;
6782 if ((state->received_param == state->total_param) &&
6783 (state->received_data == state->total_data)) {
6785 struct smb_request req;
6786 init_smb_request(&req, (uint8 *)inbuf);
6788 outsize = handle_trans2(conn, &req, state, inbuf, outbuf,
6790 SAFE_FREE(state->data);
6791 SAFE_FREE(state->param);
6793 END_PROFILE(SMBtrans2);
6797 DLIST_ADD(conn->pending_trans, state);
6799 /* We need to send an interim response then receive the rest
6800 of the parameter/data bytes */
6801 outsize = set_message(inbuf, outbuf,0,0,False);
6803 END_PROFILE(SMBtrans2);
6808 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6809 SAFE_FREE(state->data);
6810 SAFE_FREE(state->param);
6812 END_PROFILE(SMBtrans2);
6813 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6817 /****************************************************************************
6818 Reply to a SMBtranss2
6819 ****************************************************************************/
6821 int reply_transs2(connection_struct *conn,
6822 char *inbuf,char *outbuf,int size,int bufsize)
6825 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6826 struct trans_state *state;
6827 struct smb_request req;
6829 START_PROFILE(SMBtranss2);
6833 for (state = conn->pending_trans; state != NULL;
6834 state = state->next) {
6835 if (state->mid == SVAL(inbuf,smb_mid)) {
6840 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6841 END_PROFILE(SMBtranss2);
6842 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6845 /* Revise state->total_param and state->total_data in case they have
6846 changed downwards */
6848 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6849 state->total_param = SVAL(inbuf, smb_tpscnt);
6850 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6851 state->total_data = SVAL(inbuf, smb_tdscnt);
6853 pcnt = SVAL(inbuf, smb_spscnt);
6854 poff = SVAL(inbuf, smb_spsoff);
6855 pdisp = SVAL(inbuf, smb_spsdisp);
6857 dcnt = SVAL(inbuf, smb_sdscnt);
6858 doff = SVAL(inbuf, smb_sdsoff);
6859 ddisp = SVAL(inbuf, smb_sdsdisp);
6861 state->received_param += pcnt;
6862 state->received_data += dcnt;
6864 if ((state->received_data > state->total_data) ||
6865 (state->received_param > state->total_param))
6869 if (pdisp+pcnt > state->total_param)
6871 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6873 if (pdisp > state->total_param)
6875 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6876 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6878 if (state->param + pdisp < state->param)
6881 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6886 if (ddisp+dcnt > state->total_data)
6888 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6890 if (ddisp > state->total_data)
6892 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6893 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6895 if (state->data + ddisp < state->data)
6898 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6902 if ((state->received_param < state->total_param) ||
6903 (state->received_data < state->total_data)) {
6904 END_PROFILE(SMBtranss2);
6908 /* construct_reply_common has done us the favor to pre-fill the
6909 * command field with SMBtranss2 which is wrong :-)
6911 SCVAL(outbuf,smb_com,SMBtrans2);
6913 init_smb_request(&req, (uint8 *)inbuf);
6915 outsize = handle_trans2(conn, &req, state, inbuf, outbuf, size,
6918 DLIST_REMOVE(conn->pending_trans, state);
6919 SAFE_FREE(state->data);
6920 SAFE_FREE(state->param);
6924 END_PROFILE(SMBtranss2);
6925 return(ERROR_DOS(ERRSRV,ERRnosupport));
6928 END_PROFILE(SMBtranss2);
6933 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6934 DLIST_REMOVE(conn->pending_trans, state);
6935 SAFE_FREE(state->data);
6936 SAFE_FREE(state->param);
6938 END_PROFILE(SMBtranss2);
6939 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);