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"));
3003 own_grp = (unsigned int)*puid;
3004 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3005 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3006 SIVAL(pdata,2,own_grp);
3010 case SMB_ACL_GROUP_OBJ:
3011 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3012 own_grp = (unsigned int)pst->st_gid;
3013 SIVAL(pdata,2,own_grp);
3018 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3020 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3023 own_grp = (unsigned int)*pgid;
3024 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3025 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3026 SIVAL(pdata,2,own_grp);
3031 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3032 SIVAL(pdata,2,0xFFFFFFFF);
3033 SIVAL(pdata,6,0xFFFFFFFF);
3036 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3037 SIVAL(pdata,2,0xFFFFFFFF);
3038 SIVAL(pdata,6,0xFFFFFFFF);
3041 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3044 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3051 /****************************************************************************
3052 Store the FILE_UNIX_BASIC info.
3053 ****************************************************************************/
3055 static char *store_file_unix_basic(connection_struct *conn,
3058 const SMB_STRUCT_STAT *psbuf)
3060 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3061 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3063 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3066 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3069 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3070 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3071 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3074 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3078 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3082 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3085 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3089 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3093 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3096 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3100 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3107 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3108 * the chflags(2) (or equivalent) flags.
3110 * XXX: this really should be behind the VFS interface. To do this, we would
3111 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3112 * Each VFS module could then implement it's own mapping as appropriate for the
3113 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3115 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3119 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3123 { UF_IMMUTABLE, EXT_IMMUTABLE },
3127 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3131 { UF_HIDDEN, EXT_HIDDEN },
3134 /* Do not remove. We need to guarantee that this array has at least one
3135 * entry to build on HP-UX.
3141 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3142 uint32 *smb_fflags, uint32 *smb_fmask)
3144 #ifdef HAVE_STAT_ST_FLAGS
3147 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3148 *smb_fmask |= info2_flags_map[i].smb_fflag;
3149 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3150 *smb_fflags |= info2_flags_map[i].smb_fflag;
3153 #endif /* HAVE_STAT_ST_FLAGS */
3156 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3157 const uint32 smb_fflags,
3158 const uint32 smb_fmask,
3161 #ifdef HAVE_STAT_ST_FLAGS
3162 uint32 max_fmask = 0;
3165 *stat_fflags = psbuf->st_flags;
3167 /* For each flags requested in smb_fmask, check the state of the
3168 * corresponding flag in smb_fflags and set or clear the matching
3172 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3173 max_fmask |= info2_flags_map[i].smb_fflag;
3174 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3175 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3176 *stat_fflags |= info2_flags_map[i].stat_fflag;
3178 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3183 /* If smb_fmask is asking to set any bits that are not supported by
3184 * our flag mappings, we should fail.
3186 if ((smb_fmask & max_fmask) != smb_fmask) {
3193 #endif /* HAVE_STAT_ST_FLAGS */
3197 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3198 * of file flags and birth (create) time.
3200 static char *store_file_unix_basic_info2(connection_struct *conn,
3203 const SMB_STRUCT_STAT *psbuf)
3205 uint32 file_flags = 0;
3206 uint32 flags_mask = 0;
3208 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3210 /* Create (birth) time 64 bit */
3211 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3214 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3215 SIVAL(pdata, 0, file_flags); /* flags */
3216 SIVAL(pdata, 4, flags_mask); /* mask */
3222 /****************************************************************************
3223 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3224 ****************************************************************************/
3226 static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3227 unsigned int tran_call,
3228 char **pparams, int total_params, char **ppdata, int total_data,
3229 unsigned int max_data_bytes)
3231 char *params = *pparams;
3232 char *pdata = *ppdata;
3233 unsigned int data_size = 0;
3234 unsigned int param_size = 2;
3236 smb_np_struct *p_pipe = NULL;
3239 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3242 if (total_params < 4) {
3243 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3246 p_pipe = get_rpc_pipe_p(params,0);
3247 if (p_pipe == NULL) {
3248 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3251 info_level = SVAL(params,2);
3253 *pparams = (char *)SMB_REALLOC(*pparams,2);
3254 if (*pparams == NULL) {
3255 return ERROR_NT(NT_STATUS_NO_MEMORY);
3259 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3260 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3261 if (*ppdata == NULL ) {
3262 return ERROR_NT(NT_STATUS_NO_MEMORY);
3266 switch (info_level) {
3267 case SMB_FILE_STANDARD_INFORMATION:
3269 SOFF_T(pdata,0,4096LL);
3276 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3279 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3284 /****************************************************************************
3285 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3286 file name or file id).
3287 ****************************************************************************/
3289 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3290 unsigned int tran_call,
3291 char **pparams, int total_params, char **ppdata, int total_data,
3292 unsigned int max_data_bytes)
3294 char *params = *pparams;
3295 char *pdata = *ppdata;
3299 SMB_OFF_T file_size=0;
3300 SMB_BIG_UINT allocation_size=0;
3301 unsigned int data_size = 0;
3302 unsigned int param_size = 2;
3303 SMB_STRUCT_STAT sbuf;
3304 pstring fname, dos_fname;
3309 BOOL delete_pending = False;
3311 time_t create_time, mtime, atime;
3312 struct timespec create_time_ts, mtime_ts, atime_ts;
3313 files_struct *fsp = NULL;
3314 TALLOC_CTX *data_ctx = NULL;
3315 struct ea_list *ea_list = NULL;
3316 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3317 char *lock_data = NULL;
3320 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3324 if (tran_call == TRANSACT2_QFILEINFO) {
3325 if (total_params < 4) {
3326 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3330 return call_trans2qpipeinfo(conn,
3343 fsp = file_fsp(params,0);
3344 info_level = SVAL(params,2);
3346 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3348 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3349 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3352 if(fsp && (fsp->fake_file_handle)) {
3354 * This is actually for the QUOTA_FAKE_FILE --metze
3357 pstrcpy(fname, fsp->fsp_name);
3358 /* We know this name is ok, it's already passed the checks. */
3360 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3362 * This is actually a QFILEINFO on a directory
3363 * handle (returned from an NT SMB). NT5.0 seems
3364 * to do this call. JRA.
3366 /* We know this name is ok, it's already passed the checks. */
3367 pstrcpy(fname, fsp->fsp_name);
3369 if (INFO_LEVEL_IS_UNIX(info_level)) {
3370 /* Always do lstat for UNIX calls. */
3371 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3372 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3373 return UNIXERROR(ERRDOS,ERRbadpath);
3375 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3376 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3377 return UNIXERROR(ERRDOS,ERRbadpath);
3380 delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf));
3383 * Original code - this is an open file.
3385 CHECK_FSP(fsp,conn);
3387 pstrcpy(fname, fsp->fsp_name);
3388 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3389 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3390 return(UNIXERROR(ERRDOS,ERRbadfid));
3392 pos = fsp->fh->position_information;
3393 delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf));
3394 access_mask = fsp->access_mask;
3397 NTSTATUS status = NT_STATUS_OK;
3400 if (total_params < 7) {
3401 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3404 info_level = SVAL(params,0);
3406 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3408 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3409 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3412 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, ¶ms[6],
3413 sizeof(fname), total_params - 6,
3414 STR_TERMINATE, &status);
3415 if (!NT_STATUS_IS_OK(status)) {
3416 return ERROR_NT(status);
3419 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3420 if (!NT_STATUS_IS_OK(status)) {
3421 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3422 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3424 return ERROR_NT(status);
3427 status = unix_convert(conn, fname, False, NULL, &sbuf);
3428 if (!NT_STATUS_IS_OK(status)) {
3429 return ERROR_NT(status);
3431 status = check_name(conn, fname);
3432 if (!NT_STATUS_IS_OK(status)) {
3433 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3434 return ERROR_NT(status);
3437 if (INFO_LEVEL_IS_UNIX(info_level)) {
3438 /* Always do lstat for UNIX calls. */
3439 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3440 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3441 return UNIXERROR(ERRDOS,ERRbadpath);
3443 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3444 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3445 return UNIXERROR(ERRDOS,ERRbadpath);
3448 delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf));
3449 if (delete_pending) {
3450 return ERROR_NT(NT_STATUS_DELETE_PENDING);
3454 nlink = sbuf.st_nlink;
3456 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3457 /* NTFS does not seem to count ".." */
3461 if ((nlink > 0) && delete_pending) {
3465 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3466 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3469 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3470 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3472 p = strrchr_m(fname,'/');
3478 mode = dos_mode(conn,fname,&sbuf);
3480 mode = FILE_ATTRIBUTE_NORMAL;
3482 fullpathname = fname;
3484 file_size = get_file_size(sbuf);
3486 /* Pull out any data sent here before we realloc. */
3487 switch (info_level) {
3488 case SMB_INFO_QUERY_EAS_FROM_LIST:
3490 /* Pull any EA list from the data portion. */
3493 if (total_data < 4) {
3494 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3496 ea_size = IVAL(pdata,0);
3498 if (total_data > 0 && ea_size != total_data) {
3499 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3500 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3501 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3504 if (!lp_ea_support(SNUM(conn))) {
3505 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3508 if ((data_ctx = talloc_init("ea_list")) == NULL) {
3509 return ERROR_NT(NT_STATUS_NO_MEMORY);
3512 /* Pull out the list of names. */
3513 ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3515 talloc_destroy(data_ctx);
3516 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3521 case SMB_QUERY_POSIX_LOCK:
3523 if (fsp == NULL || fsp->fh->fd == -1) {
3524 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3527 if (total_data != POSIX_LOCK_DATA_SIZE) {
3528 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3531 if ((data_ctx = talloc_init("lock_request")) == NULL) {
3532 return ERROR_NT(NT_STATUS_NO_MEMORY);
3535 /* Copy the lock range data. */
3536 lock_data = (char *)TALLOC_MEMDUP(
3537 data_ctx, pdata, total_data);
3539 talloc_destroy(data_ctx);
3540 return ERROR_NT(NT_STATUS_NO_MEMORY);
3547 *pparams = (char *)SMB_REALLOC(*pparams,2);
3548 if (*pparams == NULL) {
3549 talloc_destroy(data_ctx);
3550 return ERROR_NT(NT_STATUS_NO_MEMORY);
3554 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3555 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3556 if (*ppdata == NULL ) {
3557 talloc_destroy(data_ctx);
3558 return ERROR_NT(NT_STATUS_NO_MEMORY);
3562 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3563 mtime_ts = get_mtimespec(&sbuf);
3564 atime_ts = get_atimespec(&sbuf);
3566 allocation_size = get_allocation_size(conn,fsp,&sbuf);
3569 if (!null_timespec(fsp->pending_modtime)) {
3570 /* the pending modtime overrides the current modtime */
3571 mtime_ts = fsp->pending_modtime;
3574 /* Do we have this path open ? */
3575 files_struct *fsp1 = file_find_di_first(file_id_sbuf(&sbuf));
3576 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3577 /* the pending modtime overrides the current modtime */
3578 mtime_ts = fsp1->pending_modtime;
3580 if (fsp1 && fsp1->initial_allocation_size) {
3581 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3585 if (lp_dos_filetime_resolution(SNUM(conn))) {
3586 dos_filetime_timespec(&create_time_ts);
3587 dos_filetime_timespec(&mtime_ts);
3588 dos_filetime_timespec(&atime_ts);
3591 create_time = convert_timespec_to_time_t(create_time_ts);
3592 mtime = convert_timespec_to_time_t(mtime_ts);
3593 atime = convert_timespec_to_time_t(atime_ts);
3595 /* NT expects the name to be in an exact form of the *full*
3596 filename. See the trans2 torture test */
3597 if (strequal(base_name,".")) {
3598 pstrcpy(dos_fname, "\\");
3600 pstr_sprintf(dos_fname, "\\%s", fname);
3601 string_replace(dos_fname, '/', '\\');
3604 switch (info_level) {
3605 case SMB_INFO_STANDARD:
3606 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3608 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3609 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3610 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3611 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3612 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3613 SSVAL(pdata,l1_attrFile,mode);
3616 case SMB_INFO_QUERY_EA_SIZE:
3618 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3619 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3621 srv_put_dos_date2(pdata,0,create_time);
3622 srv_put_dos_date2(pdata,4,atime);
3623 srv_put_dos_date2(pdata,8,mtime); /* write time */
3624 SIVAL(pdata,12,(uint32)file_size);
3625 SIVAL(pdata,16,(uint32)allocation_size);
3626 SSVAL(pdata,20,mode);
3627 SIVAL(pdata,22,ea_size);
3631 case SMB_INFO_IS_NAME_VALID:
3632 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3633 if (tran_call == TRANSACT2_QFILEINFO) {
3634 /* os/2 needs this ? really ?*/
3635 return ERROR_DOS(ERRDOS,ERRbadfunc);
3641 case SMB_INFO_QUERY_EAS_FROM_LIST:
3643 size_t total_ea_len = 0;
3644 struct ea_list *ea_file_list = NULL;
3646 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3648 ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3649 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3651 if (!ea_list || (total_ea_len > data_size)) {
3652 talloc_destroy(data_ctx);
3654 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3658 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3659 talloc_destroy(data_ctx);
3663 case SMB_INFO_QUERY_ALL_EAS:
3665 /* We have data_size bytes to put EA's into. */
3666 size_t total_ea_len = 0;
3668 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3670 data_ctx = talloc_init("ea_ctx");
3672 return ERROR_NT(NT_STATUS_NO_MEMORY);
3675 ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3676 if (!ea_list || (total_ea_len > data_size)) {
3677 talloc_destroy(data_ctx);
3679 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3683 data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3684 talloc_destroy(data_ctx);
3688 case SMB_FILE_BASIC_INFORMATION:
3689 case SMB_QUERY_FILE_BASIC_INFO:
3691 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3692 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3693 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3695 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3699 put_long_date_timespec(pdata,create_time_ts);
3700 put_long_date_timespec(pdata+8,atime_ts);
3701 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3702 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3703 SIVAL(pdata,32,mode);
3705 DEBUG(5,("SMB_QFBI - "));
3706 DEBUG(5,("create: %s ", ctime(&create_time)));
3707 DEBUG(5,("access: %s ", ctime(&atime)));
3708 DEBUG(5,("write: %s ", ctime(&mtime)));
3709 DEBUG(5,("change: %s ", ctime(&mtime)));
3710 DEBUG(5,("mode: %x\n", mode));
3713 case SMB_FILE_STANDARD_INFORMATION:
3714 case SMB_QUERY_FILE_STANDARD_INFO:
3716 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3718 SOFF_T(pdata,0,allocation_size);
3719 SOFF_T(pdata,8,file_size);
3720 SIVAL(pdata,16,nlink);
3721 SCVAL(pdata,20,delete_pending?1:0);
3722 SCVAL(pdata,21,(mode&aDIR)?1:0);
3723 SSVAL(pdata,22,0); /* Padding. */
3726 case SMB_FILE_EA_INFORMATION:
3727 case SMB_QUERY_FILE_EA_INFO:
3729 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3730 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3732 SIVAL(pdata,0,ea_size);
3736 /* Get the 8.3 name - used if NT SMB was negotiated. */
3737 case SMB_QUERY_FILE_ALT_NAME_INFO:
3738 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3742 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3743 pstrcpy(short_name,base_name);
3744 /* Mangle if not already 8.3 */
3745 if(!mangle_is_8_3(short_name, True, conn->params)) {
3746 mangle_map(short_name,True,True,conn->params);
3748 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3749 data_size = 4 + len;
3754 case SMB_QUERY_FILE_NAME_INFO:
3756 this must be *exactly* right for ACLs on mapped drives to work
3758 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3759 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3760 data_size = 4 + len;
3764 case SMB_FILE_ALLOCATION_INFORMATION:
3765 case SMB_QUERY_FILE_ALLOCATION_INFO:
3766 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3768 SOFF_T(pdata,0,allocation_size);
3771 case SMB_FILE_END_OF_FILE_INFORMATION:
3772 case SMB_QUERY_FILE_END_OF_FILEINFO:
3773 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3775 SOFF_T(pdata,0,file_size);
3778 case SMB_QUERY_FILE_ALL_INFO:
3779 case SMB_FILE_ALL_INFORMATION:
3781 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3782 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3783 put_long_date_timespec(pdata,create_time_ts);
3784 put_long_date_timespec(pdata+8,atime_ts);
3785 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3786 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3787 SIVAL(pdata,32,mode);
3788 SIVAL(pdata,36,0); /* padding. */
3790 SOFF_T(pdata,0,allocation_size);
3791 SOFF_T(pdata,8,file_size);
3792 SIVAL(pdata,16,nlink);
3793 SCVAL(pdata,20,delete_pending);
3794 SCVAL(pdata,21,(mode&aDIR)?1:0);
3797 SIVAL(pdata,0,ea_size);
3798 pdata += 4; /* EA info */
3799 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3802 data_size = PTR_DIFF(pdata,(*ppdata));
3805 case SMB_FILE_INTERNAL_INFORMATION:
3806 /* This should be an index number - looks like
3809 I think this causes us to fail the IFSKIT
3810 BasicFileInformationTest. -tpot */
3812 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3813 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3814 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3818 case SMB_FILE_ACCESS_INFORMATION:
3819 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3820 SIVAL(pdata,0,access_mask);
3824 case SMB_FILE_NAME_INFORMATION:
3825 /* Pathname with leading '\'. */
3828 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3829 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3830 SIVAL(pdata,0,byte_len);
3831 data_size = 4 + byte_len;
3835 case SMB_FILE_DISPOSITION_INFORMATION:
3836 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3838 SCVAL(pdata,0,delete_pending);
3841 case SMB_FILE_POSITION_INFORMATION:
3842 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3844 SOFF_T(pdata,0,pos);
3847 case SMB_FILE_MODE_INFORMATION:
3848 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3849 SIVAL(pdata,0,mode);
3853 case SMB_FILE_ALIGNMENT_INFORMATION:
3854 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3855 SIVAL(pdata,0,0); /* No alignment needed. */
3861 * NT4 server just returns "invalid query" to this - if we try to answer
3862 * it then NTws gets a BSOD! (tridge).
3863 * W2K seems to want this. JRA.
3865 case SMB_QUERY_FILE_STREAM_INFO:
3867 case SMB_FILE_STREAM_INFORMATION:
3868 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3872 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3873 SIVAL(pdata,0,0); /* ??? */
3874 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3875 SOFF_T(pdata,8,file_size);
3876 SOFF_T(pdata,16,allocation_size);
3877 data_size = 24 + byte_len;
3881 case SMB_QUERY_COMPRESSION_INFO:
3882 case SMB_FILE_COMPRESSION_INFORMATION:
3883 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3884 SOFF_T(pdata,0,file_size);
3885 SIVAL(pdata,8,0); /* ??? */
3886 SIVAL(pdata,12,0); /* ??? */
3890 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3891 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3892 put_long_date_timespec(pdata,create_time_ts);
3893 put_long_date_timespec(pdata+8,atime_ts);
3894 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3895 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3896 SOFF_T(pdata,32,allocation_size);
3897 SOFF_T(pdata,40,file_size);
3898 SIVAL(pdata,48,mode);
3899 SIVAL(pdata,52,0); /* ??? */
3903 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3904 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3905 SIVAL(pdata,0,mode);
3911 * CIFS UNIX Extensions.
3914 case SMB_QUERY_FILE_UNIX_BASIC:
3916 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3917 data_size = PTR_DIFF(pdata,(*ppdata));
3921 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3923 for (i=0; i<100; i++)
3924 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3930 case SMB_QUERY_FILE_UNIX_INFO2:
3932 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3933 data_size = PTR_DIFF(pdata,(*ppdata));
3937 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3939 for (i=0; i<100; i++)
3940 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3946 case SMB_QUERY_FILE_UNIX_LINK:
3950 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3952 if(!S_ISLNK(sbuf.st_mode))
3953 return(UNIXERROR(ERRSRV,ERRbadlink));
3955 return(UNIXERROR(ERRDOS,ERRbadlink));
3957 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3959 return(UNIXERROR(ERRDOS,ERRnoaccess));
3961 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3963 data_size = PTR_DIFF(pdata,(*ppdata));
3968 #if defined(HAVE_POSIX_ACLS)
3969 case SMB_QUERY_POSIX_ACL:
3971 SMB_ACL_T file_acl = NULL;
3972 SMB_ACL_T def_acl = NULL;
3973 uint16 num_file_acls = 0;
3974 uint16 num_def_acls = 0;
3976 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3977 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3979 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3982 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3983 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3985 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3988 if (S_ISDIR(sbuf.st_mode)) {
3989 if (fsp && fsp->is_directory) {
3990 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3992 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3994 def_acl = free_empty_sys_acl(conn, def_acl);
3997 num_file_acls = count_acl_entries(conn, file_acl);
3998 num_def_acls = count_acl_entries(conn, def_acl);
4000 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4001 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4003 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4004 SMB_POSIX_ACL_HEADER_SIZE) ));
4006 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4009 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4011 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
4014 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4015 SSVAL(pdata,2,num_file_acls);
4016 SSVAL(pdata,4,num_def_acls);
4017 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4019 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4022 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4024 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4026 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4028 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4031 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4033 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4037 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4040 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4042 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4048 case SMB_QUERY_POSIX_LOCK:
4050 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4052 SMB_BIG_UINT offset;
4054 enum brl_type lock_type;
4056 if (total_data != POSIX_LOCK_DATA_SIZE) {
4057 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4060 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4061 case POSIX_LOCK_TYPE_READ:
4062 lock_type = READ_LOCK;
4064 case POSIX_LOCK_TYPE_WRITE:
4065 lock_type = WRITE_LOCK;
4067 case POSIX_LOCK_TYPE_UNLOCK:
4069 /* There's no point in asking for an unlock... */
4070 talloc_destroy(data_ctx);
4071 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4074 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4075 #if defined(HAVE_LONGLONG)
4076 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4077 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4078 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4079 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4080 #else /* HAVE_LONGLONG */
4081 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4082 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4083 #endif /* HAVE_LONGLONG */
4085 status = query_lock(fsp,
4092 if (ERROR_WAS_LOCK_DENIED(status)) {
4093 /* Here we need to report who has it locked... */
4094 data_size = POSIX_LOCK_DATA_SIZE;
4096 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4097 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4098 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4099 #if defined(HAVE_LONGLONG)
4100 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4101 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4102 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4103 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4104 #else /* HAVE_LONGLONG */
4105 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4106 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4107 #endif /* HAVE_LONGLONG */
4109 } else if (NT_STATUS_IS_OK(status)) {
4110 /* For success we just return a copy of what we sent
4111 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4112 data_size = POSIX_LOCK_DATA_SIZE;
4113 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4114 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4116 return ERROR_NT(status);
4122 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4125 send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
4130 /****************************************************************************
4131 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4133 ****************************************************************************/
4135 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4137 SMB_STRUCT_STAT sbuf1, sbuf2;
4138 pstring last_component_oldname;
4139 pstring last_component_newname;
4140 NTSTATUS status = NT_STATUS_OK;
4145 status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4146 if (!NT_STATUS_IS_OK(status)) {
4150 status = check_name(conn, oldname);
4151 if (!NT_STATUS_IS_OK(status)) {
4155 /* source must already exist. */
4156 if (!VALID_STAT(sbuf1)) {
4157 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4160 status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4161 if (!NT_STATUS_IS_OK(status)) {
4165 status = check_name(conn, newname);
4166 if (!NT_STATUS_IS_OK(status)) {
4170 /* Disallow if newname already exists. */
4171 if (VALID_STAT(sbuf2)) {
4172 return NT_STATUS_OBJECT_NAME_COLLISION;
4175 /* No links from a directory. */
4176 if (S_ISDIR(sbuf1.st_mode)) {
4177 return NT_STATUS_FILE_IS_A_DIRECTORY;
4180 /* Ensure this is within the share. */
4181 status = check_reduced_name(conn, oldname);
4182 if (!NT_STATUS_IS_OK(status)) {
4186 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4188 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4189 status = map_nt_error_from_unix(errno);
4190 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4191 nt_errstr(status), newname, oldname));
4197 /****************************************************************************
4198 Deal with setting the time from any of the setfilepathinfo functions.
4199 ****************************************************************************/
4201 static NTSTATUS smb_set_file_time(connection_struct *conn,
4204 const SMB_STRUCT_STAT *psbuf,
4205 struct timespec ts[2])
4208 FILE_NOTIFY_CHANGE_LAST_ACCESS
4209 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4212 if (!VALID_STAT(*psbuf)) {
4213 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4216 /* get some defaults (no modifications) if any info is zero or -1. */
4217 if (null_timespec(ts[0])) {
4218 ts[0] = get_atimespec(psbuf);
4219 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4222 if (null_timespec(ts[1])) {
4223 ts[1] = get_mtimespec(psbuf);
4224 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4227 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4228 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4231 * Try and set the times of this file if
4232 * they are different from the current values.
4236 struct timespec mts = get_mtimespec(psbuf);
4237 struct timespec ats = get_atimespec(psbuf);
4238 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4239 return NT_STATUS_OK;
4245 * This was a setfileinfo on an open file.
4246 * NT does this a lot. We also need to
4247 * set the time here, as it can be read by
4248 * FindFirst/FindNext and with the patch for bug #2045
4249 * in smbd/fileio.c it ensures that this timestamp is
4250 * kept sticky even after a write. We save the request
4251 * away and will set it on file close and after a write. JRA.
4254 if (!null_timespec(ts[1])) {
4255 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4256 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4257 fsp_set_pending_modtime(fsp, ts[1]);
4261 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4263 if(file_ntimes(conn, fname, ts)!=0) {
4264 return map_nt_error_from_unix(errno);
4267 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4269 return NT_STATUS_OK;
4272 /****************************************************************************
4273 Deal with setting the dosmode from any of the setfilepathinfo functions.
4274 ****************************************************************************/
4276 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4278 SMB_STRUCT_STAT *psbuf,
4281 if (!VALID_STAT(*psbuf)) {
4282 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4286 if (S_ISDIR(psbuf->st_mode)) {
4293 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4295 /* check the mode isn't different, before changing it */
4296 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4298 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4299 fname, (unsigned int)dosmode ));
4301 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4302 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4303 fname, strerror(errno)));
4304 return map_nt_error_from_unix(errno);
4307 return NT_STATUS_OK;
4310 /****************************************************************************
4311 Deal with setting the size from any of the setfilepathinfo functions.
4312 ****************************************************************************/
4314 static NTSTATUS smb_set_file_size(connection_struct *conn,
4315 struct smb_request *req,
4318 SMB_STRUCT_STAT *psbuf,
4321 NTSTATUS status = NT_STATUS_OK;
4322 files_struct *new_fsp = NULL;
4324 if (!VALID_STAT(*psbuf)) {
4325 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4328 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4330 if (size == get_file_size(*psbuf)) {
4331 return NT_STATUS_OK;
4334 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4335 fname, (double)size ));
4337 if (fsp && fsp->fh->fd != -1) {
4338 /* Handle based call. */
4339 if (vfs_set_filelen(fsp, size) == -1) {
4340 return map_nt_error_from_unix(errno);
4342 return NT_STATUS_OK;
4345 status = open_file_ntcreate(conn, req, fname, psbuf,
4347 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4350 FILE_ATTRIBUTE_NORMAL,
4351 FORCE_OPLOCK_BREAK_TO_NONE,
4354 if (!NT_STATUS_IS_OK(status)) {
4355 /* NB. We check for open_was_deferred in the caller. */
4359 if (vfs_set_filelen(new_fsp, size) == -1) {
4360 status = map_nt_error_from_unix(errno);
4361 close_file(new_fsp,NORMAL_CLOSE);
4365 close_file(new_fsp,NORMAL_CLOSE);
4366 return NT_STATUS_OK;
4369 /****************************************************************************
4370 Deal with SMB_INFO_SET_EA.
4371 ****************************************************************************/
4373 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4379 struct ea_list *ea_list = NULL;
4380 TALLOC_CTX *ctx = NULL;
4381 NTSTATUS status = NT_STATUS_OK;
4383 if (total_data < 10) {
4385 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4386 length. They seem to have no effect. Bug #3212. JRA */
4388 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4389 /* We're done. We only get EA info in this call. */
4390 return NT_STATUS_OK;
4393 return NT_STATUS_INVALID_PARAMETER;
4396 if (IVAL(pdata,0) > total_data) {
4397 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4398 IVAL(pdata,0), (unsigned int)total_data));
4399 return NT_STATUS_INVALID_PARAMETER;
4402 ctx = talloc_init("SMB_INFO_SET_EA");
4404 return NT_STATUS_NO_MEMORY;
4406 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4408 talloc_destroy(ctx);
4409 return NT_STATUS_INVALID_PARAMETER;
4411 status = set_ea(conn, fsp, fname, ea_list);
4412 talloc_destroy(ctx);
4417 /****************************************************************************
4418 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4419 ****************************************************************************/
4421 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4426 SMB_STRUCT_STAT *psbuf)
4428 NTSTATUS status = NT_STATUS_OK;
4429 BOOL delete_on_close;
4432 if (total_data < 1) {
4433 return NT_STATUS_INVALID_PARAMETER;
4437 return NT_STATUS_INVALID_HANDLE;
4440 delete_on_close = (CVAL(pdata,0) ? True : False);
4441 dosmode = dos_mode(conn, fname, psbuf);
4443 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4444 "delete_on_close = %u\n",
4446 (unsigned int)dosmode,
4447 (unsigned int)delete_on_close ));
4449 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4451 if (!NT_STATUS_IS_OK(status)) {
4455 /* The set is across all open files on this dev/inode pair. */
4456 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
4457 return NT_STATUS_ACCESS_DENIED;
4459 return NT_STATUS_OK;
4462 /****************************************************************************
4463 Deal with SMB_FILE_POSITION_INFORMATION.
4464 ****************************************************************************/
4466 static NTSTATUS smb_file_position_information(connection_struct *conn,
4471 SMB_BIG_UINT position_information;
4473 if (total_data < 8) {
4474 return NT_STATUS_INVALID_PARAMETER;
4478 /* Ignore on pathname based set. */
4479 return NT_STATUS_OK;
4482 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4483 #ifdef LARGE_SMB_OFF_T
4484 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4485 #else /* LARGE_SMB_OFF_T */
4486 if (IVAL(pdata,4) != 0) {
4487 /* more than 32 bits? */
4488 return NT_STATUS_INVALID_PARAMETER;
4490 #endif /* LARGE_SMB_OFF_T */
4492 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4493 fsp->fsp_name, (double)position_information ));
4494 fsp->fh->position_information = position_information;
4495 return NT_STATUS_OK;
4498 /****************************************************************************
4499 Deal with SMB_FILE_MODE_INFORMATION.
4500 ****************************************************************************/
4502 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4508 if (total_data < 4) {
4509 return NT_STATUS_INVALID_PARAMETER;
4511 mode = IVAL(pdata,0);
4512 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4513 return NT_STATUS_INVALID_PARAMETER;
4515 return NT_STATUS_OK;
4518 /****************************************************************************
4519 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4520 ****************************************************************************/
4522 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4528 pstring link_target;
4529 const char *newname = fname;
4530 NTSTATUS status = NT_STATUS_OK;
4532 /* Set a symbolic link. */
4533 /* Don't allow this if follow links is false. */
4535 if (total_data == 0) {
4536 return NT_STATUS_INVALID_PARAMETER;
4539 if (!lp_symlinks(SNUM(conn))) {
4540 return NT_STATUS_ACCESS_DENIED;
4543 srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), link_target, pdata,
4544 sizeof(link_target), total_data, STR_TERMINATE);
4546 /* !widelinks forces the target path to be within the share. */
4547 /* This means we can interpret the target as a pathname. */
4548 if (!lp_widelinks(SNUM(conn))) {
4550 char *last_dirp = NULL;
4552 if (*link_target == '/') {
4553 /* No absolute paths allowed. */
4554 return NT_STATUS_ACCESS_DENIED;
4556 pstrcpy(rel_name, newname);
4557 last_dirp = strrchr_m(rel_name, '/');
4559 last_dirp[1] = '\0';
4561 pstrcpy(rel_name, "./");
4563 pstrcat(rel_name, link_target);
4565 status = check_name(conn, rel_name);
4566 if (!NT_STATUS_IS_OK(status)) {
4571 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4572 newname, link_target ));
4574 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4575 return map_nt_error_from_unix(errno);
4578 return NT_STATUS_OK;
4581 /****************************************************************************
4582 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4583 ****************************************************************************/
4585 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4593 NTSTATUS status = NT_STATUS_OK;
4595 /* Set a hard link. */
4596 if (total_data == 0) {
4597 return NT_STATUS_INVALID_PARAMETER;
4600 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), oldname, pdata,
4601 sizeof(oldname), total_data, STR_TERMINATE, &status);
4602 if (!NT_STATUS_IS_OK(status)) {
4606 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4607 if (!NT_STATUS_IS_OK(status)) {
4611 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4614 return hardlink_internals(conn, oldname, fname);
4617 /****************************************************************************
4618 Deal with SMB_FILE_RENAME_INFORMATION.
4619 ****************************************************************************/
4621 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4622 struct smb_request *req,
4635 BOOL dest_has_wcard = False;
4636 NTSTATUS status = NT_STATUS_OK;
4639 if (total_data < 13) {
4640 return NT_STATUS_INVALID_PARAMETER;
4643 overwrite = (CVAL(pdata,0) ? True : False);
4644 root_fid = IVAL(pdata,4);
4645 len = IVAL(pdata,8);
4647 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4648 return NT_STATUS_INVALID_PARAMETER;
4651 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, &pdata[12],
4652 sizeof(newname), len, 0, &status,
4654 if (!NT_STATUS_IS_OK(status)) {
4658 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4659 if (!NT_STATUS_IS_OK(status)) {
4663 /* Check the new name has no '/' characters. */
4664 if (strchr_m(newname, '/')) {
4665 return NT_STATUS_NOT_SUPPORTED;
4668 /* Create the base directory. */
4669 pstrcpy(base_name, fname);
4670 p = strrchr_m(base_name, '/');
4674 pstrcpy(base_name, "./");
4676 /* Append the new name. */
4677 pstrcat(base_name, newname);
4680 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4681 fsp->fnum, fsp->fsp_name, base_name ));
4682 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4684 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4686 status = rename_internals(conn, req, fname, base_name, 0,
4687 overwrite, False, dest_has_wcard);
4693 /****************************************************************************
4694 Deal with SMB_SET_POSIX_ACL.
4695 ****************************************************************************/
4697 #if defined(HAVE_POSIX_ACLS)
4698 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4703 SMB_STRUCT_STAT *psbuf)
4705 uint16 posix_acl_version;
4706 uint16 num_file_acls;
4707 uint16 num_def_acls;
4708 BOOL valid_file_acls = True;
4709 BOOL valid_def_acls = True;
4711 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4712 return NT_STATUS_INVALID_PARAMETER;
4714 posix_acl_version = SVAL(pdata,0);
4715 num_file_acls = SVAL(pdata,2);
4716 num_def_acls = SVAL(pdata,4);
4718 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4719 valid_file_acls = False;
4723 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4724 valid_def_acls = False;
4728 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4729 return NT_STATUS_INVALID_PARAMETER;
4732 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4733 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4734 return NT_STATUS_INVALID_PARAMETER;
4737 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4738 fname ? fname : fsp->fsp_name,
4739 (unsigned int)num_file_acls,
4740 (unsigned int)num_def_acls));
4742 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4743 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4744 return map_nt_error_from_unix(errno);
4747 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4748 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4749 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4750 return map_nt_error_from_unix(errno);
4752 return NT_STATUS_OK;
4756 /****************************************************************************
4757 Deal with SMB_SET_POSIX_LOCK.
4758 ****************************************************************************/
4760 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4768 SMB_BIG_UINT offset;
4770 BOOL blocking_lock = False;
4771 enum brl_type lock_type;
4772 NTSTATUS status = NT_STATUS_OK;
4774 if (fsp == NULL || fsp->fh->fd == -1) {
4775 return NT_STATUS_INVALID_HANDLE;
4778 if (total_data != POSIX_LOCK_DATA_SIZE) {
4779 return NT_STATUS_INVALID_PARAMETER;
4782 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4783 case POSIX_LOCK_TYPE_READ:
4784 lock_type = READ_LOCK;
4786 case POSIX_LOCK_TYPE_WRITE:
4787 /* Return the right POSIX-mappable error code for files opened read-only. */
4788 if (!fsp->can_write) {
4789 return NT_STATUS_INVALID_HANDLE;
4791 lock_type = WRITE_LOCK;
4793 case POSIX_LOCK_TYPE_UNLOCK:
4794 lock_type = UNLOCK_LOCK;
4797 return NT_STATUS_INVALID_PARAMETER;
4800 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4801 blocking_lock = False;
4802 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4803 blocking_lock = True;
4805 return NT_STATUS_INVALID_PARAMETER;
4808 if (!lp_blocking_locks(SNUM(conn))) {
4809 blocking_lock = False;
4812 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4813 #if defined(HAVE_LONGLONG)
4814 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4815 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4816 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4817 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4818 #else /* HAVE_LONGLONG */
4819 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4820 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4821 #endif /* HAVE_LONGLONG */
4823 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4824 "lock_pid = %u, count = %.0f, offset = %.0f\n",
4826 (unsigned int)lock_type,
4827 (unsigned int)lock_pid,
4831 if (lock_type == UNLOCK_LOCK) {
4832 status = do_unlock(smbd_messaging_context(),
4839 uint32 block_smbpid;
4841 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
4852 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4854 * A blocking lock was requested. Package up
4855 * this smb into a queued request and push it
4856 * onto the blocking lock queue.
4858 if(push_blocking_lock_request(br_lck,
4861 -1, /* infinite timeout. */
4869 TALLOC_FREE(br_lck);
4873 TALLOC_FREE(br_lck);
4879 /****************************************************************************
4880 Deal with SMB_INFO_STANDARD.
4881 ****************************************************************************/
4883 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4888 const SMB_STRUCT_STAT *psbuf)
4890 struct timespec ts[2];
4892 if (total_data < 12) {
4893 return NT_STATUS_INVALID_PARAMETER;
4897 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4899 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4901 DEBUG(10,("smb_set_info_standard: file %s\n",
4902 fname ? fname : fsp->fsp_name ));
4904 return smb_set_file_time(conn,
4911 /****************************************************************************
4912 Deal with SMB_SET_FILE_BASIC_INFO.
4913 ****************************************************************************/
4915 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4920 SMB_STRUCT_STAT *psbuf)
4922 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4923 struct timespec write_time;
4924 struct timespec changed_time;
4926 struct timespec ts[2];
4927 NTSTATUS status = NT_STATUS_OK;
4929 if (total_data < 36) {
4930 return NT_STATUS_INVALID_PARAMETER;
4933 /* Set the attributes */
4934 dosmode = IVAL(pdata,32);
4935 status = smb_set_file_dosmode(conn,
4939 if (!NT_STATUS_IS_OK(status)) {
4943 /* Ignore create time at offset pdata. */
4946 ts[0] = interpret_long_date(pdata+8);
4948 write_time = interpret_long_date(pdata+16);
4949 changed_time = interpret_long_date(pdata+24);
4952 ts[1] = timespec_min(&write_time, &changed_time);
4954 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4958 /* Prefer a defined time to an undefined one. */
4959 if (null_timespec(ts[1])) {
4960 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4963 DEBUG(10,("smb_set_file_basic_info: file %s\n",
4964 fname ? fname : fsp->fsp_name ));
4966 return smb_set_file_time(conn,
4973 /****************************************************************************
4974 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4975 ****************************************************************************/
4977 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4978 struct smb_request *req,
4983 SMB_STRUCT_STAT *psbuf)
4985 SMB_BIG_UINT allocation_size = 0;
4986 NTSTATUS status = NT_STATUS_OK;
4987 files_struct *new_fsp = NULL;
4989 if (!VALID_STAT(*psbuf)) {
4990 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4993 if (total_data < 8) {
4994 return NT_STATUS_INVALID_PARAMETER;
4997 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4998 #ifdef LARGE_SMB_OFF_T
4999 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5000 #else /* LARGE_SMB_OFF_T */
5001 if (IVAL(pdata,4) != 0) {
5002 /* more than 32 bits? */
5003 return NT_STATUS_INVALID_PARAMETER;
5005 #endif /* LARGE_SMB_OFF_T */
5007 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5008 fname, (double)allocation_size ));
5010 if (allocation_size) {
5011 allocation_size = smb_roundup(conn, allocation_size);
5014 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5015 fname, (double)allocation_size ));
5017 if (fsp && fsp->fh->fd != -1) {
5018 /* Open file handle. */
5019 /* Only change if needed. */
5020 if (allocation_size != get_file_size(*psbuf)) {
5021 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5022 return map_nt_error_from_unix(errno);
5025 /* But always update the time. */
5026 if (null_timespec(fsp->pending_modtime)) {
5028 * This is equivalent to a write. Ensure it's seen immediately
5029 * if there are no pending writes.
5031 set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
5033 return NT_STATUS_OK;
5036 /* Pathname or stat or directory file. */
5038 status = open_file_ntcreate(conn, req, fname, psbuf,
5040 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5043 FILE_ATTRIBUTE_NORMAL,
5044 FORCE_OPLOCK_BREAK_TO_NONE,
5047 if (!NT_STATUS_IS_OK(status)) {
5048 /* NB. We check for open_was_deferred in the caller. */
5052 /* Only change if needed. */
5053 if (allocation_size != get_file_size(*psbuf)) {
5054 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5055 status = map_nt_error_from_unix(errno);
5056 close_file(new_fsp,NORMAL_CLOSE);
5061 /* Changing the allocation size should set the last mod time. */
5062 /* Don't need to call set_filetime as this will be flushed on
5065 fsp_set_pending_modtime(new_fsp, timespec_current());
5067 close_file(new_fsp,NORMAL_CLOSE);
5068 return NT_STATUS_OK;
5071 /****************************************************************************
5072 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5073 ****************************************************************************/
5075 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5076 struct smb_request *req,
5081 SMB_STRUCT_STAT *psbuf)
5085 if (total_data < 8) {
5086 return NT_STATUS_INVALID_PARAMETER;
5089 size = IVAL(pdata,0);
5090 #ifdef LARGE_SMB_OFF_T
5091 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5092 #else /* LARGE_SMB_OFF_T */
5093 if (IVAL(pdata,4) != 0) {
5094 /* more than 32 bits? */
5095 return NT_STATUS_INVALID_PARAMETER;
5097 #endif /* LARGE_SMB_OFF_T */
5098 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5099 "file %s to %.0f\n", fname, (double)size ));
5101 return smb_set_file_size(conn, req,
5108 /****************************************************************************
5109 Allow a UNIX info mknod.
5110 ****************************************************************************/
5112 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5116 SMB_STRUCT_STAT *psbuf)
5118 uint32 file_type = IVAL(pdata,56);
5119 #if defined(HAVE_MAKEDEV)
5120 uint32 dev_major = IVAL(pdata,60);
5121 uint32 dev_minor = IVAL(pdata,68);
5123 SMB_DEV_T dev = (SMB_DEV_T)0;
5124 uint32 raw_unixmode = IVAL(pdata,84);
5128 if (total_data < 100) {
5129 return NT_STATUS_INVALID_PARAMETER;
5132 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5133 if (!NT_STATUS_IS_OK(status)) {
5137 #if defined(HAVE_MAKEDEV)
5138 dev = makedev(dev_major, dev_minor);
5141 switch (file_type) {
5142 #if defined(S_IFIFO)
5143 case UNIX_TYPE_FIFO:
5144 unixmode |= S_IFIFO;
5147 #if defined(S_IFSOCK)
5148 case UNIX_TYPE_SOCKET:
5149 unixmode |= S_IFSOCK;
5152 #if defined(S_IFCHR)
5153 case UNIX_TYPE_CHARDEV:
5154 unixmode |= S_IFCHR;
5157 #if defined(S_IFBLK)
5158 case UNIX_TYPE_BLKDEV:
5159 unixmode |= S_IFBLK;
5163 return NT_STATUS_INVALID_PARAMETER;
5166 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5167 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5169 /* Ok - do the mknod. */
5170 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5171 return map_nt_error_from_unix(errno);
5174 /* If any of the other "set" calls fail we
5175 * don't want to end up with a half-constructed mknod.
5178 if (lp_inherit_perms(SNUM(conn))) {
5180 conn, parent_dirname(fname),
5184 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5185 status = map_nt_error_from_unix(errno);
5186 SMB_VFS_UNLINK(conn,fname);
5189 return NT_STATUS_OK;
5192 /****************************************************************************
5193 Deal with SMB_SET_FILE_UNIX_BASIC.
5194 ****************************************************************************/
5196 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5197 struct smb_request *req,
5202 SMB_STRUCT_STAT *psbuf)
5204 struct timespec ts[2];
5205 uint32 raw_unixmode;
5208 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5209 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5210 NTSTATUS status = NT_STATUS_OK;
5211 BOOL delete_on_fail = False;
5212 enum perm_type ptype;
5214 if (total_data < 100) {
5215 return NT_STATUS_INVALID_PARAMETER;
5218 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5219 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5220 size=IVAL(pdata,0); /* first 8 Bytes are size */
5221 #ifdef LARGE_SMB_OFF_T
5222 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5223 #else /* LARGE_SMB_OFF_T */
5224 if (IVAL(pdata,4) != 0) {
5225 /* more than 32 bits? */
5226 return NT_STATUS_INVALID_PARAMETER;
5228 #endif /* LARGE_SMB_OFF_T */
5231 ts[0] = interpret_long_date(pdata+24); /* access_time */
5232 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5233 set_owner = (uid_t)IVAL(pdata,40);
5234 set_grp = (gid_t)IVAL(pdata,48);
5235 raw_unixmode = IVAL(pdata,84);
5237 if (VALID_STAT(*psbuf)) {
5238 if (S_ISDIR(psbuf->st_mode)) {
5239 ptype = PERM_EXISTING_DIR;
5241 ptype = PERM_EXISTING_FILE;
5244 ptype = PERM_NEW_FILE;
5247 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5248 if (!NT_STATUS_IS_OK(status)) {
5252 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5253 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5254 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5256 if (!VALID_STAT(*psbuf)) {
5258 * The only valid use of this is to create character and block
5259 * devices, and named pipes. This is deprecated (IMHO) and
5260 * a new info level should be used for mknod. JRA.
5263 status = smb_unix_mknod(conn,
5268 if (!NT_STATUS_IS_OK(status)) {
5272 /* Ensure we don't try and change anything else. */
5273 raw_unixmode = SMB_MODE_NO_CHANGE;
5274 size = get_file_size(*psbuf);
5275 ts[0] = get_atimespec(psbuf);
5276 ts[1] = get_mtimespec(psbuf);
5278 * We continue here as we might want to change the
5281 delete_on_fail = True;
5285 /* Horrible backwards compatibility hack as an old server bug
5286 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5290 size = get_file_size(*psbuf);
5295 * Deal with the UNIX specific mode set.
5298 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5299 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5300 (unsigned int)unixmode, fname ));
5301 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5302 return map_nt_error_from_unix(errno);
5307 * Deal with the UNIX specific uid set.
5310 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5313 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5314 (unsigned int)set_owner, fname ));
5316 if (S_ISLNK(psbuf->st_mode)) {
5317 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5319 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5323 status = map_nt_error_from_unix(errno);
5324 if (delete_on_fail) {
5325 SMB_VFS_UNLINK(conn,fname);
5332 * Deal with the UNIX specific gid set.
5335 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5336 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5337 (unsigned int)set_owner, fname ));
5338 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5339 status = map_nt_error_from_unix(errno);
5340 if (delete_on_fail) {
5341 SMB_VFS_UNLINK(conn,fname);
5347 /* Deal with any size changes. */
5349 status = smb_set_file_size(conn, req,
5354 if (!NT_STATUS_IS_OK(status)) {
5358 /* Deal with any time changes. */
5360 return smb_set_file_time(conn,
5367 /****************************************************************************
5368 Deal with SMB_SET_FILE_UNIX_INFO2.
5369 ****************************************************************************/
5371 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5372 struct smb_request *req,
5377 SMB_STRUCT_STAT *psbuf)
5383 if (total_data < 116) {
5384 return NT_STATUS_INVALID_PARAMETER;
5387 /* Start by setting all the fields that are common between UNIX_BASIC
5390 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5392 if (!NT_STATUS_IS_OK(status)) {
5396 smb_fflags = IVAL(pdata, 108);
5397 smb_fmask = IVAL(pdata, 112);
5399 /* NB: We should only attempt to alter the file flags if the client
5400 * sends a non-zero mask.
5402 if (smb_fmask != 0) {
5403 int stat_fflags = 0;
5405 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5407 /* Client asked to alter a flag we don't understand. */
5408 return NT_STATUS_INVALID_PARAMETER;
5411 if (fsp && fsp->fh->fd != -1) {
5412 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
5413 return NT_STATUS_NOT_SUPPORTED;
5415 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5416 return map_nt_error_from_unix(errno);
5421 /* XXX: need to add support for changing the create_time here. You
5422 * can do this for paths on Darwin with setattrlist(2). The right way
5423 * to hook this up is probably by extending the VFS utimes interface.
5426 return NT_STATUS_OK;
5429 /****************************************************************************
5430 Create a directory with POSIX semantics.
5431 ****************************************************************************/
5433 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5434 struct smb_request *req,
5438 SMB_STRUCT_STAT *psbuf,
5439 int *pdata_return_size)
5441 NTSTATUS status = NT_STATUS_OK;
5442 uint32 raw_unixmode = 0;
5443 uint32 mod_unixmode = 0;
5444 mode_t unixmode = (mode_t)0;
5445 files_struct *fsp = NULL;
5446 uint16 info_level_return = 0;
5448 char *pdata = *ppdata;
5450 if (total_data < 18) {
5451 return NT_STATUS_INVALID_PARAMETER;
5454 raw_unixmode = IVAL(pdata,8);
5455 /* Next 4 bytes are not yet defined. */
5457 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5458 if (!NT_STATUS_IS_OK(status)) {
5462 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5464 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5465 fname, (unsigned int)unixmode ));
5467 status = open_directory(conn, req,
5470 FILE_READ_ATTRIBUTES, /* Just a stat open */
5471 FILE_SHARE_NONE, /* Ignored for stat opens */
5478 if (NT_STATUS_IS_OK(status)) {
5479 close_file(fsp, NORMAL_CLOSE);
5482 info_level_return = SVAL(pdata,16);
5484 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5485 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5486 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5487 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5489 *pdata_return_size = 12;
5492 /* Realloc the data size */
5493 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5494 if (*ppdata == NULL) {
5495 *pdata_return_size = 0;
5496 return NT_STATUS_NO_MEMORY;
5500 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5501 SSVAL(pdata,2,0); /* No fnum. */
5502 SIVAL(pdata,4,info); /* Was directory created. */
5504 switch (info_level_return) {
5505 case SMB_QUERY_FILE_UNIX_BASIC:
5506 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5507 SSVAL(pdata,10,0); /* Padding. */
5508 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5510 case SMB_QUERY_FILE_UNIX_INFO2:
5511 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5512 SSVAL(pdata,10,0); /* Padding. */
5513 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5516 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5517 SSVAL(pdata,10,0); /* Padding. */
5524 /****************************************************************************
5525 Open/Create a file with POSIX semantics.
5526 ****************************************************************************/
5528 static NTSTATUS smb_posix_open(connection_struct *conn,
5529 struct smb_request *req,
5533 SMB_STRUCT_STAT *psbuf,
5534 int *pdata_return_size)
5536 BOOL extended_oplock_granted = False;
5537 char *pdata = *ppdata;
5539 uint32 wire_open_mode = 0;
5540 uint32 raw_unixmode = 0;
5541 uint32 mod_unixmode = 0;
5542 uint32 create_disp = 0;
5543 uint32 access_mask = 0;
5544 uint32 create_options = 0;
5545 NTSTATUS status = NT_STATUS_OK;
5546 mode_t unixmode = (mode_t)0;
5547 files_struct *fsp = NULL;
5548 int oplock_request = 0;
5550 uint16 info_level_return = 0;
5552 if (total_data < 18) {
5553 return NT_STATUS_INVALID_PARAMETER;
5556 flags = IVAL(pdata,0);
5557 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5558 if (oplock_request) {
5559 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5562 wire_open_mode = IVAL(pdata,4);
5564 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5565 return smb_posix_mkdir(conn, req,
5573 switch (wire_open_mode & SMB_ACCMODE) {
5575 access_mask = FILE_READ_DATA;
5578 access_mask = FILE_WRITE_DATA;
5581 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5584 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5585 (unsigned int)wire_open_mode ));
5586 return NT_STATUS_INVALID_PARAMETER;
5589 wire_open_mode &= ~SMB_ACCMODE;
5591 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5592 create_disp = FILE_CREATE;
5593 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5594 create_disp = FILE_OVERWRITE_IF;
5595 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5596 create_disp = FILE_OPEN_IF;
5598 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5599 (unsigned int)wire_open_mode ));
5600 return NT_STATUS_INVALID_PARAMETER;
5603 raw_unixmode = IVAL(pdata,8);
5604 /* Next 4 bytes are not yet defined. */
5606 status = unix_perms_from_wire(conn,
5609 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5612 if (!NT_STATUS_IS_OK(status)) {
5616 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5618 if (wire_open_mode & SMB_O_SYNC) {
5619 create_options |= FILE_WRITE_THROUGH;
5621 if (wire_open_mode & SMB_O_APPEND) {
5622 access_mask |= FILE_APPEND_DATA;
5624 if (wire_open_mode & SMB_O_DIRECT) {
5625 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5628 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5630 (unsigned int)wire_open_mode,
5631 (unsigned int)unixmode ));
5633 status = open_file_ntcreate(conn, req,
5637 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5639 0, /* no create options yet. */
5645 if (!NT_STATUS_IS_OK(status)) {
5649 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5650 extended_oplock_granted = True;
5653 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5654 extended_oplock_granted = True;
5657 info_level_return = SVAL(pdata,16);
5659 /* Allocate the correct return size. */
5661 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5662 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5663 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
5664 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5666 *pdata_return_size = 12;
5669 /* Realloc the data size */
5670 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5671 if (*ppdata == NULL) {
5672 close_file(fsp,ERROR_CLOSE);
5673 *pdata_return_size = 0;
5674 return NT_STATUS_NO_MEMORY;
5678 if (extended_oplock_granted) {
5679 if (flags & REQUEST_BATCH_OPLOCK) {
5680 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5682 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5684 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5685 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5687 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5690 SSVAL(pdata,2,fsp->fnum);
5691 SIVAL(pdata,4,info); /* Was file created etc. */
5693 switch (info_level_return) {
5694 case SMB_QUERY_FILE_UNIX_BASIC:
5695 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5696 SSVAL(pdata,10,0); /* padding. */
5697 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5699 case SMB_QUERY_FILE_UNIX_INFO2:
5700 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5701 SSVAL(pdata,10,0); /* padding. */
5702 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5705 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5706 SSVAL(pdata,10,0); /* padding. */
5709 return NT_STATUS_OK;
5712 /****************************************************************************
5713 Delete a file with POSIX semantics.
5714 ****************************************************************************/
5716 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5717 struct smb_request *req,
5721 SMB_STRUCT_STAT *psbuf)
5723 NTSTATUS status = NT_STATUS_OK;
5724 files_struct *fsp = NULL;
5728 if (total_data < 2) {
5729 return NT_STATUS_INVALID_PARAMETER;
5732 flags = SVAL(pdata,0);
5734 if (!VALID_STAT(*psbuf)) {
5735 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5738 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5739 !VALID_STAT_OF_DIR(*psbuf)) {
5740 return NT_STATUS_NOT_A_DIRECTORY;
5743 DEBUG(10,("smb_posix_unlink: %s %s\n",
5744 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5747 if (VALID_STAT_OF_DIR(*psbuf)) {
5748 status = open_directory(conn, req,
5752 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5754 FILE_DELETE_ON_CLOSE,
5755 FILE_FLAG_POSIX_SEMANTICS|0777,
5761 status = open_file_ntcreate(conn, req,
5765 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5768 FILE_FLAG_POSIX_SEMANTICS|0777,
5769 0, /* No oplock, but break existing ones. */
5773 * For file opens we must set the delete on close
5777 if (!NT_STATUS_IS_OK(status)) {
5781 status = smb_set_file_disposition_info(conn,
5789 if (!NT_STATUS_IS_OK(status)) {
5792 return close_file(fsp, NORMAL_CLOSE);
5795 /****************************************************************************
5796 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5797 ****************************************************************************/
5799 static int call_trans2setfilepathinfo(connection_struct *conn,
5800 struct smb_request *req,
5801 char *inbuf, char *outbuf, int length,
5803 unsigned int tran_call,
5804 char **pparams, int total_params, char **ppdata, int total_data,
5805 unsigned int max_data_bytes)
5807 char *params = *pparams;
5808 char *pdata = *ppdata;
5810 SMB_STRUCT_STAT sbuf;
5812 files_struct *fsp = NULL;
5813 NTSTATUS status = NT_STATUS_OK;
5814 int data_return_size = 0;
5817 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5822 if (tran_call == TRANSACT2_SETFILEINFO) {
5823 if (total_params < 4) {
5824 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5827 fsp = file_fsp(params,0);
5828 info_level = SVAL(params,2);
5830 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5832 * This is actually a SETFILEINFO on a directory
5833 * handle (returned from an NT SMB). NT5.0 seems
5834 * to do this call. JRA.
5836 pstrcpy(fname, fsp->fsp_name);
5837 if (INFO_LEVEL_IS_UNIX(info_level)) {
5838 /* Always do lstat for UNIX calls. */
5839 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
5840 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
5841 return UNIXERROR(ERRDOS,ERRbadpath);
5844 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5845 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5846 return UNIXERROR(ERRDOS,ERRbadpath);
5849 } else if (fsp && fsp->print_file) {
5851 * Doing a DELETE_ON_CLOSE should cancel a print job.
5853 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5854 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5856 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5859 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5862 return (UNIXERROR(ERRDOS,ERRbadpath));
5865 * Original code - this is an open file.
5867 CHECK_FSP(fsp,conn);
5869 pstrcpy(fname, fsp->fsp_name);
5871 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5872 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5873 return(UNIXERROR(ERRDOS,ERRbadfid));
5878 if (total_params < 7) {
5879 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5882 info_level = SVAL(params,0);
5883 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, ¶ms[6],
5884 sizeof(fname), total_params - 6, STR_TERMINATE,
5886 if (!NT_STATUS_IS_OK(status)) {
5887 return ERROR_NT(status);
5890 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5891 if (!NT_STATUS_IS_OK(status)) {
5892 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5893 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5895 return ERROR_NT(status);
5898 status = unix_convert(conn, fname, False, NULL, &sbuf);
5899 if (!NT_STATUS_IS_OK(status)) {
5900 return ERROR_NT(status);
5903 status = check_name(conn, fname);
5904 if (!NT_STATUS_IS_OK(status)) {
5905 return ERROR_NT(status);
5908 if (INFO_LEVEL_IS_UNIX(info_level)) {
5910 * For CIFS UNIX extensions the target name may not exist.
5913 /* Always do lstat for UNIX calls. */
5914 SMB_VFS_LSTAT(conn,fname,&sbuf);
5916 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
5917 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
5918 return UNIXERROR(ERRDOS,ERRbadpath);
5922 if (!CAN_WRITE(conn)) {
5923 return ERROR_DOS(ERRSRV,ERRaccess);
5926 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5927 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5930 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5931 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5933 /* Realloc the parameter size */
5934 *pparams = (char *)SMB_REALLOC(*pparams,2);
5935 if (*pparams == NULL) {
5936 return ERROR_NT(NT_STATUS_NO_MEMORY);
5942 if (fsp && !null_timespec(fsp->pending_modtime)) {
5943 /* the pending modtime overrides the current modtime */
5944 set_mtimespec(&sbuf, fsp->pending_modtime);
5947 switch (info_level) {
5949 case SMB_INFO_STANDARD:
5951 status = smb_set_info_standard(conn,
5960 case SMB_INFO_SET_EA:
5962 status = smb_info_set_ea(conn,
5970 case SMB_SET_FILE_BASIC_INFO:
5971 case SMB_FILE_BASIC_INFORMATION:
5973 status = smb_set_file_basic_info(conn,
5982 case SMB_FILE_ALLOCATION_INFORMATION:
5983 case SMB_SET_FILE_ALLOCATION_INFO:
5985 status = smb_set_file_allocation_info(conn, req,
5994 case SMB_FILE_END_OF_FILE_INFORMATION:
5995 case SMB_SET_FILE_END_OF_FILE_INFO:
5997 status = smb_set_file_end_of_file_info(conn, req,
6006 case SMB_FILE_DISPOSITION_INFORMATION:
6007 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6010 /* JRA - We used to just ignore this on a path ?
6011 * Shouldn't this be invalid level on a pathname
6014 if (tran_call != TRANSACT2_SETFILEINFO) {
6015 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6018 status = smb_set_file_disposition_info(conn,
6027 case SMB_FILE_POSITION_INFORMATION:
6029 status = smb_file_position_information(conn,
6036 /* From tridge Samba4 :
6037 * MODE_INFORMATION in setfileinfo (I have no
6038 * idea what "mode information" on a file is - it takes a value of 0,
6039 * 2, 4 or 6. What could it be?).
6042 case SMB_FILE_MODE_INFORMATION:
6044 status = smb_file_mode_information(conn,
6051 * CIFS UNIX extensions.
6054 case SMB_SET_FILE_UNIX_BASIC:
6056 status = smb_set_file_unix_basic(conn, req,
6065 case SMB_SET_FILE_UNIX_INFO2:
6067 status = smb_set_file_unix_info2(conn, req,
6076 case SMB_SET_FILE_UNIX_LINK:
6078 if (tran_call != TRANSACT2_SETPATHINFO) {
6079 /* We must have a pathname for this. */
6080 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6082 status = smb_set_file_unix_link(conn,
6090 case SMB_SET_FILE_UNIX_HLINK:
6092 if (tran_call != TRANSACT2_SETPATHINFO) {
6093 /* We must have a pathname for this. */
6094 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6096 status = smb_set_file_unix_hlink(conn,
6105 case SMB_FILE_RENAME_INFORMATION:
6107 status = smb_file_rename_information(conn, req,
6117 #if defined(HAVE_POSIX_ACLS)
6118 case SMB_SET_POSIX_ACL:
6120 status = smb_set_posix_acl(conn,
6130 case SMB_SET_POSIX_LOCK:
6132 if (tran_call != TRANSACT2_SETFILEINFO) {
6133 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6135 status = smb_set_posix_lock(conn,
6144 case SMB_POSIX_PATH_OPEN:
6146 if (tran_call != TRANSACT2_SETPATHINFO) {
6147 /* We must have a pathname for this. */
6148 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6151 status = smb_posix_open(conn, req,
6160 case SMB_POSIX_PATH_UNLINK:
6162 if (tran_call != TRANSACT2_SETPATHINFO) {
6163 /* We must have a pathname for this. */
6164 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6167 status = smb_posix_unlink(conn, req,
6176 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6180 if (!NT_STATUS_IS_OK(status)) {
6181 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6182 /* We have re-scheduled this call. */
6185 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6186 /* We have re-scheduled this call. */
6189 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6190 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6192 return ERROR_NT(status);
6196 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6201 /****************************************************************************
6202 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6203 ****************************************************************************/
6205 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6206 char **pparams, int total_params, char **ppdata, int total_data,
6207 unsigned int max_data_bytes)
6209 char *params = *pparams;
6210 char *pdata = *ppdata;
6212 SMB_STRUCT_STAT sbuf;
6213 NTSTATUS status = NT_STATUS_OK;
6214 struct ea_list *ea_list = NULL;
6216 if (!CAN_WRITE(conn))
6217 return ERROR_DOS(ERRSRV,ERRaccess);
6219 if (total_params < 5) {
6220 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6223 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory, ¶ms[4],
6224 sizeof(directory), total_params - 4, STR_TERMINATE,
6226 if (!NT_STATUS_IS_OK(status)) {
6227 return ERROR_NT(status);
6230 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6232 status = unix_convert(conn, directory, False, NULL, &sbuf);
6233 if (!NT_STATUS_IS_OK(status)) {
6234 return ERROR_NT(status);
6237 status = check_name(conn, directory);
6238 if (!NT_STATUS_IS_OK(status)) {
6239 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6240 return ERROR_NT(status);
6243 /* Any data in this call is an EA list. */
6244 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6245 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6249 * OS/2 workplace shell seems to send SET_EA requests of "null"
6250 * length (4 bytes containing IVAL 4).
6251 * They seem to have no effect. Bug #3212. JRA.
6254 if (total_data != 4) {
6255 if (total_data < 10) {
6256 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6259 if (IVAL(pdata,0) > total_data) {
6260 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6261 IVAL(pdata,0), (unsigned int)total_data));
6262 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6265 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6268 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6270 } else if (IVAL(pdata,0) != 4) {
6271 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6274 status = create_directory(conn, directory);
6276 if (!NT_STATUS_IS_OK(status)) {
6277 return ERROR_NT(status);
6280 /* Try and set any given EA. */
6282 status = set_ea(conn, NULL, directory, ea_list);
6283 if (!NT_STATUS_IS_OK(status)) {
6284 return ERROR_NT(status);
6288 /* Realloc the parameter and data sizes */
6289 *pparams = (char *)SMB_REALLOC(*pparams,2);
6290 if(*pparams == NULL) {
6291 return ERROR_NT(NT_STATUS_NO_MEMORY);
6297 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6302 /****************************************************************************
6303 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6304 We don't actually do this - we just send a null response.
6305 ****************************************************************************/
6307 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6308 char **pparams, int total_params, char **ppdata, int total_data,
6309 unsigned int max_data_bytes)
6311 static uint16 fnf_handle = 257;
6312 char *params = *pparams;
6315 if (total_params < 6) {
6316 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6319 info_level = SVAL(params,4);
6320 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6322 switch (info_level) {
6327 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6330 /* Realloc the parameter and data sizes */
6331 *pparams = (char *)SMB_REALLOC(*pparams,6);
6332 if (*pparams == NULL) {
6333 return ERROR_NT(NT_STATUS_NO_MEMORY);
6337 SSVAL(params,0,fnf_handle);
6338 SSVAL(params,2,0); /* No changes */
6339 SSVAL(params,4,0); /* No EA errors */
6346 send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6351 /****************************************************************************
6352 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
6353 changes). Currently this does nothing.
6354 ****************************************************************************/
6356 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6357 char **pparams, int total_params, char **ppdata, int total_data,
6358 unsigned int max_data_bytes)
6360 char *params = *pparams;
6362 DEBUG(3,("call_trans2findnotifynext\n"));
6364 /* Realloc the parameter and data sizes */
6365 *pparams = (char *)SMB_REALLOC(*pparams,4);
6366 if (*pparams == NULL) {
6367 return ERROR_NT(NT_STATUS_NO_MEMORY);
6371 SSVAL(params,0,0); /* No changes */
6372 SSVAL(params,2,0); /* No EA errors */
6374 send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6379 /****************************************************************************
6380 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6381 ****************************************************************************/
6383 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6384 char **pparams, int total_params, char **ppdata, int total_data,
6385 unsigned int max_data_bytes)
6387 char *params = *pparams;
6390 int max_referral_level;
6391 NTSTATUS status = NT_STATUS_OK;
6393 DEBUG(10,("call_trans2getdfsreferral\n"));
6395 if (total_params < 3) {
6396 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6399 max_referral_level = SVAL(params,0);
6401 if(!lp_host_msdfs())
6402 return ERROR_DOS(ERRDOS,ERRbadfunc);
6404 srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), pathname, ¶ms[2],
6405 sizeof(pathname), total_params - 2, STR_TERMINATE);
6406 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6407 return ERROR_NT(status);
6409 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6410 send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6415 #define LMCAT_SPL 0x53
6416 #define LMFUNC_GETJOBID 0x60
6418 /****************************************************************************
6419 Reply to a TRANS2_IOCTL - used for OS/2 printing.
6420 ****************************************************************************/
6422 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6423 char **pparams, int total_params, char **ppdata, int total_data,
6424 unsigned int max_data_bytes)
6426 char *pdata = *ppdata;
6427 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6429 /* check for an invalid fid before proceeding */
6432 return(ERROR_DOS(ERRDOS,ERRbadfid));
6434 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6435 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6436 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6437 if (*ppdata == NULL) {
6438 return ERROR_NT(NT_STATUS_NO_MEMORY);
6442 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6443 CAN ACCEPT THIS IN UNICODE. JRA. */
6445 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
6446 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6447 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6448 send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6451 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6452 return ERROR_DOS(ERRSRV,ERRerror);
6456 /****************************************************************************
6457 Reply to a SMBfindclose (stop trans2 directory search).
6458 ****************************************************************************/
6460 int reply_findclose(connection_struct *conn,
6461 char *inbuf,char *outbuf,int length,int bufsize)
6464 int dptr_num=SVALS(inbuf,smb_vwv0);
6465 START_PROFILE(SMBfindclose);
6467 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6469 dptr_close(&dptr_num);
6471 outsize = set_message(inbuf, outbuf,0,0,False);
6473 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6475 END_PROFILE(SMBfindclose);
6479 /****************************************************************************
6480 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6481 ****************************************************************************/
6483 int reply_findnclose(connection_struct *conn,
6484 char *inbuf,char *outbuf,int length,int bufsize)
6488 START_PROFILE(SMBfindnclose);
6490 dptr_num = SVAL(inbuf,smb_vwv0);
6492 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6494 /* We never give out valid handles for a
6495 findnotifyfirst - so any dptr_num is ok here.
6498 outsize = set_message(inbuf, outbuf,0,0,False);
6500 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6502 END_PROFILE(SMBfindnclose);
6506 static int handle_trans2(connection_struct *conn, struct smb_request *req,
6507 struct trans_state *state,
6508 char *inbuf, char *outbuf, int size, int bufsize)
6512 if (Protocol >= PROTOCOL_NT1) {
6513 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6516 /* Now we must call the relevant TRANS2 function */
6517 switch(state->call) {
6518 case TRANSACT2_OPEN:
6520 START_PROFILE(Trans2_open);
6521 outsize = call_trans2open(
6522 conn, req, inbuf, outbuf, bufsize,
6523 &state->param, state->total_param,
6524 &state->data, state->total_data,
6525 state->max_data_return);
6526 END_PROFILE(Trans2_open);
6530 case TRANSACT2_FINDFIRST:
6532 START_PROFILE(Trans2_findfirst);
6533 outsize = call_trans2findfirst(
6534 conn, inbuf, outbuf, bufsize,
6535 &state->param, state->total_param,
6536 &state->data, state->total_data,
6537 state->max_data_return);
6538 END_PROFILE(Trans2_findfirst);
6542 case TRANSACT2_FINDNEXT:
6544 START_PROFILE(Trans2_findnext);
6545 outsize = call_trans2findnext(
6546 conn, inbuf, outbuf, size, bufsize,
6547 &state->param, state->total_param,
6548 &state->data, state->total_data,
6549 state->max_data_return);
6550 END_PROFILE(Trans2_findnext);
6554 case TRANSACT2_QFSINFO:
6556 START_PROFILE(Trans2_qfsinfo);
6557 outsize = call_trans2qfsinfo(
6558 conn, inbuf, outbuf, size, bufsize,
6559 &state->param, state->total_param,
6560 &state->data, state->total_data,
6561 state->max_data_return);
6562 END_PROFILE(Trans2_qfsinfo);
6566 case TRANSACT2_SETFSINFO:
6568 START_PROFILE(Trans2_setfsinfo);
6569 outsize = call_trans2setfsinfo(
6570 conn, inbuf, outbuf, size, bufsize,
6571 &state->param, state->total_param,
6572 &state->data, state->total_data,
6573 state->max_data_return);
6574 END_PROFILE(Trans2_setfsinfo);
6578 case TRANSACT2_QPATHINFO:
6579 case TRANSACT2_QFILEINFO:
6581 START_PROFILE(Trans2_qpathinfo);
6582 outsize = call_trans2qfilepathinfo(
6583 conn, inbuf, outbuf, size, bufsize, state->call,
6584 &state->param, state->total_param,
6585 &state->data, state->total_data,
6586 state->max_data_return);
6587 END_PROFILE(Trans2_qpathinfo);
6591 case TRANSACT2_SETPATHINFO:
6592 case TRANSACT2_SETFILEINFO:
6594 START_PROFILE(Trans2_setpathinfo);
6595 outsize = call_trans2setfilepathinfo(
6596 conn, req, inbuf, outbuf, size, bufsize, state->call,
6597 &state->param, state->total_param,
6598 &state->data, state->total_data,
6599 state->max_data_return);
6600 END_PROFILE(Trans2_setpathinfo);
6604 case TRANSACT2_FINDNOTIFYFIRST:
6606 START_PROFILE(Trans2_findnotifyfirst);
6607 outsize = call_trans2findnotifyfirst(
6608 conn, inbuf, outbuf, size, bufsize,
6609 &state->param, state->total_param,
6610 &state->data, state->total_data,
6611 state->max_data_return);
6612 END_PROFILE(Trans2_findnotifyfirst);
6616 case TRANSACT2_FINDNOTIFYNEXT:
6618 START_PROFILE(Trans2_findnotifynext);
6619 outsize = call_trans2findnotifynext(
6620 conn, inbuf, outbuf, size, bufsize,
6621 &state->param, state->total_param,
6622 &state->data, state->total_data,
6623 state->max_data_return);
6624 END_PROFILE(Trans2_findnotifynext);
6628 case TRANSACT2_MKDIR:
6630 START_PROFILE(Trans2_mkdir);
6631 outsize = call_trans2mkdir(
6632 conn, inbuf, outbuf, size, bufsize,
6633 &state->param, state->total_param,
6634 &state->data, state->total_data,
6635 state->max_data_return);
6636 END_PROFILE(Trans2_mkdir);
6640 case TRANSACT2_GET_DFS_REFERRAL:
6642 START_PROFILE(Trans2_get_dfs_referral);
6643 outsize = call_trans2getdfsreferral(
6644 conn, inbuf, outbuf, size, bufsize,
6645 &state->param, state->total_param,
6646 &state->data, state->total_data,
6647 state->max_data_return);
6648 END_PROFILE(Trans2_get_dfs_referral);
6652 case TRANSACT2_IOCTL:
6654 START_PROFILE(Trans2_ioctl);
6655 outsize = call_trans2ioctl(
6656 conn, inbuf, outbuf, size, bufsize,
6657 &state->param, state->total_param,
6658 &state->data, state->total_data,
6659 state->max_data_return);
6660 END_PROFILE(Trans2_ioctl);
6665 /* Error in request */
6666 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6667 outsize = ERROR_DOS(ERRSRV,ERRerror);
6673 /****************************************************************************
6674 Reply to a SMBtrans2.
6675 ****************************************************************************/
6677 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6678 int size, int bufsize)
6681 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6682 unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6683 unsigned int psoff = SVAL(inbuf, smb_psoff);
6684 unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6685 unsigned int tran_call = SVAL(inbuf, smb_setup0);
6686 struct trans_state *state;
6689 START_PROFILE(SMBtrans2);
6691 result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6692 if (!NT_STATUS_IS_OK(result)) {
6693 DEBUG(2, ("Got invalid trans2 request: %s\n",
6694 nt_errstr(result)));
6695 END_PROFILE(SMBtrans2);
6696 return ERROR_NT(result);
6699 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6700 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
6701 && (tran_call != TRANSACT2_QFILEINFO)) {
6702 END_PROFILE(SMBtrans2);
6703 return ERROR_DOS(ERRSRV,ERRaccess);
6706 if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6707 DEBUG(0, ("talloc failed\n"));
6708 END_PROFILE(SMBtrans2);
6709 return ERROR_NT(NT_STATUS_NO_MEMORY);
6712 state->cmd = SMBtrans2;
6714 state->mid = SVAL(inbuf, smb_mid);
6715 state->vuid = SVAL(inbuf, smb_uid);
6716 state->setup_count = SVAL(inbuf, smb_suwcnt);
6717 state->setup = NULL;
6718 state->total_param = SVAL(inbuf, smb_tpscnt);
6719 state->param = NULL;
6720 state->total_data = SVAL(inbuf, smb_tdscnt);
6722 state->max_param_return = SVAL(inbuf, smb_mprcnt);
6723 state->max_data_return = SVAL(inbuf, smb_mdrcnt);
6724 state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6725 state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6726 state->one_way = BITSETW(inbuf+smb_vwv5,1);
6728 state->call = tran_call;
6730 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6731 is so as a sanity check */
6732 if (state->setup_count != 1) {
6734 * Need to have rc=0 for ioctl to get job id for OS/2.
6735 * Network printing will fail if function is not successful.
6736 * Similar function in reply.c will be used if protocol
6737 * is LANMAN1.0 instead of LM1.2X002.
6738 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
6739 * outbuf doesn't have to be set(only job id is used).
6741 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6742 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6743 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6744 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6746 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6747 DEBUG(2,("Transaction is %d\n",tran_call));
6749 END_PROFILE(SMBtrans2);
6750 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6754 if ((dscnt > state->total_data) || (pscnt > state->total_param))
6757 if (state->total_data) {
6758 /* Can't use talloc here, the core routines do realloc on the
6759 * params and data. */
6760 state->data = (char *)SMB_MALLOC(state->total_data);
6761 if (state->data == NULL) {
6762 DEBUG(0,("reply_trans2: data malloc fail for %u "
6763 "bytes !\n", (unsigned int)state->total_data));
6765 END_PROFILE(SMBtrans2);
6766 return(ERROR_DOS(ERRDOS,ERRnomem));
6768 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6770 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6771 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6774 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6777 if (state->total_param) {
6778 /* Can't use talloc here, the core routines do realloc on the
6779 * params and data. */
6780 state->param = (char *)SMB_MALLOC(state->total_param);
6781 if (state->param == NULL) {
6782 DEBUG(0,("reply_trans: param malloc fail for %u "
6783 "bytes !\n", (unsigned int)state->total_param));
6784 SAFE_FREE(state->data);
6786 END_PROFILE(SMBtrans2);
6787 return(ERROR_DOS(ERRDOS,ERRnomem));
6789 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6791 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6792 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6795 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6798 state->received_data = dscnt;
6799 state->received_param = pscnt;
6801 if ((state->received_param == state->total_param) &&
6802 (state->received_data == state->total_data)) {
6804 struct smb_request req;
6805 init_smb_request(&req, (uint8 *)inbuf);
6807 outsize = handle_trans2(conn, &req, state, inbuf, outbuf,
6809 SAFE_FREE(state->data);
6810 SAFE_FREE(state->param);
6812 END_PROFILE(SMBtrans2);
6816 DLIST_ADD(conn->pending_trans, state);
6818 /* We need to send an interim response then receive the rest
6819 of the parameter/data bytes */
6820 outsize = set_message(inbuf, outbuf,0,0,False);
6822 END_PROFILE(SMBtrans2);
6827 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6828 SAFE_FREE(state->data);
6829 SAFE_FREE(state->param);
6831 END_PROFILE(SMBtrans2);
6832 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6836 /****************************************************************************
6837 Reply to a SMBtranss2
6838 ****************************************************************************/
6840 int reply_transs2(connection_struct *conn,
6841 char *inbuf,char *outbuf,int size,int bufsize)
6844 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6845 struct trans_state *state;
6846 struct smb_request req;
6848 START_PROFILE(SMBtranss2);
6852 for (state = conn->pending_trans; state != NULL;
6853 state = state->next) {
6854 if (state->mid == SVAL(inbuf,smb_mid)) {
6859 if ((state == NULL) || (state->cmd != SMBtrans2)) {
6860 END_PROFILE(SMBtranss2);
6861 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6864 /* Revise state->total_param and state->total_data in case they have
6865 changed downwards */
6867 if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6868 state->total_param = SVAL(inbuf, smb_tpscnt);
6869 if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6870 state->total_data = SVAL(inbuf, smb_tdscnt);
6872 pcnt = SVAL(inbuf, smb_spscnt);
6873 poff = SVAL(inbuf, smb_spsoff);
6874 pdisp = SVAL(inbuf, smb_spsdisp);
6876 dcnt = SVAL(inbuf, smb_sdscnt);
6877 doff = SVAL(inbuf, smb_sdsoff);
6878 ddisp = SVAL(inbuf, smb_sdsdisp);
6880 state->received_param += pcnt;
6881 state->received_data += dcnt;
6883 if ((state->received_data > state->total_data) ||
6884 (state->received_param > state->total_param))
6888 if (pdisp+pcnt > state->total_param)
6890 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6892 if (pdisp > state->total_param)
6894 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6895 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6897 if (state->param + pdisp < state->param)
6900 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6905 if (ddisp+dcnt > state->total_data)
6907 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6909 if (ddisp > state->total_data)
6911 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6912 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6914 if (state->data + ddisp < state->data)
6917 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6921 if ((state->received_param < state->total_param) ||
6922 (state->received_data < state->total_data)) {
6923 END_PROFILE(SMBtranss2);
6927 /* construct_reply_common has done us the favor to pre-fill the
6928 * command field with SMBtranss2 which is wrong :-)
6930 SCVAL(outbuf,smb_com,SMBtrans2);
6932 init_smb_request(&req, (uint8 *)inbuf);
6934 outsize = handle_trans2(conn, &req, state, inbuf, outbuf, size,
6937 DLIST_REMOVE(conn->pending_trans, state);
6938 SAFE_FREE(state->data);
6939 SAFE_FREE(state->param);
6943 END_PROFILE(SMBtranss2);
6944 return(ERROR_DOS(ERRSRV,ERRnosupport));
6947 END_PROFILE(SMBtranss2);
6952 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6953 DLIST_REMOVE(conn->pending_trans, state);
6954 SAFE_FREE(state->data);
6955 SAFE_FREE(state->param);
6957 END_PROFILE(SMBtranss2);
6958 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);