2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2003
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005
8 Extensively modified by Andrew Tridgell, 1995
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 extern enum protocol_types Protocol;
29 extern int smb_read_error;
30 extern uint32 global_client_caps;
31 extern struct current_user current_user;
33 #define get_file_size(sbuf) ((sbuf).st_size)
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
36 /********************************************************************
37 Roundup a value to the nearest allocation roundup size boundary.
38 Only do this for Windows clients.
39 ********************************************************************/
41 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
43 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
45 /* Only roundup for Windows clients. */
46 enum remote_arch_types ra_type = get_remote_arch();
47 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
48 val = SMB_ROUNDUP(val,rval);
53 /********************************************************************
54 Given a stat buffer return the allocated size on disk, taking into
56 ********************************************************************/
58 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
62 if(S_ISDIR(sbuf->st_mode)) {
66 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
67 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
69 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
72 if (fsp && fsp->initial_allocation_size)
73 ret = MAX(ret,fsp->initial_allocation_size);
75 return smb_roundup(conn, ret);
78 /****************************************************************************
79 Utility functions for dealing with extended attributes.
80 ****************************************************************************/
82 static const char *prohibited_ea_names[] = {
83 SAMBA_POSIX_INHERITANCE_EA_NAME,
84 SAMBA_XATTR_DOS_ATTRIB,
88 /****************************************************************************
89 Refuse to allow clients to overwrite our private xattrs.
90 ****************************************************************************/
92 static BOOL samba_private_attr_name(const char *unix_ea_name)
96 for (i = 0; prohibited_ea_names[i]; i++) {
97 if (strequal( prohibited_ea_names[i], unix_ea_name))
103 /****************************************************************************
104 Get one EA value. Fill in a struct ea_struct.
105 ****************************************************************************/
107 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
108 const char *fname, char *ea_name, struct ea_struct *pea)
110 /* Get the value of this xattr. Max size is 64k. */
111 size_t attr_size = 256;
117 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
122 if (fsp && fsp->fh->fd != -1) {
123 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
125 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
128 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
137 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
138 dump_data(10, val, sizeret);
141 if (strnequal(ea_name, "user.", 5)) {
142 pea->name = &ea_name[5];
146 pea->value.data = (unsigned char *)val;
147 pea->value.length = (size_t)sizeret;
151 /****************************************************************************
152 Return a linked list of the total EA's. Plus the total size
153 ****************************************************************************/
155 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
156 const char *fname, size_t *pea_total_len)
158 /* Get a list of all xattrs. Max namesize is 64k. */
159 size_t ea_namelist_size = 1024;
164 struct ea_list *ea_list_head = NULL;
168 if (!lp_ea_support(SNUM(conn))) {
172 for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
173 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
174 if (fsp && fsp->fh->fd != -1) {
175 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
177 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
180 if (sizeret == -1 && errno == ERANGE) {
181 ea_namelist_size *= 2;
190 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
193 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
194 struct ea_list *listp, *tmp;
196 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
199 listp = TALLOC_P(mem_ctx, struct ea_list);
203 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
209 push_ascii_fstring(dos_ea_name, listp->ea.name);
210 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
211 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
212 (unsigned int)*pea_total_len, dos_ea_name,
213 (unsigned int)listp->ea.value.length ));
215 DLIST_ADD_END(ea_list_head, listp, tmp);
217 /* Add on 4 for total length. */
218 if (*pea_total_len) {
223 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
227 /****************************************************************************
228 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
230 ****************************************************************************/
232 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
233 connection_struct *conn, struct ea_list *ea_list)
235 unsigned int ret_data_size = 4;
238 SMB_ASSERT(total_data_size >= 4);
240 if (!lp_ea_support(SNUM(conn))) {
245 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
248 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
249 dos_namelen = strlen(dos_ea_name);
250 if (dos_namelen > 255 || dos_namelen == 0) {
253 if (ea_list->ea.value.length > 65535) {
256 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
260 /* We know we have room. */
261 SCVAL(p,0,ea_list->ea.flags);
262 SCVAL(p,1,dos_namelen);
263 SSVAL(p,2,ea_list->ea.value.length);
264 fstrcpy(p+4, dos_ea_name);
265 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
267 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
268 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
271 ret_data_size = PTR_DIFF(p, pdata);
272 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
273 SIVAL(pdata,0,ret_data_size);
274 return ret_data_size;
277 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
279 size_t total_ea_len = 0;
280 TALLOC_CTX *mem_ctx = NULL;
282 if (!lp_ea_support(SNUM(conn))) {
285 mem_ctx = talloc_init("estimate_ea_size");
286 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
287 talloc_destroy(mem_ctx);
291 /****************************************************************************
292 Ensure the EA name is case insensitive by matching any existing EA name.
293 ****************************************************************************/
295 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
298 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
299 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
301 for (; ea_list; ea_list = ea_list->next) {
302 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
303 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
304 &unix_ea_name[5], ea_list->ea.name));
305 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
309 talloc_destroy(mem_ctx);
312 /****************************************************************************
313 Set or delete an extended attribute.
314 ****************************************************************************/
316 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
318 if (!lp_ea_support(SNUM(conn))) {
319 return NT_STATUS_EAS_NOT_SUPPORTED;
322 for (;ea_list; ea_list = ea_list->next) {
324 fstring unix_ea_name;
326 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
327 fstrcat(unix_ea_name, ea_list->ea.name);
329 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
331 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
333 if (samba_private_attr_name(unix_ea_name)) {
334 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
335 return NT_STATUS_ACCESS_DENIED;
338 if (ea_list->ea.value.length == 0) {
339 /* Remove the attribute. */
340 if (fsp && (fsp->fh->fd != -1)) {
341 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
342 unix_ea_name, fsp->fsp_name));
343 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
345 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
346 unix_ea_name, fname));
347 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
350 /* Removing a non existent attribute always succeeds. */
351 if (ret == -1 && errno == ENOATTR) {
352 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
358 if (fsp && (fsp->fh->fd != -1)) {
359 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
360 unix_ea_name, fsp->fsp_name));
361 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
362 ea_list->ea.value.data, ea_list->ea.value.length, 0);
364 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
365 unix_ea_name, fname));
366 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
367 ea_list->ea.value.data, ea_list->ea.value.length, 0);
373 if (errno == ENOTSUP) {
374 return NT_STATUS_EAS_NOT_SUPPORTED;
377 return map_nt_error_from_unix(errno);
383 /****************************************************************************
384 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
385 ****************************************************************************/
387 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
389 struct ea_list *ea_list_head = NULL;
392 while (offset + 2 < data_size) {
394 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
395 unsigned int namelen = CVAL(pdata,offset);
397 offset++; /* Go past the namelen byte. */
399 /* integer wrap paranioa. */
400 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
401 (offset > data_size) || (namelen > data_size) ||
402 (offset + namelen >= data_size)) {
405 /* Ensure the name is null terminated. */
406 if (pdata[offset + namelen] != '\0') {
409 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
414 offset += (namelen + 1); /* Go past the name + terminating zero. */
415 DLIST_ADD_END(ea_list_head, eal, tmp);
416 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
422 /****************************************************************************
423 Read one EA list entry from the buffer.
424 ****************************************************************************/
426 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
428 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
430 unsigned int namelen;
440 eal->ea.flags = CVAL(pdata,0);
441 namelen = CVAL(pdata,1);
442 val_len = SVAL(pdata,2);
444 if (4 + namelen + 1 + val_len > data_size) {
448 /* Ensure the name is null terminated. */
449 if (pdata[namelen + 4] != '\0') {
452 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
457 eal->ea.value = data_blob(NULL, (size_t)val_len + 1);
458 if (!eal->ea.value.data) {
462 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
464 /* Ensure we're null terminated just in case we print the value. */
465 eal->ea.value.data[val_len] = '\0';
466 /* But don't count the null. */
467 eal->ea.value.length--;
470 *pbytes_used = 4 + namelen + 1 + val_len;
473 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
474 dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
479 /****************************************************************************
480 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
481 ****************************************************************************/
483 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
485 struct ea_list *ea_list_head = NULL;
487 size_t bytes_used = 0;
489 while (offset < data_size) {
491 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
497 DLIST_ADD_END(ea_list_head, eal, tmp);
498 offset += bytes_used;
504 /****************************************************************************
505 Count the total EA size needed.
506 ****************************************************************************/
508 static size_t ea_list_size(struct ea_list *ealist)
511 struct ea_list *listp;
514 for (listp = ealist; listp; listp = listp->next) {
515 push_ascii_fstring(dos_ea_name, listp->ea.name);
516 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
518 /* Add on 4 for total length. */
526 /****************************************************************************
527 Return a union of EA's from a file list and a list of names.
528 The TALLOC context for the two lists *MUST* be identical as we steal
529 memory from one list to add to another. JRA.
530 ****************************************************************************/
532 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
534 struct ea_list *nlistp, *flistp;
536 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
537 for (flistp = file_list; flistp; flistp = flistp->next) {
538 if (strequal(nlistp->ea.name, flistp->ea.name)) {
544 /* Copy the data from this entry. */
545 nlistp->ea.flags = flistp->ea.flags;
546 nlistp->ea.value = flistp->ea.value;
549 nlistp->ea.flags = 0;
550 ZERO_STRUCT(nlistp->ea.value);
554 *total_ea_len = ea_list_size(name_list);
558 /****************************************************************************
559 Send the required number of replies back.
560 We assume all fields other than the data fields are
561 set correctly for the type of call.
562 HACK ! Always assumes smb_setup field is zero.
563 ****************************************************************************/
565 static int send_trans2_replies(char *outbuf,
572 /* As we are using a protocol > LANMAN1 then the max_send
573 variable must have been set in the sessetupX call.
574 This takes precedence over the max_xmit field in the
575 global struct. These different max_xmit variables should
576 be merged as this is now too confusing */
578 int data_to_send = datasize;
579 int params_to_send = paramsize;
583 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
584 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
585 int data_alignment_offset = 0;
587 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
589 set_message(outbuf,10,0,True);
591 /* If there genuinely are no parameters or data to send just send the empty packet */
593 if(params_to_send == 0 && data_to_send == 0) {
595 if (!send_smb(smbd_server_fd(),outbuf))
596 exit_server("send_trans2_replies: send_smb failed.");
600 /* When sending params and data ensure that both are nicely aligned */
601 /* Only do this alignment when there is also data to send - else
602 can cause NT redirector problems. */
604 if (((params_to_send % 4) != 0) && (data_to_send != 0))
605 data_alignment_offset = 4 - (params_to_send % 4);
607 /* Space is bufsize minus Netbios over TCP header minus SMB header */
608 /* The alignment_offset is to align the param bytes on an even byte
609 boundary. NT 4.0 Beta needs this to work correctly. */
611 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
613 /* useable_space can never be more than max_send minus the alignment offset. */
615 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
617 while (params_to_send || data_to_send) {
618 /* Calculate whether we will totally or partially fill this packet */
620 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
622 /* We can never send more than useable_space */
624 * Note that 'useable_space' does not include the alignment offsets,
625 * but we must include the alignment offsets in the calculation of
626 * the length of the data we send over the wire, as the alignment offsets
627 * are sent here. Fix from Marc_Jacobsen@hp.com.
630 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
632 set_message(outbuf, 10, total_sent_thistime, True);
634 /* Set total params and data to be sent */
635 SSVAL(outbuf,smb_tprcnt,paramsize);
636 SSVAL(outbuf,smb_tdrcnt,datasize);
638 /* Calculate how many parameters and data we can fit into
639 * this packet. Parameters get precedence
642 params_sent_thistime = MIN(params_to_send,useable_space);
643 data_sent_thistime = useable_space - params_sent_thistime;
644 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
646 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
648 /* smb_proff is the offset from the start of the SMB header to the
649 parameter bytes, however the first 4 bytes of outbuf are
650 the Netbios over TCP header. Thus use smb_base() to subtract
651 them from the calculation */
653 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
655 if(params_sent_thistime == 0)
656 SSVAL(outbuf,smb_prdisp,0);
658 /* Absolute displacement of param bytes sent in this packet */
659 SSVAL(outbuf,smb_prdisp,pp - params);
661 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
662 if(data_sent_thistime == 0) {
663 SSVAL(outbuf,smb_droff,0);
664 SSVAL(outbuf,smb_drdisp, 0);
666 /* The offset of the data bytes is the offset of the
667 parameter bytes plus the number of parameters being sent this time */
668 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
669 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
670 SSVAL(outbuf,smb_drdisp, pd - pdata);
673 /* Copy the param bytes into the packet */
675 if(params_sent_thistime)
676 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
678 /* Copy in the data bytes */
679 if(data_sent_thistime)
680 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
681 data_alignment_offset,pd,data_sent_thistime);
683 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
684 params_sent_thistime, data_sent_thistime, useable_space));
685 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
686 params_to_send, data_to_send, paramsize, datasize));
688 /* Send the packet */
690 if (!send_smb(smbd_server_fd(),outbuf))
691 exit_server("send_trans2_replies: send_smb failed.");
693 pp += params_sent_thistime;
694 pd += data_sent_thistime;
696 params_to_send -= params_sent_thistime;
697 data_to_send -= data_sent_thistime;
700 if(params_to_send < 0 || data_to_send < 0) {
701 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
702 params_to_send, data_to_send));
710 /****************************************************************************
711 Reply to a TRANSACT2_OPEN.
712 ****************************************************************************/
714 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
715 char **pparams, int total_params, char **ppdata, int total_data,
716 unsigned int max_data_bytes)
718 char *params = *pparams;
719 char *pdata = *ppdata;
724 BOOL return_additional_info;
735 SMB_STRUCT_STAT sbuf;
737 BOOL bad_path = False;
739 TALLOC_CTX *ctx = NULL;
740 struct ea_list *ea_list = NULL;
745 uint32 create_disposition;
746 uint32 create_options = 0;
749 * Ensure we have enough parameters to perform the operation.
752 if (total_params < 29) {
753 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
756 flags = SVAL(params, 0);
757 deny_mode = SVAL(params, 2);
758 open_attr = SVAL(params,6);
759 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
760 if (oplock_request) {
761 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
765 return_additional_info = BITSETW(params,0);
766 open_sattr = SVAL(params, 4);
767 open_time = make_unix_date3(params+8);
769 open_ofun = SVAL(params,12);
770 open_size = IVAL(params,14);
774 return(ERROR_DOS(ERRSRV,ERRaccess));
777 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
778 if (!NT_STATUS_IS_OK(status)) {
779 return ERROR_NT(status);
782 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
783 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
784 (unsigned int)open_ofun, open_size));
786 /* XXXX we need to handle passed times, sattr and flags */
788 unix_convert(fname,conn,0,&bad_path,&sbuf);
790 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
793 if (!check_name(fname,conn)) {
794 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
797 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
802 return ERROR_DOS(ERRDOS, ERRbadaccess);
805 /* Any data in this call is an EA list. */
806 if (total_data && !lp_ea_support(SNUM(conn))) {
807 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
811 if (total_data < 10) {
812 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
815 if (IVAL(pdata,0) > total_data) {
816 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
817 IVAL(pdata,0), (unsigned int)total_data));
818 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
821 ctx = talloc_init("TRANS2_OPEN_SET_EA");
823 return ERROR_NT(NT_STATUS_NO_MEMORY);
825 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
828 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
832 fsp = open_file_ntcreate(conn,fname,&sbuf,
843 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
844 /* We have re-scheduled this call. */
847 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
850 size = get_file_size(sbuf);
851 fattr = dos_mode(conn,fname,&sbuf);
852 mtime = sbuf.st_mtime;
856 close_file(fsp,False);
857 return(ERROR_DOS(ERRDOS,ERRnoaccess));
860 if (total_data && smb_action == FILE_WAS_CREATED) {
861 status = set_ea(conn, fsp, fname, ea_list);
863 if (!NT_STATUS_IS_OK(status)) {
864 close_file(fsp,False);
865 return ERROR_NT(status);
869 /* Realloc the size of parameters and data we will return */
870 params = SMB_REALLOC(*pparams, 30);
871 if( params == NULL ) {
872 return ERROR_NT(NT_STATUS_NO_MEMORY);
876 SSVAL(params,0,fsp->fnum);
877 SSVAL(params,2,open_attr);
878 put_dos_date2(params,4, mtime);
879 SIVAL(params,8, (uint32)size);
880 SSVAL(params,12,deny_mode);
881 SSVAL(params,14,0); /* open_type - file or directory. */
882 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
884 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
885 smb_action |= EXTENDED_OPLOCK_GRANTED;
888 SSVAL(params,18,smb_action);
891 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
893 SIVAL(params,20,inode);
894 SSVAL(params,24,0); /* Padding. */
896 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
897 SIVAL(params, 26, ea_size);
899 SIVAL(params, 26, 0);
902 /* Send the required number of replies */
903 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0);
908 /*********************************************************
909 Routine to check if a given string matches exactly.
910 as a special case a mask of "." does NOT match. That
911 is required for correct wildcard semantics
912 Case can be significant or not.
913 **********************************************************/
915 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
917 if (mask[0] == '.' && mask[1] == 0)
920 return strcmp(str,mask)==0;
921 if (StrCaseCmp(str,mask) != 0) {
924 if (ms_has_wild(str)) {
930 /****************************************************************************
931 Return the filetype for UNIX extensions.
932 ****************************************************************************/
934 static uint32 unix_filetype(mode_t mode)
937 return UNIX_TYPE_FILE;
938 else if(S_ISDIR(mode))
939 return UNIX_TYPE_DIR;
941 else if(S_ISLNK(mode))
942 return UNIX_TYPE_SYMLINK;
945 else if(S_ISCHR(mode))
946 return UNIX_TYPE_CHARDEV;
949 else if(S_ISBLK(mode))
950 return UNIX_TYPE_BLKDEV;
953 else if(S_ISFIFO(mode))
954 return UNIX_TYPE_FIFO;
957 else if(S_ISSOCK(mode))
958 return UNIX_TYPE_SOCKET;
961 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
962 return UNIX_TYPE_UNKNOWN;
965 /****************************************************************************
966 Map wire perms onto standard UNIX permissions. Obey share restrictions.
967 ****************************************************************************/
969 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
973 if (perms == SMB_MODE_NO_CHANGE)
976 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
977 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
978 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
979 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
980 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
981 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
982 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
983 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
984 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
986 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
989 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
992 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
995 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
996 ret &= lp_dir_mask(SNUM(conn));
997 /* Add in force bits */
998 ret |= lp_force_dir_mode(SNUM(conn));
1000 /* Apply mode mask */
1001 ret &= lp_create_mask(SNUM(conn));
1002 /* Add in force bits */
1003 ret |= lp_force_create_mode(SNUM(conn));
1009 /****************************************************************************
1010 Get a level dependent lanman2 dir entry.
1011 ****************************************************************************/
1013 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1014 void *inbuf, void *outbuf,
1015 char *path_mask,uint32 dirtype,int info_level,
1016 int requires_resume_key,
1017 BOOL dont_descend,char **ppdata,
1018 char *base_data, int space_remaining,
1019 BOOL *out_of_space, BOOL *got_exact_match,
1020 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1024 SMB_STRUCT_STAT sbuf;
1028 char *p, *q, *pdata = *ppdata;
1032 SMB_OFF_T file_size = 0;
1033 SMB_BIG_UINT allocation_size = 0;
1035 time_t mdate=0, adate=0, cdate=0;
1037 char *last_entry_ptr;
1039 uint32 nt_extmode; /* Used for NT connections instead of mode */
1040 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1041 BOOL check_mangled_names = lp_manglednames(SNUM(conn));
1044 *out_of_space = False;
1045 *got_exact_match = False;
1050 p = strrchr_m(path_mask,'/');
1053 pstrcpy(mask,"*.*");
1057 pstrcpy(mask, path_mask);
1062 /* Needed if we run out of space */
1063 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1064 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1067 * Due to bugs in NT client redirectors we are not using
1068 * resume keys any more - set them to zero.
1069 * Check out the related comments in findfirst/findnext.
1075 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1076 (long)conn->dirptr,curr_dirpos));
1081 pstrcpy(fname,dname);
1083 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
1084 got_match = mask_match(fname, mask, conn->case_sensitive);
1086 if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False, SNUM(conn))) {
1089 * It turns out that NT matches wildcards against
1090 * both long *and* short names. This may explain some
1091 * of the wildcard wierdness from old DOS clients
1092 * that some people have been seeing.... JRA.
1096 pstrcpy( newname, fname);
1097 mangle_map( newname, True, False, SNUM(conn));
1098 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
1099 got_match = mask_match(newname, mask, conn->case_sensitive);
1103 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1104 if (dont_descend && !isdots)
1107 pstrcpy(pathreal,conn->dirpath);
1109 pstrcat(pathreal,"/");
1110 pstrcat(pathreal,dname);
1112 if (INFO_LEVEL_IS_UNIX(info_level)) {
1113 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1114 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1115 pathreal,strerror(errno)));
1118 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1120 /* Needed to show the msdfs symlinks as
1123 if(lp_host_msdfs() &&
1124 lp_msdfs_root(SNUM(conn)) &&
1125 is_msdfs_link(NULL,conn, pathreal, NULL, NULL,
1128 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1129 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1133 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1134 pathreal,strerror(errno)));
1139 mode = dos_mode(conn,pathreal,&sbuf);
1141 if (!dir_check_ftype(conn,mode,dirtype)) {
1142 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1146 file_size = get_file_size(sbuf);
1147 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1148 mdate = sbuf.st_mtime;
1149 adate = sbuf.st_atime;
1150 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1152 if (lp_dos_filetime_resolution(SNUM(conn))) {
1159 /* This is necessary, as otherwise the
1160 * desktop.ini file in this folder is
1162 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
1166 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1172 mangle_map(fname,False,True,SNUM(conn));
1177 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1179 switch (info_level) {
1180 case SMB_FIND_INFO_STANDARD:
1181 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1182 if(requires_resume_key) {
1186 put_dos_date2(p,0,cdate);
1187 put_dos_date2(p,4,adate);
1188 put_dos_date2(p,8,mdate);
1189 SIVAL(p,12,(uint32)file_size);
1190 SIVAL(p,16,(uint32)allocation_size);
1194 p += align_string(outbuf, p, 0);
1195 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1196 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1198 SCVAL(nameptr, -1, len - 2);
1200 SCVAL(nameptr, -1, 0);
1204 SCVAL(nameptr, -1, len - 1);
1206 SCVAL(nameptr, -1, 0);
1212 case SMB_FIND_EA_SIZE:
1213 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1214 if(requires_resume_key) {
1218 put_dos_date2(p,0,cdate);
1219 put_dos_date2(p,4,adate);
1220 put_dos_date2(p,8,mdate);
1221 SIVAL(p,12,(uint32)file_size);
1222 SIVAL(p,16,(uint32)allocation_size);
1225 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1226 SIVAL(p,22,ea_size); /* Extended attributes */
1230 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1231 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1244 SCVAL(nameptr,0,len);
1246 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1249 case SMB_FIND_EA_LIST:
1251 struct ea_list *file_list = NULL;
1254 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1258 if(requires_resume_key) {
1262 put_dos_date2(p,0,cdate);
1263 put_dos_date2(p,4,adate);
1264 put_dos_date2(p,8,mdate);
1265 SIVAL(p,12,(uint32)file_size);
1266 SIVAL(p,16,(uint32)allocation_size);
1268 p += 22; /* p now points to the EA area. */
1270 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1271 name_list = ea_list_union(name_list, file_list, &ea_len);
1273 /* We need to determine if this entry will fit in the space available. */
1274 /* Max string size is 255 bytes. */
1275 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1276 /* Move the dirptr back to prev_dirpos */
1277 dptr_SeekDir(conn->dirptr, prev_dirpos);
1278 *out_of_space = True;
1279 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1280 return False; /* Not finished - just out of space */
1283 /* Push the ea_data followed by the name. */
1284 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1286 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1287 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1300 SCVAL(nameptr,0,len);
1302 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1306 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1307 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1308 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1310 SIVAL(p,0,reskey); p += 4;
1311 put_long_date(p,cdate); p += 8;
1312 put_long_date(p,adate); p += 8;
1313 put_long_date(p,mdate); p += 8;
1314 put_long_date(p,mdate); p += 8;
1315 SOFF_T(p,0,file_size); p += 8;
1316 SOFF_T(p,0,allocation_size); p += 8;
1317 SIVAL(p,0,nt_extmode); p += 4;
1318 q = p; p += 4; /* q is placeholder for name length. */
1320 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1321 SIVAL(p,0,ea_size); /* Extended attributes */
1324 /* Clear the short name buffer. This is
1325 * IMPORTANT as not doing so will trigger
1326 * a Win2k client bug. JRA.
1328 if (!was_8_3 && check_mangled_names) {
1329 pstring mangled_name;
1330 pstrcpy(mangled_name, fname);
1331 mangle_map(mangled_name,True,True,SNUM(conn));
1332 mangled_name[12] = 0;
1333 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1335 memset(p + 2 + len,'\0',24 - len);
1342 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1345 SIVAL(p,0,0); /* Ensure any padding is null. */
1346 len = PTR_DIFF(p, pdata);
1347 len = (len + 3) & ~3;
1352 case SMB_FIND_FILE_DIRECTORY_INFO:
1353 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1355 SIVAL(p,0,reskey); p += 4;
1356 put_long_date(p,cdate); p += 8;
1357 put_long_date(p,adate); p += 8;
1358 put_long_date(p,mdate); p += 8;
1359 put_long_date(p,mdate); p += 8;
1360 SOFF_T(p,0,file_size); p += 8;
1361 SOFF_T(p,0,allocation_size); p += 8;
1362 SIVAL(p,0,nt_extmode); p += 4;
1363 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1366 SIVAL(p,0,0); /* Ensure any padding is null. */
1367 len = PTR_DIFF(p, pdata);
1368 len = (len + 3) & ~3;
1373 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1374 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1376 SIVAL(p,0,reskey); p += 4;
1377 put_long_date(p,cdate); p += 8;
1378 put_long_date(p,adate); p += 8;
1379 put_long_date(p,mdate); p += 8;
1380 put_long_date(p,mdate); p += 8;
1381 SOFF_T(p,0,file_size); p += 8;
1382 SOFF_T(p,0,allocation_size); p += 8;
1383 SIVAL(p,0,nt_extmode); p += 4;
1384 q = p; p += 4; /* q is placeholder for name length. */
1386 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1387 SIVAL(p,0,ea_size); /* Extended attributes */
1390 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1394 SIVAL(p,0,0); /* Ensure any padding is null. */
1395 len = PTR_DIFF(p, pdata);
1396 len = (len + 3) & ~3;
1401 case SMB_FIND_FILE_NAMES_INFO:
1402 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1404 SIVAL(p,0,reskey); p += 4;
1406 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1407 acl on a dir (tridge) */
1408 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1411 SIVAL(p,0,0); /* Ensure any padding is null. */
1412 len = PTR_DIFF(p, pdata);
1413 len = (len + 3) & ~3;
1418 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1419 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1421 SIVAL(p,0,reskey); p += 4;
1422 put_long_date(p,cdate); p += 8;
1423 put_long_date(p,adate); p += 8;
1424 put_long_date(p,mdate); p += 8;
1425 put_long_date(p,mdate); 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 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1436 SIVAL(p,0,sbuf.st_dev); p += 4;
1437 SIVAL(p,0,sbuf.st_ino); p += 4;
1438 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1441 SIVAL(p,0,0); /* Ensure any padding is null. */
1442 len = PTR_DIFF(p, pdata);
1443 len = (len + 3) & ~3;
1448 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1449 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1450 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1452 SIVAL(p,0,reskey); p += 4;
1453 put_long_date(p,cdate); p += 8;
1454 put_long_date(p,adate); p += 8;
1455 put_long_date(p,mdate); p += 8;
1456 put_long_date(p,mdate); p += 8;
1457 SOFF_T(p,0,file_size); p += 8;
1458 SOFF_T(p,0,allocation_size); p += 8;
1459 SIVAL(p,0,nt_extmode); p += 4;
1460 q = p; p += 4; /* q is placeholder for name length */
1462 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1463 SIVAL(p,0,ea_size); /* Extended attributes */
1466 /* Clear the short name buffer. This is
1467 * IMPORTANT as not doing so will trigger
1468 * a Win2k client bug. JRA.
1470 if (!was_8_3 && check_mangled_names) {
1471 pstring mangled_name;
1472 pstrcpy(mangled_name, fname);
1473 mangle_map(mangled_name,True,True,SNUM(conn));
1474 mangled_name[12] = 0;
1475 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1478 memset(p + 2 + len,'\0',24 - len);
1485 SSVAL(p,0,0); p += 2; /* Reserved ? */
1486 SIVAL(p,0,sbuf.st_dev); p += 4;
1487 SIVAL(p,0,sbuf.st_ino); p += 4;
1488 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1491 SIVAL(p,0,0); /* Ensure any padding is null. */
1492 len = PTR_DIFF(p, pdata);
1493 len = (len + 3) & ~3;
1498 /* CIFS UNIX Extension. */
1500 case SMB_FIND_FILE_UNIX:
1501 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1503 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1505 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1506 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1509 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1512 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1513 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1514 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1517 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1521 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1525 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1528 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1532 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1536 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1539 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1543 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1547 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1549 SIVAL(p,0,0); /* Ensure any padding is null. */
1551 len = PTR_DIFF(p, pdata);
1552 len = (len + 3) & ~3;
1553 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1555 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1564 if (PTR_DIFF(p,pdata) > space_remaining) {
1565 /* Move the dirptr back to prev_dirpos */
1566 dptr_SeekDir(conn->dirptr, prev_dirpos);
1567 *out_of_space = True;
1568 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1569 return False; /* Not finished - just out of space */
1572 /* Setup the last entry pointer, as an offset from base_data */
1573 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1574 /* Advance the data pointer to the next slot */
1580 /****************************************************************************
1581 Reply to a TRANS2_FINDFIRST.
1582 ****************************************************************************/
1584 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1585 char **pparams, int total_params, char **ppdata, int total_data,
1586 unsigned int max_data_bytes)
1588 /* We must be careful here that we don't return more than the
1589 allowed number of data bytes. If this means returning fewer than
1590 maxentries then so be it. We assume that the redirector has
1591 enough room for the fixed number of parameter bytes it has
1593 char *params = *pparams;
1594 char *pdata = *ppdata;
1595 uint32 dirtype = SVAL(params,0);
1596 int maxentries = SVAL(params,2);
1597 uint16 findfirst_flags = SVAL(params,4);
1598 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1599 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1600 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1601 int info_level = SVAL(params,6);
1605 int last_entry_off=0;
1609 BOOL finished = False;
1610 BOOL dont_descend = False;
1611 BOOL out_of_space = False;
1612 int space_remaining;
1613 BOOL bad_path = False;
1614 SMB_STRUCT_STAT sbuf;
1615 TALLOC_CTX *ea_ctx = NULL;
1616 struct ea_list *ea_list = NULL;
1617 NTSTATUS ntstatus = NT_STATUS_OK;
1619 if (total_params < 12) {
1620 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1623 *directory = *mask = 0;
1625 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1626 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1627 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1628 info_level, max_data_bytes));
1631 /* W2K3 seems to treat zero as 1. */
1635 switch (info_level) {
1636 case SMB_FIND_INFO_STANDARD:
1637 case SMB_FIND_EA_SIZE:
1638 case SMB_FIND_EA_LIST:
1639 case SMB_FIND_FILE_DIRECTORY_INFO:
1640 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1641 case SMB_FIND_FILE_NAMES_INFO:
1642 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1643 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1644 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1646 case SMB_FIND_FILE_UNIX:
1647 if (!lp_unix_extensions())
1648 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1651 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1654 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1655 if (!NT_STATUS_IS_OK(ntstatus)) {
1656 return ERROR_NT(ntstatus);
1659 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1661 unix_convert(directory,conn,0,&bad_path,&sbuf);
1663 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1665 if(!check_name(directory,conn)) {
1666 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1669 p = strrchr_m(directory,'/');
1671 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1672 if((directory[0] == '.') && (directory[1] == '\0'))
1675 pstrcpy(mask,directory);
1676 pstrcpy(directory,"./");
1682 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1684 if (info_level == SMB_FIND_EA_LIST) {
1687 if (total_data < 4) {
1688 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1691 ea_size = IVAL(pdata,0);
1692 if (ea_size != total_data) {
1693 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1694 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1695 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1698 if (!lp_ea_support(SNUM(conn))) {
1699 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1702 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1703 return ERROR_NT(NT_STATUS_NO_MEMORY);
1706 /* Pull out the list of names. */
1707 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1709 talloc_destroy(ea_ctx);
1710 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1714 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1715 if( pdata == NULL ) {
1716 talloc_destroy(ea_ctx);
1717 return ERROR_NT(NT_STATUS_NO_MEMORY);
1722 /* Realloc the params space */
1723 params = SMB_REALLOC(*pparams, 10);
1724 if (params == NULL) {
1725 talloc_destroy(ea_ctx);
1726 return ERROR_NT(NT_STATUS_NO_MEMORY);
1730 /* Save the wildcard match and attribs we are using on this directory -
1731 needed as lanman2 assumes these are being saved between calls */
1733 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, dirtype);
1735 talloc_destroy(ea_ctx);
1736 return(UNIXERROR(ERRDOS,ERRbadfile));
1739 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1741 /* We don't need to check for VOL here as this is returned by
1742 a different TRANS2 call. */
1744 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1745 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1746 dont_descend = True;
1749 space_remaining = max_data_bytes;
1750 out_of_space = False;
1752 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1753 BOOL got_exact_match = False;
1755 /* this is a heuristic to avoid seeking the dirptr except when
1756 absolutely necessary. It allows for a filename of about 40 chars */
1757 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1758 out_of_space = True;
1761 finished = !get_lanman2_dir_entry(conn,
1763 mask,dirtype,info_level,
1764 requires_resume_key,dont_descend,
1765 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1766 &last_entry_off, ea_list, ea_ctx);
1769 if (finished && out_of_space)
1772 if (!finished && !out_of_space)
1776 * As an optimisation if we know we aren't looking
1777 * for a wildcard name (ie. the name matches the wildcard exactly)
1778 * then we can finish on any (first) match.
1779 * This speeds up large directory searches. JRA.
1785 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1788 talloc_destroy(ea_ctx);
1790 /* Check if we can close the dirptr */
1791 if(close_after_first || (finished && close_if_end)) {
1792 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1793 dptr_close(&dptr_num);
1797 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1798 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1799 * the protocol level is less than NT1. Tested with smbclient. JRA.
1800 * This should fix the OS/2 client bug #2335.
1803 if(numentries == 0) {
1804 dptr_close(&dptr_num);
1805 if (Protocol < PROTOCOL_NT1) {
1806 return ERROR_DOS(ERRDOS,ERRnofiles);
1808 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1812 /* At this point pdata points to numentries directory entries. */
1814 /* Set up the return parameter block */
1815 SSVAL(params,0,dptr_num);
1816 SSVAL(params,2,numentries);
1817 SSVAL(params,4,finished);
1818 SSVAL(params,6,0); /* Never an EA error */
1819 SSVAL(params,8,last_entry_off);
1821 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1823 if ((! *directory) && dptr_path(dptr_num))
1824 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1826 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1827 smb_fn_name(CVAL(inbuf,smb_com)),
1828 mask, directory, dirtype, numentries ) );
1831 * Force a name mangle here to ensure that the
1832 * mask as an 8.3 name is top of the mangled cache.
1833 * The reasons for this are subtle. Don't remove
1834 * this code unless you know what you are doing
1835 * (see PR#13758). JRA.
1838 if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn)))
1839 mangle_map(mask, True, True, SNUM(conn));
1844 /****************************************************************************
1845 Reply to a TRANS2_FINDNEXT.
1846 ****************************************************************************/
1848 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1849 char **pparams, int total_params, char **ppdata, int total_data,
1850 unsigned int max_data_bytes)
1852 /* We must be careful here that we don't return more than the
1853 allowed number of data bytes. If this means returning fewer than
1854 maxentries then so be it. We assume that the redirector has
1855 enough room for the fixed number of parameter bytes it has
1857 char *params = *pparams;
1858 char *pdata = *ppdata;
1859 int dptr_num = SVAL(params,0);
1860 int maxentries = SVAL(params,2);
1861 uint16 info_level = SVAL(params,4);
1862 uint32 resume_key = IVAL(params,6);
1863 uint16 findnext_flags = SVAL(params,10);
1864 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1865 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1866 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1867 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1868 pstring resume_name;
1874 int i, last_entry_off=0;
1875 BOOL finished = False;
1876 BOOL dont_descend = False;
1877 BOOL out_of_space = False;
1878 int space_remaining;
1879 TALLOC_CTX *ea_ctx = NULL;
1880 struct ea_list *ea_list = NULL;
1881 NTSTATUS ntstatus = NT_STATUS_OK;
1883 if (total_params < 12) {
1884 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1887 *mask = *directory = *resume_name = 0;
1889 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1890 if (!NT_STATUS_IS_OK(ntstatus)) {
1891 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1892 complain (it thinks we're asking for the directory above the shared
1893 path or an invalid name). Catch this as the resume name is only compared, never used in
1894 a file access. JRA. */
1895 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1896 pstrcpy(resume_name, "..");
1897 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1898 pstrcpy(resume_name, ".");
1900 return ERROR_NT(ntstatus);
1904 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1905 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1906 resume_key = %d resume name = %s continue=%d level = %d\n",
1907 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1908 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1911 /* W2K3 seems to treat zero as 1. */
1915 switch (info_level) {
1916 case SMB_FIND_INFO_STANDARD:
1917 case SMB_FIND_EA_SIZE:
1918 case SMB_FIND_EA_LIST:
1919 case SMB_FIND_FILE_DIRECTORY_INFO:
1920 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1921 case SMB_FIND_FILE_NAMES_INFO:
1922 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1924 case SMB_FIND_FILE_UNIX:
1925 if (!lp_unix_extensions())
1926 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1929 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1932 if (info_level == SMB_FIND_EA_LIST) {
1935 if (total_data < 4) {
1936 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1939 ea_size = IVAL(pdata,0);
1940 if (ea_size != total_data) {
1941 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1942 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1943 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1946 if (!lp_ea_support(SNUM(conn))) {
1947 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1950 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1951 return ERROR_NT(NT_STATUS_NO_MEMORY);
1954 /* Pull out the list of names. */
1955 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1957 talloc_destroy(ea_ctx);
1958 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1962 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1964 talloc_destroy(ea_ctx);
1965 return ERROR_NT(NT_STATUS_NO_MEMORY);
1970 /* Realloc the params space */
1971 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1972 if( params == NULL ) {
1973 talloc_destroy(ea_ctx);
1974 return ERROR_NT(NT_STATUS_NO_MEMORY);
1979 /* Check that the dptr is valid */
1980 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
1981 talloc_destroy(ea_ctx);
1982 return ERROR_DOS(ERRDOS,ERRnofiles);
1985 string_set(&conn->dirpath,dptr_path(dptr_num));
1987 /* Get the wildcard mask from the dptr */
1988 if((p = dptr_wcard(dptr_num))== NULL) {
1989 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1990 talloc_destroy(ea_ctx);
1991 return ERROR_DOS(ERRDOS,ERRnofiles);
1995 pstrcpy(directory,conn->dirpath);
1997 /* Get the attr mask from the dptr */
1998 dirtype = dptr_attr(dptr_num);
2000 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2001 dptr_num, mask, dirtype,
2003 dptr_TellDir(conn->dirptr)));
2005 /* We don't need to check for VOL here as this is returned by
2006 a different TRANS2 call. */
2008 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2009 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2010 dont_descend = True;
2013 space_remaining = max_data_bytes;
2014 out_of_space = False;
2017 * Seek to the correct position. We no longer use the resume key but
2018 * depend on the last file name instead.
2021 if(*resume_name && !continue_bit) {
2024 long current_pos = 0;
2026 * Remember, mangle_map is called by
2027 * get_lanman2_dir_entry(), so the resume name
2028 * could be mangled. Ensure we check the unmangled name.
2031 if (mangle_is_mangled(resume_name, SNUM(conn))) {
2032 mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn));
2036 * Fix for NT redirector problem triggered by resume key indexes
2037 * changing between directory scans. We now return a resume key of 0
2038 * and instead look for the filename to continue from (also given
2039 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2040 * findfirst/findnext (as is usual) then the directory pointer
2041 * should already be at the correct place.
2044 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2045 } /* end if resume_name && !continue_bit */
2047 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2048 BOOL got_exact_match = False;
2050 /* this is a heuristic to avoid seeking the dirptr except when
2051 absolutely necessary. It allows for a filename of about 40 chars */
2052 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2053 out_of_space = True;
2056 finished = !get_lanman2_dir_entry(conn,
2058 mask,dirtype,info_level,
2059 requires_resume_key,dont_descend,
2060 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2061 &last_entry_off, ea_list, ea_ctx);
2064 if (finished && out_of_space)
2067 if (!finished && !out_of_space)
2071 * As an optimisation if we know we aren't looking
2072 * for a wildcard name (ie. the name matches the wildcard exactly)
2073 * then we can finish on any (first) match.
2074 * This speeds up large directory searches. JRA.
2080 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2083 talloc_destroy(ea_ctx);
2085 /* Check if we can close the dirptr */
2086 if(close_after_request || (finished && close_if_end)) {
2087 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2088 dptr_close(&dptr_num); /* This frees up the saved mask */
2091 /* Set up the return parameter block */
2092 SSVAL(params,0,numentries);
2093 SSVAL(params,2,finished);
2094 SSVAL(params,4,0); /* Never an EA error */
2095 SSVAL(params,6,last_entry_off);
2097 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2099 if ((! *directory) && dptr_path(dptr_num))
2100 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2102 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2103 smb_fn_name(CVAL(inbuf,smb_com)),
2104 mask, directory, dirtype, numentries ) );
2109 /****************************************************************************
2110 Reply to a TRANS2_QFSINFO (query filesystem info).
2111 ****************************************************************************/
2113 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2114 char **pparams, int total_params, char **ppdata, int total_data,
2115 unsigned int max_data_bytes)
2117 char *pdata = *ppdata;
2118 char *params = *pparams;
2119 uint16 info_level = SVAL(params,0);
2122 char *vname = volume_label(SNUM(conn));
2123 int snum = SNUM(conn);
2124 char *fstype = lp_fstype(SNUM(conn));
2127 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2129 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2130 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2131 return ERROR_DOS(ERRSRV,ERRinvdevice);
2134 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2135 if ( pdata == NULL ) {
2136 return ERROR_NT(NT_STATUS_NO_MEMORY);
2140 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2142 switch (info_level) {
2143 case SMB_INFO_ALLOCATION:
2145 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2147 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2148 return(UNIXERROR(ERRHRD,ERRgeneral));
2151 block_size = lp_block_size(snum);
2152 if (bsize < block_size) {
2153 SMB_BIG_UINT factor = block_size/bsize;
2158 if (bsize > block_size) {
2159 SMB_BIG_UINT factor = bsize/block_size;
2164 bytes_per_sector = 512;
2165 sectors_per_unit = bsize/bytes_per_sector;
2167 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2168 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2169 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2171 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2172 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2173 SIVAL(pdata,l1_cUnit,dsize);
2174 SIVAL(pdata,l1_cUnitAvail,dfree);
2175 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2179 case SMB_INFO_VOLUME:
2180 /* Return volume name */
2182 * Add volume serial number - hash of a combination of
2183 * the called hostname and the service name.
2185 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2187 * Win2k3 and previous mess this up by sending a name length
2188 * one byte short. I believe only older clients (OS/2 Win9x) use
2189 * this call so try fixing this by adding a terminating null to
2190 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2192 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2193 SCVAL(pdata,l2_vol_cch,len);
2194 data_len = l2_vol_szVolLabel + len;
2195 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2196 (unsigned)st.st_ctime, len, vname));
2199 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2200 case SMB_FS_ATTRIBUTE_INFORMATION:
2203 #if defined(HAVE_SYS_QUOTAS)
2204 quota_flag = FILE_VOLUME_QUOTAS;
2207 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2208 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2209 quota_flag); /* FS ATTRIBUTES */
2211 SIVAL(pdata,4,255); /* Max filename component length */
2212 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2213 and will think we can't do long filenames */
2214 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2216 data_len = 12 + len;
2219 case SMB_QUERY_FS_LABEL_INFO:
2220 case SMB_FS_LABEL_INFORMATION:
2221 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2226 case SMB_QUERY_FS_VOLUME_INFO:
2227 case SMB_FS_VOLUME_INFORMATION:
2230 * Add volume serial number - hash of a combination of
2231 * the called hostname and the service name.
2233 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2234 (str_checksum(get_local_machine_name())<<16));
2236 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2237 SIVAL(pdata,12,len);
2239 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2240 (int)strlen(vname),vname, lp_servicename(snum)));
2243 case SMB_QUERY_FS_SIZE_INFO:
2244 case SMB_FS_SIZE_INFORMATION:
2246 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2248 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2249 return(UNIXERROR(ERRHRD,ERRgeneral));
2251 block_size = lp_block_size(snum);
2252 if (bsize < block_size) {
2253 SMB_BIG_UINT factor = block_size/bsize;
2258 if (bsize > block_size) {
2259 SMB_BIG_UINT factor = bsize/block_size;
2264 bytes_per_sector = 512;
2265 sectors_per_unit = bsize/bytes_per_sector;
2266 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2267 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2268 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2269 SBIG_UINT(pdata,0,dsize);
2270 SBIG_UINT(pdata,8,dfree);
2271 SIVAL(pdata,16,sectors_per_unit);
2272 SIVAL(pdata,20,bytes_per_sector);
2276 case SMB_FS_FULL_SIZE_INFORMATION:
2278 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2280 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2281 return(UNIXERROR(ERRHRD,ERRgeneral));
2283 block_size = lp_block_size(snum);
2284 if (bsize < block_size) {
2285 SMB_BIG_UINT factor = block_size/bsize;
2290 if (bsize > block_size) {
2291 SMB_BIG_UINT factor = bsize/block_size;
2296 bytes_per_sector = 512;
2297 sectors_per_unit = bsize/bytes_per_sector;
2298 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2299 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2300 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2301 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2302 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2303 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2304 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2305 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2309 case SMB_QUERY_FS_DEVICE_INFO:
2310 case SMB_FS_DEVICE_INFORMATION:
2312 SIVAL(pdata,0,0); /* dev type */
2313 SIVAL(pdata,4,0); /* characteristics */
2316 #ifdef HAVE_SYS_QUOTAS
2317 case SMB_FS_QUOTA_INFORMATION:
2319 * what we have to send --metze:
2321 * Unknown1: 24 NULL bytes
2322 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2323 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2324 * Quota Flags: 2 byte :
2325 * Unknown3: 6 NULL bytes
2329 * details for Quota Flags:
2331 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2332 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2333 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2334 * 0x0001 Enable Quotas: enable quota for this fs
2338 /* we need to fake up a fsp here,
2339 * because its not send in this call
2342 SMB_NTQUOTA_STRUCT quotas;
2345 ZERO_STRUCT(quotas);
2352 if (current_user.uid != 0) {
2353 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2354 lp_servicename(SNUM(conn)),conn->user));
2355 return ERROR_DOS(ERRDOS,ERRnoaccess);
2358 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2359 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2360 return ERROR_DOS(ERRSRV,ERRerror);
2365 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2367 /* Unknown1 24 NULL bytes*/
2368 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2369 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2370 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2372 /* Default Soft Quota 8 bytes */
2373 SBIG_UINT(pdata,24,quotas.softlim);
2375 /* Default Hard Quota 8 bytes */
2376 SBIG_UINT(pdata,32,quotas.hardlim);
2378 /* Quota flag 2 bytes */
2379 SSVAL(pdata,40,quotas.qflags);
2381 /* Unknown3 6 NULL bytes */
2387 #endif /* HAVE_SYS_QUOTAS */
2388 case SMB_FS_OBJECTID_INFORMATION:
2393 * Query the version and capabilities of the CIFS UNIX extensions
2397 case SMB_QUERY_CIFS_UNIX_INFO:
2398 if (!lp_unix_extensions())
2399 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2401 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2402 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2403 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(CIFS_UNIX_POSIX_ACLS_CAP|
2404 CIFS_UNIX_POSIX_PATHNAMES_CAP))); /* We have POSIX ACLs and pathname capability. */
2407 case SMB_MAC_QUERY_FS_INFO:
2409 * Thursby MAC extension... ONLY on NTFS filesystems
2410 * once we do streams then we don't need this
2412 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2414 SIVAL(pdata,84,0x100); /* Don't support mac... */
2419 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2423 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2425 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2430 /****************************************************************************
2431 Reply to a TRANS2_SETFSINFO (set filesystem info).
2432 ****************************************************************************/
2434 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2435 char **pparams, int total_params, char **ppdata, int total_data,
2436 unsigned int max_data_bytes)
2438 char *pdata = *ppdata;
2439 char *params = *pparams;
2443 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2446 if (total_params < 4) {
2447 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2449 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2452 info_level = SVAL(params,2);
2454 switch(info_level) {
2455 case SMB_SET_CIFS_UNIX_INFO:
2457 uint16 client_unix_major;
2458 uint16 client_unix_minor;
2459 uint32 client_unix_cap_low;
2460 uint32 client_unix_cap_high;
2462 if (!lp_unix_extensions()) {
2463 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2466 /* There should be 12 bytes of capabilities set. */
2467 if (total_data < 8) {
2468 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2470 client_unix_major = SVAL(pdata,0);
2471 client_unix_minor = SVAL(pdata,2);
2472 client_unix_cap_low = IVAL(pdata,4);
2473 client_unix_cap_high = IVAL(pdata,8);
2474 /* Just print these values for now. */
2475 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2476 cap_low = 0x%x, cap_high = 0x%x\n",
2477 (unsigned int)client_unix_major,
2478 (unsigned int)client_unix_minor,
2479 (unsigned int)client_unix_cap_low,
2480 (unsigned int)client_unix_cap_high ));
2482 /* Here is where we must switch to posix pathname processing... */
2483 lp_set_posix_pathnames();
2484 mangle_change_to_posix();
2487 case SMB_FS_QUOTA_INFORMATION:
2489 files_struct *fsp = NULL;
2490 SMB_NTQUOTA_STRUCT quotas;
2492 ZERO_STRUCT(quotas);
2495 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2496 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2497 lp_servicename(SNUM(conn)),conn->user));
2498 return ERROR_DOS(ERRSRV,ERRaccess);
2501 /* note: normaly there're 48 bytes,
2502 * but we didn't use the last 6 bytes for now
2505 fsp = file_fsp(params,0);
2506 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2507 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2508 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2511 if (total_data < 42) {
2512 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2514 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2517 /* unknown_1 24 NULL bytes in pdata*/
2519 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2520 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2521 #ifdef LARGE_SMB_OFF_T
2522 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2523 #else /* LARGE_SMB_OFF_T */
2524 if ((IVAL(pdata,28) != 0)&&
2525 ((quotas.softlim != 0xFFFFFFFF)||
2526 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2527 /* more than 32 bits? */
2528 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2530 #endif /* LARGE_SMB_OFF_T */
2532 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2533 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2534 #ifdef LARGE_SMB_OFF_T
2535 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2536 #else /* LARGE_SMB_OFF_T */
2537 if ((IVAL(pdata,36) != 0)&&
2538 ((quotas.hardlim != 0xFFFFFFFF)||
2539 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2540 /* more than 32 bits? */
2541 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2543 #endif /* LARGE_SMB_OFF_T */
2545 /* quota_flags 2 bytes **/
2546 quotas.qflags = SVAL(pdata,40);
2548 /* unknown_2 6 NULL bytes follow*/
2550 /* now set the quotas */
2551 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2552 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2553 return ERROR_DOS(ERRSRV,ERRerror);
2559 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2561 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2566 * sending this reply works fine,
2567 * but I'm not sure it's the same
2568 * like windows do...
2571 outsize = set_message(outbuf,10,0,True);
2576 /****************************************************************************
2577 Utility function to set bad path error.
2578 ****************************************************************************/
2580 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2582 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2583 err, (int)bad_path ));
2587 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2589 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2592 return UNIXERROR(def_class,def_code);
2595 #if defined(HAVE_POSIX_ACLS)
2596 /****************************************************************************
2597 Utility function to count the number of entries in a POSIX acl.
2598 ****************************************************************************/
2600 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2602 unsigned int ace_count = 0;
2603 int entry_id = SMB_ACL_FIRST_ENTRY;
2604 SMB_ACL_ENTRY_T entry;
2606 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2608 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2609 entry_id = SMB_ACL_NEXT_ENTRY;
2616 /****************************************************************************
2617 Utility function to marshall a POSIX acl into wire format.
2618 ****************************************************************************/
2620 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2622 int entry_id = SMB_ACL_FIRST_ENTRY;
2623 SMB_ACL_ENTRY_T entry;
2625 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2626 SMB_ACL_TAG_T tagtype;
2627 SMB_ACL_PERMSET_T permset;
2628 unsigned char perms = 0;
2629 unsigned int own_grp;
2632 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2633 entry_id = SMB_ACL_NEXT_ENTRY;
2636 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2637 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2641 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2642 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2646 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2647 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2648 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2650 SCVAL(pdata,1,perms);
2653 case SMB_ACL_USER_OBJ:
2654 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2655 own_grp = (unsigned int)pst->st_uid;
2656 SIVAL(pdata,2,own_grp);
2661 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2663 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2665 own_grp = (unsigned int)*puid;
2666 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2667 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2668 SIVAL(pdata,2,own_grp);
2672 case SMB_ACL_GROUP_OBJ:
2673 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2674 own_grp = (unsigned int)pst->st_gid;
2675 SIVAL(pdata,2,own_grp);
2680 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2682 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2684 own_grp = (unsigned int)*pgid;
2685 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2686 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2687 SIVAL(pdata,2,own_grp);
2692 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2693 SIVAL(pdata,2,0xFFFFFFFF);
2694 SIVAL(pdata,6,0xFFFFFFFF);
2697 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2698 SIVAL(pdata,2,0xFFFFFFFF);
2699 SIVAL(pdata,6,0xFFFFFFFF);
2702 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2705 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2712 /****************************************************************************
2713 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2714 file name or file id).
2715 ****************************************************************************/
2717 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2718 unsigned int tran_call,
2719 char **pparams, int total_params, char **ppdata, int total_data,
2720 unsigned int max_data_bytes)
2722 char *params = *pparams;
2723 char *pdata = *ppdata;
2727 SMB_OFF_T file_size=0;
2728 SMB_BIG_UINT allocation_size=0;
2729 unsigned int data_size = 0;
2730 unsigned int param_size = 2;
2731 SMB_STRUCT_STAT sbuf;
2732 pstring fname, dos_fname;
2737 BOOL bad_path = False;
2738 BOOL delete_pending = False;
2741 files_struct *fsp = NULL;
2742 TALLOC_CTX *ea_ctx = NULL;
2743 struct ea_list *ea_list = NULL;
2744 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2747 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2751 if (tran_call == TRANSACT2_QFILEINFO) {
2752 if (total_params < 4) {
2753 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2756 fsp = file_fsp(params,0);
2757 info_level = SVAL(params,2);
2759 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2761 if(fsp && (fsp->fake_file_handle)) {
2763 * This is actually for the QUOTA_FAKE_FILE --metze
2766 pstrcpy(fname, fsp->fsp_name);
2767 /* We know this name is ok, it's already passed the checks. */
2769 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2771 * This is actually a QFILEINFO on a directory
2772 * handle (returned from an NT SMB). NT5.0 seems
2773 * to do this call. JRA.
2775 /* We know this name is ok, it's already passed the checks. */
2776 pstrcpy(fname, fsp->fsp_name);
2778 if (INFO_LEVEL_IS_UNIX(info_level)) {
2779 /* Always do lstat for UNIX calls. */
2780 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2781 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2782 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2784 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2785 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2786 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2790 get_delete_on_close_flag(sbuf.st_dev,
2795 * Original code - this is an open file.
2797 CHECK_FSP(fsp,conn);
2799 pstrcpy(fname, fsp->fsp_name);
2800 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2801 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2802 return(UNIXERROR(ERRDOS,ERRbadfid));
2804 pos = fsp->fh->position_information;
2806 get_delete_on_close_flag(sbuf.st_dev,
2809 access_mask = fsp->access_mask;
2812 NTSTATUS status = NT_STATUS_OK;
2815 if (total_params < 6) {
2816 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2819 info_level = SVAL(params,0);
2821 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2823 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2824 if (!NT_STATUS_IS_OK(status)) {
2825 return ERROR_NT(status);
2828 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2830 unix_convert(fname,conn,0,&bad_path,&sbuf);
2832 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2834 if (!check_name(fname,conn)) {
2835 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2836 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2839 if (INFO_LEVEL_IS_UNIX(info_level)) {
2840 /* Always do lstat for UNIX calls. */
2841 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2842 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2843 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2845 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2846 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2847 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2850 delete_pending = get_delete_on_close_flag(sbuf.st_dev,
2853 if (delete_pending) {
2854 return ERROR_NT(NT_STATUS_DELETE_PENDING);
2858 nlink = sbuf.st_nlink;
2860 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2861 /* NTFS does not seem to count ".." */
2865 if ((nlink > 0) && delete_pending) {
2869 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2870 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2872 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2873 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2875 p = strrchr_m(fname,'/');
2881 mode = dos_mode(conn,fname,&sbuf);
2883 mode = FILE_ATTRIBUTE_NORMAL;
2885 fullpathname = fname;
2886 file_size = get_file_size(sbuf);
2888 /* This is necessary, as otherwise the desktop.ini file in
2889 * this folder is ignored */
2890 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2894 /* Pull any EA list from the data portion. */
2895 if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2898 if (total_data < 4) {
2899 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2901 ea_size = IVAL(pdata,0);
2903 if (total_data > 0 && ea_size != total_data) {
2904 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2905 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2906 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2909 if (!lp_ea_support(SNUM(conn))) {
2910 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2913 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2914 return ERROR_NT(NT_STATUS_NO_MEMORY);
2917 /* Pull out the list of names. */
2918 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2920 talloc_destroy(ea_ctx);
2921 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2925 params = SMB_REALLOC(*pparams,2);
2926 if (params == NULL) {
2927 talloc_destroy(ea_ctx);
2928 return ERROR_NT(NT_STATUS_NO_MEMORY);
2932 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2933 pdata = SMB_REALLOC(*ppdata, data_size);
2934 if ( pdata == NULL ) {
2935 talloc_destroy(ea_ctx);
2936 return ERROR_NT(NT_STATUS_NO_MEMORY);
2940 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2942 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2945 if (fsp->pending_modtime) {
2946 /* the pending modtime overrides the current modtime */
2947 sbuf.st_mtime = fsp->pending_modtime;
2950 /* Do we have this path open ? */
2951 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2952 if (fsp1 && fsp1->pending_modtime) {
2953 /* the pending modtime overrides the current modtime */
2954 sbuf.st_mtime = fsp1->pending_modtime;
2956 if (fsp1 && fsp1->initial_allocation_size) {
2957 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
2961 if (lp_dos_filetime_resolution(SNUM(conn))) {
2963 sbuf.st_atime &= ~1;
2964 sbuf.st_ctime &= ~1;
2965 sbuf.st_mtime &= ~1;
2968 /* NT expects the name to be in an exact form of the *full*
2969 filename. See the trans2 torture test */
2970 if (strequal(base_name,".")) {
2971 pstrcpy(dos_fname, "\\");
2973 pstr_sprintf(dos_fname, "\\%s", fname);
2974 string_replace(dos_fname, '/', '\\');
2977 switch (info_level) {
2978 case SMB_INFO_STANDARD:
2979 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2981 put_dos_date2(pdata,l1_fdateCreation,c_time);
2982 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2983 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2984 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2985 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2986 SSVAL(pdata,l1_attrFile,mode);
2989 case SMB_INFO_QUERY_EA_SIZE:
2991 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2992 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2994 put_dos_date2(pdata,0,c_time);
2995 put_dos_date2(pdata,4,sbuf.st_atime);
2996 put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */
2997 SIVAL(pdata,12,(uint32)file_size);
2998 SIVAL(pdata,16,(uint32)allocation_size);
2999 SSVAL(pdata,20,mode);
3000 SIVAL(pdata,22,ea_size);
3004 case SMB_INFO_IS_NAME_VALID:
3005 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3006 if (tran_call == TRANSACT2_QFILEINFO) {
3007 /* os/2 needs this ? really ?*/
3008 return ERROR_DOS(ERRDOS,ERRbadfunc);
3014 case SMB_INFO_QUERY_EAS_FROM_LIST:
3016 size_t total_ea_len = 0;
3017 struct ea_list *ea_file_list = NULL;
3019 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3021 ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3022 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3024 if (!ea_list || (total_ea_len > data_size)) {
3025 talloc_destroy(ea_ctx);
3027 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3031 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3032 talloc_destroy(ea_ctx);
3036 case SMB_INFO_QUERY_ALL_EAS:
3038 /* We have data_size bytes to put EA's into. */
3039 size_t total_ea_len = 0;
3041 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3043 ea_ctx = talloc_init("ea_ctx");
3045 return ERROR_NT(NT_STATUS_NO_MEMORY);
3048 ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3049 if (!ea_list || (total_ea_len > data_size)) {
3050 talloc_destroy(ea_ctx);
3052 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3056 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3057 talloc_destroy(ea_ctx);
3061 case SMB_FILE_BASIC_INFORMATION:
3062 case SMB_QUERY_FILE_BASIC_INFO:
3064 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3065 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3066 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3068 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3072 put_long_date(pdata,c_time);
3073 put_long_date(pdata+8,sbuf.st_atime);
3074 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3075 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3076 SIVAL(pdata,32,mode);
3078 DEBUG(5,("SMB_QFBI - "));
3080 time_t create_time = c_time;
3081 DEBUG(5,("create: %s ", ctime(&create_time)));
3083 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3084 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3085 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3086 DEBUG(5,("mode: %x\n", mode));
3089 case SMB_FILE_STANDARD_INFORMATION:
3090 case SMB_QUERY_FILE_STANDARD_INFO:
3092 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3094 SOFF_T(pdata,0,allocation_size);
3095 SOFF_T(pdata,8,file_size);
3096 SIVAL(pdata,16,nlink);
3097 SCVAL(pdata,20,delete_pending?1:0);
3098 SCVAL(pdata,21,(mode&aDIR)?1:0);
3099 SSVAL(pdata,22,0); /* Padding. */
3102 case SMB_FILE_EA_INFORMATION:
3103 case SMB_QUERY_FILE_EA_INFO:
3105 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3106 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3108 SIVAL(pdata,0,ea_size);
3112 /* Get the 8.3 name - used if NT SMB was negotiated. */
3113 case SMB_QUERY_FILE_ALT_NAME_INFO:
3114 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3118 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3119 pstrcpy(short_name,base_name);
3120 /* Mangle if not already 8.3 */
3121 if(!mangle_is_8_3(short_name, True, SNUM(conn))) {
3122 mangle_map(short_name,True,True,SNUM(conn));
3124 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3125 data_size = 4 + len;
3130 case SMB_QUERY_FILE_NAME_INFO:
3132 this must be *exactly* right for ACLs on mapped drives to work
3134 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3135 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3136 data_size = 4 + len;
3140 case SMB_FILE_ALLOCATION_INFORMATION:
3141 case SMB_QUERY_FILE_ALLOCATION_INFO:
3142 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3144 SOFF_T(pdata,0,allocation_size);
3147 case SMB_FILE_END_OF_FILE_INFORMATION:
3148 case SMB_QUERY_FILE_END_OF_FILEINFO:
3149 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3151 SOFF_T(pdata,0,file_size);
3154 case SMB_QUERY_FILE_ALL_INFO:
3155 case SMB_FILE_ALL_INFORMATION:
3157 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3158 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3159 put_long_date(pdata,c_time);
3160 put_long_date(pdata+8,sbuf.st_atime);
3161 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3162 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3163 SIVAL(pdata,32,mode);
3164 SIVAL(pdata,36,0); /* padding. */
3166 SOFF_T(pdata,0,allocation_size);
3167 SOFF_T(pdata,8,file_size);
3168 SIVAL(pdata,16,nlink);
3169 SCVAL(pdata,20,delete_pending);
3170 SCVAL(pdata,21,(mode&aDIR)?1:0);
3173 SIVAL(pdata,0,ea_size);
3174 pdata += 4; /* EA info */
3175 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3178 data_size = PTR_DIFF(pdata,(*ppdata));
3181 case SMB_FILE_INTERNAL_INFORMATION:
3182 /* This should be an index number - looks like
3185 I think this causes us to fail the IFSKIT
3186 BasicFileInformationTest. -tpot */
3188 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3189 SIVAL(pdata,0,sbuf.st_dev);
3190 SIVAL(pdata,4,sbuf.st_ino);
3194 case SMB_FILE_ACCESS_INFORMATION:
3195 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3196 SIVAL(pdata,0,access_mask);
3200 case SMB_FILE_NAME_INFORMATION:
3201 /* Pathname with leading '\'. */
3204 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
3205 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3206 SIVAL(pdata,0,byte_len);
3207 data_size = 4 + byte_len;
3211 case SMB_FILE_DISPOSITION_INFORMATION:
3212 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3214 SCVAL(pdata,0,delete_pending);
3217 case SMB_FILE_POSITION_INFORMATION:
3218 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3220 SOFF_T(pdata,0,pos);
3223 case SMB_FILE_MODE_INFORMATION:
3224 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3225 SIVAL(pdata,0,mode);
3229 case SMB_FILE_ALIGNMENT_INFORMATION:
3230 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3231 SIVAL(pdata,0,0); /* No alignment needed. */
3237 * NT4 server just returns "invalid query" to this - if we try to answer
3238 * it then NTws gets a BSOD! (tridge).
3239 * W2K seems to want this. JRA.
3241 case SMB_QUERY_FILE_STREAM_INFO:
3243 case SMB_FILE_STREAM_INFORMATION:
3244 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3248 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
3249 SIVAL(pdata,0,0); /* ??? */
3250 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3251 SOFF_T(pdata,8,file_size);
3252 SIVAL(pdata,16,allocation_size);
3253 SIVAL(pdata,20,0); /* ??? */
3254 data_size = 24 + byte_len;
3258 case SMB_QUERY_COMPRESSION_INFO:
3259 case SMB_FILE_COMPRESSION_INFORMATION:
3260 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3261 SOFF_T(pdata,0,file_size);
3262 SIVAL(pdata,8,0); /* ??? */
3263 SIVAL(pdata,12,0); /* ??? */
3267 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3268 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3269 put_long_date(pdata,c_time);
3270 put_long_date(pdata+8,sbuf.st_atime);
3271 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3272 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3273 SIVAL(pdata,32,allocation_size);
3274 SOFF_T(pdata,40,file_size);
3275 SIVAL(pdata,48,mode);
3276 SIVAL(pdata,52,0); /* ??? */
3280 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3281 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3282 SIVAL(pdata,0,mode);
3288 * CIFS UNIX Extensions.
3291 case SMB_QUERY_FILE_UNIX_BASIC:
3293 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3294 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3296 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3299 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3302 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3303 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3304 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3307 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3311 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3315 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3318 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3322 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3326 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3329 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3333 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3336 data_size = PTR_DIFF(pdata,(*ppdata));
3340 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3342 for (i=0; i<100; i++)
3343 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3349 case SMB_QUERY_FILE_UNIX_LINK:
3353 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3355 if(!S_ISLNK(sbuf.st_mode))
3356 return(UNIXERROR(ERRSRV,ERRbadlink));
3358 return(UNIXERROR(ERRDOS,ERRbadlink));
3360 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3362 return(UNIXERROR(ERRDOS,ERRnoaccess));
3364 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3366 data_size = PTR_DIFF(pdata,(*ppdata));
3371 #if defined(HAVE_POSIX_ACLS)
3372 case SMB_QUERY_POSIX_ACL:
3374 SMB_ACL_T file_acl = NULL;
3375 SMB_ACL_T def_acl = NULL;
3376 uint16 num_file_acls = 0;
3377 uint16 num_def_acls = 0;
3379 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3380 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3382 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3385 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3386 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3388 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3391 if (S_ISDIR(sbuf.st_mode)) {
3392 if (fsp && fsp->is_directory) {
3393 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3395 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3397 def_acl = free_empty_sys_acl(conn, def_acl);
3400 num_file_acls = count_acl_entries(conn, file_acl);
3401 num_def_acls = count_acl_entries(conn, def_acl);
3403 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3404 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3406 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3407 SMB_POSIX_ACL_HEADER_SIZE) ));
3409 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3412 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3414 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3417 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3418 SSVAL(pdata,2,num_file_acls);
3419 SSVAL(pdata,4,num_def_acls);
3420 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3422 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3425 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3427 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3429 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3431 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3434 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3436 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3440 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3443 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3445 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3451 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3454 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3459 /****************************************************************************
3460 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3462 ****************************************************************************/
3464 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3466 BOOL bad_path_oldname = False;
3467 BOOL bad_path_newname = False;
3468 SMB_STRUCT_STAT sbuf1, sbuf2;
3469 pstring last_component_oldname;
3470 pstring last_component_newname;
3471 NTSTATUS status = NT_STATUS_OK;
3477 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3478 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3481 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3482 if (bad_path_oldname) {
3483 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3486 /* Quick check for "." and ".." */
3487 if (last_component_oldname[0] == '.') {
3488 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3489 return NT_STATUS_OBJECT_NAME_INVALID;
3493 /* source must already exist. */
3494 if (!VALID_STAT(sbuf1)) {
3495 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3498 if (!check_name(oldname,conn)) {
3499 return NT_STATUS_ACCESS_DENIED;
3502 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3503 if (bad_path_newname) {
3504 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3507 /* Quick check for "." and ".." */
3508 if (last_component_newname[0] == '.') {
3509 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3510 return NT_STATUS_OBJECT_NAME_INVALID;
3514 /* Disallow if newname already exists. */
3515 if (VALID_STAT(sbuf2)) {
3516 return NT_STATUS_OBJECT_NAME_COLLISION;
3519 if (!check_name(newname,conn)) {
3520 return NT_STATUS_ACCESS_DENIED;
3523 /* No links from a directory. */
3524 if (S_ISDIR(sbuf1.st_mode)) {
3525 return NT_STATUS_FILE_IS_A_DIRECTORY;
3528 /* Ensure this is within the share. */
3529 if (!reduce_name(conn, oldname) != 0)
3530 return NT_STATUS_ACCESS_DENIED;
3532 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3534 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3535 status = map_nt_error_from_unix(errno);
3536 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3537 nt_errstr(status), newname, oldname));
3543 /****************************************************************************
3544 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3545 ****************************************************************************/
3547 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3548 unsigned int tran_call,
3549 char **pparams, int total_params, char **ppdata, int total_data,
3550 unsigned int max_data_bytes)
3552 char *params = *pparams;
3553 char *pdata = *ppdata;
3558 SMB_STRUCT_STAT sbuf;
3561 BOOL bad_path = False;
3562 files_struct *fsp = NULL;
3563 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3564 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3565 mode_t unixmode = 0;
3566 NTSTATUS status = NT_STATUS_OK;
3569 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3574 if (tran_call == TRANSACT2_SETFILEINFO) {
3575 if (total_params < 4) {
3576 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3579 fsp = file_fsp(params,0);
3580 info_level = SVAL(params,2);
3582 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3584 * This is actually a SETFILEINFO on a directory
3585 * handle (returned from an NT SMB). NT5.0 seems
3586 * to do this call. JRA.
3588 pstrcpy(fname, fsp->fsp_name);
3589 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3590 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3591 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3593 } else if (fsp && fsp->print_file) {
3595 * Doing a DELETE_ON_CLOSE should cancel a print job.
3597 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3598 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
3600 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3603 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3606 return (UNIXERROR(ERRDOS,ERRbadpath));
3609 * Original code - this is an open file.
3611 CHECK_FSP(fsp,conn);
3613 pstrcpy(fname, fsp->fsp_name);
3616 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3617 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3618 return(UNIXERROR(ERRDOS,ERRbadfid));
3623 if (total_params < 6) {
3624 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3627 info_level = SVAL(params,0);
3628 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3629 if (!NT_STATUS_IS_OK(status)) {
3630 return ERROR_NT(status);
3632 unix_convert(fname,conn,0,&bad_path,&sbuf);
3634 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3638 * For CIFS UNIX extensions the target name may not exist.
3641 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3642 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3643 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3646 if(!check_name(fname, conn)) {
3647 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3652 if (!CAN_WRITE(conn))
3653 return ERROR_DOS(ERRSRV,ERRaccess);
3655 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3656 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3658 if (VALID_STAT(sbuf))
3659 unixmode = sbuf.st_mode;
3661 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3662 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3664 /* Realloc the parameter size */
3665 params = SMB_REALLOC(*pparams,2);
3666 if(params == NULL) {
3667 return ERROR_NT(NT_STATUS_NO_MEMORY);
3673 if (fsp && fsp->pending_modtime) {
3674 /* the pending modtime overrides the current modtime */
3675 sbuf.st_mtime = fsp->pending_modtime;
3678 size = get_file_size(sbuf);
3679 tvs.modtime = sbuf.st_mtime;
3680 tvs.actime = sbuf.st_atime;
3681 dosmode = dos_mode(conn,fname,&sbuf);
3682 unixmode = sbuf.st_mode;
3684 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3685 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3687 switch (info_level) {
3688 case SMB_INFO_STANDARD:
3690 if (total_data < 12) {
3691 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3695 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3697 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3701 case SMB_INFO_SET_EA:
3703 struct ea_list *ea_list = NULL;
3704 TALLOC_CTX *ctx = NULL;
3706 if (total_data < 10) {
3707 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3710 if (IVAL(pdata,0) > total_data) {
3711 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3712 IVAL(pdata,0), (unsigned int)total_data));
3713 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3716 ctx = talloc_init("SMB_INFO_SET_EA");
3718 return ERROR_NT(NT_STATUS_NO_MEMORY);
3720 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3722 talloc_destroy(ctx);
3723 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3725 status = set_ea(conn, fsp, fname, ea_list);
3726 talloc_destroy(ctx);
3728 if (!NT_STATUS_IS_OK(status)) {
3729 return ERROR_NT(status);
3732 /* We're done. We only get EA info in this call. */
3734 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3739 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3740 /* XXXX um, i don't think this is right.
3741 it's also not in the cifs6.txt spec.
3743 case SMB_INFO_QUERY_EAS_FROM_LIST:
3744 if (total_data < 28)
3745 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3747 tvs.actime = make_unix_date2(pdata+8);
3748 tvs.modtime = make_unix_date2(pdata+12);
3749 size = IVAL(pdata,16);
3750 dosmode = IVAL(pdata,24);
3753 /* XXXX nor this. not in cifs6.txt, either. */
3754 case SMB_INFO_QUERY_ALL_EAS:
3755 if (total_data < 28)
3756 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3758 tvs.actime = make_unix_date2(pdata+8);
3759 tvs.modtime = make_unix_date2(pdata+12);
3760 size = IVAL(pdata,16);
3761 dosmode = IVAL(pdata,24);
3765 case SMB_SET_FILE_BASIC_INFO:
3766 case SMB_FILE_BASIC_INFORMATION:
3768 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3770 time_t changed_time;
3772 if (total_data < 36) {
3773 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3776 /* Ignore create time at offset pdata. */
3779 tvs.actime = interpret_long_date(pdata+8);
3781 write_time = interpret_long_date(pdata+16);
3782 changed_time = interpret_long_date(pdata+24);
3784 tvs.modtime = MIN(write_time, changed_time);
3786 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3787 tvs.modtime = write_time;
3789 /* Prefer a defined time to an undefined one. */
3790 if (null_mtime(tvs.modtime)) {
3791 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3795 dosmode = IVAL(pdata,32);
3799 case SMB_FILE_ALLOCATION_INFORMATION:
3800 case SMB_SET_FILE_ALLOCATION_INFO:
3803 SMB_BIG_UINT allocation_size;
3805 if (total_data < 8) {
3806 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3809 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3810 #ifdef LARGE_SMB_OFF_T
3811 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3812 #else /* LARGE_SMB_OFF_T */
3813 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3814 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3815 #endif /* LARGE_SMB_OFF_T */
3816 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3817 fname, (double)allocation_size ));
3819 if (allocation_size) {
3820 allocation_size = smb_roundup(conn, allocation_size);
3823 if(allocation_size != get_file_size(sbuf)) {
3824 SMB_STRUCT_STAT new_sbuf;
3826 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3827 fname, (double)allocation_size ));
3830 files_struct *new_fsp = NULL;
3832 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
3834 FILE_SHARE_READ|FILE_SHARE_WRITE,
3837 FILE_ATTRIBUTE_NORMAL,
3841 if (new_fsp == NULL) {
3842 return(UNIXERROR(ERRDOS,ERRbadpath));
3844 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3845 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
3846 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3847 new_fsp->fnum, strerror(errno)));
3850 close_file(new_fsp,True);
3852 ret = vfs_allocate_file_space(fsp, allocation_size);
3853 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3854 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3855 fsp->fnum, strerror(errno)));
3860 return ERROR_NT(NT_STATUS_DISK_FULL);
3862 /* Allocate can truncate size... */
3863 size = get_file_size(new_sbuf);
3869 case SMB_FILE_END_OF_FILE_INFORMATION:
3870 case SMB_SET_FILE_END_OF_FILE_INFO:
3872 if (total_data < 8) {
3873 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3876 size = IVAL(pdata,0);
3877 #ifdef LARGE_SMB_OFF_T
3878 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3879 #else /* LARGE_SMB_OFF_T */
3880 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3881 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3882 #endif /* LARGE_SMB_OFF_T */
3883 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3887 case SMB_FILE_DISPOSITION_INFORMATION:
3888 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3890 BOOL delete_on_close;
3892 if (total_data < 1) {
3893 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3896 delete_on_close = (CVAL(pdata,0) ? True : False);
3898 /* Just ignore this set on a path. */
3899 if (tran_call != TRANSACT2_SETFILEINFO)
3903 return(UNIXERROR(ERRDOS,ERRbadfid));
3905 status = can_set_delete_on_close(fsp, delete_on_close,
3908 if (!NT_STATUS_IS_OK(status)) {
3909 return ERROR_NT(status);
3912 /* The set is across all open files on this dev/inode pair. */
3913 if (!set_delete_on_close(fsp, delete_on_close)) {
3914 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3918 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3922 case SMB_FILE_POSITION_INFORMATION:
3924 SMB_BIG_UINT position_information;
3926 if (total_data < 8) {
3927 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3930 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3931 #ifdef LARGE_SMB_OFF_T
3932 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3933 #else /* LARGE_SMB_OFF_T */
3934 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3935 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3936 #endif /* LARGE_SMB_OFF_T */
3937 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3938 fname, (double)position_information ));
3940 fsp->fh->position_information = position_information;
3943 /* We're done. We only get position info in this call. */
3945 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3949 /* From tridge Samba4 :
3950 * MODE_INFORMATION in setfileinfo (I have no
3951 * idea what "mode information" on a file is - it takes a value of 0,
3952 * 2, 4 or 6. What could it be?).
3955 case SMB_FILE_MODE_INFORMATION:
3959 if (total_data < 4) {
3960 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3962 mode = IVAL(pdata,0);
3963 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
3964 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3967 /* We're done. We only get mode info in this call. */
3969 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3974 * CIFS UNIX extensions.
3977 case SMB_SET_FILE_UNIX_BASIC:
3979 uint32 raw_unixmode;
3981 if (total_data < 100) {
3982 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3985 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3986 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3987 size=IVAL(pdata,0); /* first 8 Bytes are size */
3988 #ifdef LARGE_SMB_OFF_T
3989 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3990 #else /* LARGE_SMB_OFF_T */
3991 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3992 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3993 #endif /* LARGE_SMB_OFF_T */
3995 pdata+=24; /* ctime & st_blocks are not changed */
3996 tvs.actime = interpret_long_date(pdata); /* access_time */
3997 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
3999 set_owner = (uid_t)IVAL(pdata,0);
4001 set_grp = (gid_t)IVAL(pdata,0);
4003 raw_unixmode = IVAL(pdata,28);
4004 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4005 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4007 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4008 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4009 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4011 if (!VALID_STAT(sbuf)) {
4014 * The only valid use of this is to create character and block
4015 * devices, and named pipes. This is deprecated (IMHO) and
4016 * a new info level should be used for mknod. JRA.
4019 uint32 file_type = IVAL(pdata,0);
4020 #if defined(HAVE_MAKEDEV)
4021 uint32 dev_major = IVAL(pdata,4);
4022 uint32 dev_minor = IVAL(pdata,12);
4025 uid_t myuid = geteuid();
4026 gid_t mygid = getegid();
4027 SMB_DEV_T dev = (SMB_DEV_T)0;
4029 if (tran_call == TRANSACT2_SETFILEINFO)
4030 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4032 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4033 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4036 #if defined(HAVE_MAKEDEV)
4037 dev = makedev(dev_major, dev_minor);
4040 /* We can only create as the owner/group we are. */
4042 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4043 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4044 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4045 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4047 switch (file_type) {
4048 #if defined(S_IFIFO)
4049 case UNIX_TYPE_FIFO:
4050 unixmode |= S_IFIFO;
4053 #if defined(S_IFSOCK)
4054 case UNIX_TYPE_SOCKET:
4055 unixmode |= S_IFSOCK;
4058 #if defined(S_IFCHR)
4059 case UNIX_TYPE_CHARDEV:
4060 unixmode |= S_IFCHR;
4063 #if defined(S_IFBLK)
4064 case UNIX_TYPE_BLKDEV:
4065 unixmode |= S_IFBLK;
4069 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4072 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4073 0%o for file %s\n", (double)dev, unixmode, fname ));
4075 /* Ok - do the mknod. */
4076 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4077 return(UNIXERROR(ERRDOS,ERRnoaccess));
4079 inherit_access_acl(conn, fname, unixmode);
4082 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4087 * Deal with the UNIX specific mode set.
4090 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4091 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4092 (unsigned int)unixmode, fname ));
4093 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4094 return(UNIXERROR(ERRDOS,ERRnoaccess));
4098 * Deal with the UNIX specific uid set.
4101 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4102 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4103 (unsigned int)set_owner, fname ));
4104 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4105 return(UNIXERROR(ERRDOS,ERRnoaccess));
4109 * Deal with the UNIX specific gid set.
4112 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4113 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4114 (unsigned int)set_owner, fname ));
4115 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4116 return(UNIXERROR(ERRDOS,ERRnoaccess));
4121 case SMB_SET_FILE_UNIX_LINK:
4123 pstring link_target;
4124 char *newname = fname;
4126 /* Set a symbolic link. */
4127 /* Don't allow this if follow links is false. */
4129 if (!lp_symlinks(SNUM(conn)))
4130 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4132 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4134 /* !widelinks forces the target path to be within the share. */
4135 /* This means we can interpret the target as a pathname. */
4136 if (!lp_widelinks(SNUM(conn))) {
4138 char *last_dirp = NULL;
4140 unix_format(link_target);
4141 if (*link_target == '/') {
4142 /* No absolute paths allowed. */
4143 return(UNIXERROR(ERRDOS,ERRnoaccess));
4145 pstrcpy(rel_name, newname);
4146 last_dirp = strrchr_m(rel_name, '/');
4148 last_dirp[1] = '\0';
4150 pstrcpy(rel_name, "./");
4152 pstrcat(rel_name, link_target);
4154 if (!check_name(rel_name, conn)) {
4155 return(UNIXERROR(ERRDOS,ERRnoaccess));
4159 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4160 fname, link_target ));
4162 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4163 return(UNIXERROR(ERRDOS,ERRnoaccess));
4165 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4169 case SMB_SET_FILE_UNIX_HLINK:
4172 char *newname = fname;
4174 /* Set a hard link. */
4175 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
4176 if (!NT_STATUS_IS_OK(status)) {
4177 return ERROR_NT(status);
4180 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4183 status = hardlink_internals(conn, oldname, newname);
4184 if (!NT_STATUS_IS_OK(status)) {
4185 return ERROR_NT(status);
4189 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4193 case SMB_FILE_RENAME_INFORMATION:
4202 if (total_data < 12) {
4203 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4206 overwrite = (CVAL(pdata,0) ? True : False);
4207 root_fid = IVAL(pdata,4);
4208 len = IVAL(pdata,8);
4209 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
4210 if (!NT_STATUS_IS_OK(status)) {
4211 return ERROR_NT(status);
4214 /* Check the new name has no '/' characters. */
4215 if (strchr_m(newname, '/'))
4216 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4218 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4220 /* Create the base directory. */
4221 pstrcpy(base_name, fname);
4222 p = strrchr_m(base_name, '/');
4225 /* Append the new name. */
4226 pstrcat(base_name, "/");
4227 pstrcat(base_name, newname);
4230 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4231 fsp->fnum, fsp->fsp_name, base_name ));
4232 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4234 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4236 status = rename_internals(conn, fname, base_name, 0, overwrite);
4238 if (!NT_STATUS_IS_OK(status)) {
4239 return ERROR_NT(status);
4241 process_pending_change_notify_queue((time_t)0);
4243 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4247 #if defined(HAVE_POSIX_ACLS)
4248 case SMB_SET_POSIX_ACL:
4250 uint16 posix_acl_version;
4251 uint16 num_file_acls;
4252 uint16 num_def_acls;
4253 BOOL valid_file_acls = True;
4254 BOOL valid_def_acls = True;
4256 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4257 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4259 posix_acl_version = SVAL(pdata,0);
4260 num_file_acls = SVAL(pdata,2);
4261 num_def_acls = SVAL(pdata,4);
4263 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4264 valid_file_acls = False;
4268 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4269 valid_def_acls = False;
4273 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4274 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4277 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4278 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4279 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4282 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4283 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4284 return(UNIXERROR(ERRDOS,ERRnoaccess));
4287 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4288 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4289 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4290 return(UNIXERROR(ERRDOS,ERRnoaccess));
4294 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4300 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4303 /* get some defaults (no modifications) if any info is zero or -1. */
4304 if (null_mtime(tvs.actime)) {
4305 tvs.actime = sbuf.st_atime;
4308 if (null_mtime(tvs.modtime)) {
4309 tvs.modtime = sbuf.st_mtime;
4312 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4313 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4314 DEBUG(6,("size: %.0f ", (double)size));
4317 if (S_ISDIR(sbuf.st_mode))
4323 DEBUG(6,("dosmode: %x\n" , dosmode));
4325 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4326 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4327 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4328 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4331 * Only do this test if we are not explicitly
4332 * changing the size of a file.
4335 size = get_file_size(sbuf);
4339 * Try and set the times, size and mode of this file -
4340 * if they are different from the current values
4343 /* check the mode isn't different, before changing it */
4344 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4346 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4348 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4349 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4350 return(UNIXERROR(ERRDOS,ERRnoaccess));
4355 if (size != get_file_size(sbuf)) {
4359 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4360 fname, (double)size ));
4363 files_struct *new_fsp = NULL;
4365 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
4367 FILE_SHARE_READ|FILE_SHARE_WRITE,
4370 FILE_ATTRIBUTE_NORMAL,
4374 if (new_fsp == NULL) {
4375 return(UNIXERROR(ERRDOS,ERRbadpath));
4377 ret = vfs_set_filelen(new_fsp, size);
4378 close_file(new_fsp,True);
4380 ret = vfs_set_filelen(fsp, size);
4384 return (UNIXERROR(ERRHRD,ERRdiskfull));
4389 * Finally the times.
4391 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4394 * This was a setfileinfo on an open file.
4395 * NT does this a lot. We also need to
4396 * set the time here, as it can be read by
4397 * FindFirst/FindNext and with the patch for bug #2045
4398 * in smbd/fileio.c it ensures that this timestamp is
4399 * kept sticky even after a write. We save the request
4400 * away and will set it on file close and after a write. JRA.
4403 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4404 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4405 fsp_set_pending_modtime(fsp, tvs.modtime);
4409 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4411 if(file_utime(conn, fname, &tvs)!=0) {
4412 return(UNIXERROR(ERRDOS,ERRnoaccess));
4417 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4422 /****************************************************************************
4423 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4424 ****************************************************************************/
4426 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4427 char **pparams, int total_params, char **ppdata, int total_data,
4428 unsigned int max_data_bytes)
4430 char *params = *pparams;
4431 char *pdata = *ppdata;
4434 SMB_STRUCT_STAT sbuf;
4435 BOOL bad_path = False;
4436 NTSTATUS status = NT_STATUS_OK;
4437 TALLOC_CTX *ctx = NULL;
4438 struct ea_list *ea_list = NULL;
4440 if (!CAN_WRITE(conn))
4441 return ERROR_DOS(ERRSRV,ERRaccess);
4443 if (total_params < 4) {
4444 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4447 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4448 if (!NT_STATUS_IS_OK(status)) {
4449 return ERROR_NT(status);
4452 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4454 unix_convert(directory,conn,0,&bad_path,&sbuf);
4456 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4459 /* Any data in this call is an EA list. */
4460 if (total_data && !lp_ea_support(SNUM(conn))) {
4461 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4465 if (total_data < 10) {
4466 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4469 if (IVAL(pdata,0) > total_data) {
4470 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4471 IVAL(pdata,0), (unsigned int)total_data));
4472 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4475 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4477 return ERROR_NT(NT_STATUS_NO_MEMORY);
4479 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4481 talloc_destroy(ctx);
4482 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4486 if (check_name(directory,conn)) {
4487 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4491 talloc_destroy(ctx);
4492 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4493 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4496 /* Try and set any given EA. */
4498 status = set_ea(conn, NULL, directory, ea_list);
4499 talloc_destroy(ctx);
4500 if (!NT_STATUS_IS_OK(status)) {
4501 return ERROR_NT(status);
4505 /* Realloc the parameter and data sizes */
4506 params = SMB_REALLOC(*pparams,2);
4507 if(params == NULL) {
4508 return ERROR_NT(NT_STATUS_NO_MEMORY);
4514 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4519 /****************************************************************************
4520 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4521 We don't actually do this - we just send a null response.
4522 ****************************************************************************/
4524 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4525 char **pparams, int total_params, char **ppdata, int total_data,
4526 unsigned int max_data_bytes)
4528 static uint16 fnf_handle = 257;
4529 char *params = *pparams;
4532 if (total_params < 6) {
4533 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4536 info_level = SVAL(params,4);
4537 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4539 switch (info_level) {
4544 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4547 /* Realloc the parameter and data sizes */
4548 params = SMB_REALLOC(*pparams,6);
4549 if(params == NULL) {
4550 return ERROR_NT(NT_STATUS_NO_MEMORY);
4554 SSVAL(params,0,fnf_handle);
4555 SSVAL(params,2,0); /* No changes */
4556 SSVAL(params,4,0); /* No EA errors */
4563 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4568 /****************************************************************************
4569 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4570 changes). Currently this does nothing.
4571 ****************************************************************************/
4573 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4574 char **pparams, int total_params, char **ppdata, int total_data,
4575 unsigned int max_data_bytes)
4577 char *params = *pparams;
4579 DEBUG(3,("call_trans2findnotifynext\n"));
4581 /* Realloc the parameter and data sizes */
4582 params = SMB_REALLOC(*pparams,4);
4583 if(params == NULL) {
4584 return ERROR_NT(NT_STATUS_NO_MEMORY);
4588 SSVAL(params,0,0); /* No changes */
4589 SSVAL(params,2,0); /* No EA errors */
4591 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4596 /****************************************************************************
4597 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4598 ****************************************************************************/
4600 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4601 char **pparams, int total_params, char **ppdata, int total_data,
4602 unsigned int max_data_bytes)
4604 char *params = *pparams;
4607 int max_referral_level;
4609 DEBUG(10,("call_trans2getdfsreferral\n"));
4611 if (total_params < 2) {
4612 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4615 max_referral_level = SVAL(params,0);
4617 if(!lp_host_msdfs())
4618 return ERROR_DOS(ERRDOS,ERRbadfunc);
4620 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4621 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4622 return UNIXERROR(ERRDOS,ERRbadfile);
4624 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4625 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4630 #define LMCAT_SPL 0x53
4631 #define LMFUNC_GETJOBID 0x60
4633 /****************************************************************************
4634 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4635 ****************************************************************************/
4637 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4638 char **pparams, int total_params, char **ppdata, int total_data,
4639 unsigned int max_data_bytes)
4641 char *pdata = *ppdata;
4642 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4644 /* check for an invalid fid before proceeding */
4647 return(ERROR_DOS(ERRDOS,ERRbadfid));
4649 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4650 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4651 pdata = SMB_REALLOC(*ppdata, 32);
4653 return ERROR_NT(NT_STATUS_NO_MEMORY);
4657 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4658 CAN ACCEPT THIS IN UNICODE. JRA. */
4660 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4661 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4662 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4663 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4666 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4667 return ERROR_DOS(ERRSRV,ERRerror);
4671 /****************************************************************************
4672 Reply to a SMBfindclose (stop trans2 directory search).
4673 ****************************************************************************/
4675 int reply_findclose(connection_struct *conn,
4676 char *inbuf,char *outbuf,int length,int bufsize)
4679 int dptr_num=SVALS(inbuf,smb_vwv0);
4680 START_PROFILE(SMBfindclose);
4682 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4684 dptr_close(&dptr_num);
4686 outsize = set_message(outbuf,0,0,True);
4688 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4690 END_PROFILE(SMBfindclose);
4694 /****************************************************************************
4695 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4696 ****************************************************************************/
4698 int reply_findnclose(connection_struct *conn,
4699 char *inbuf,char *outbuf,int length,int bufsize)
4703 START_PROFILE(SMBfindnclose);
4705 dptr_num = SVAL(inbuf,smb_vwv0);
4707 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4709 /* We never give out valid handles for a
4710 findnotifyfirst - so any dptr_num is ok here.
4713 outsize = set_message(outbuf,0,0,True);
4715 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4717 END_PROFILE(SMBfindnclose);
4721 /****************************************************************************
4722 Reply to a SMBtranss2 - just ignore it!
4723 ****************************************************************************/
4725 int reply_transs2(connection_struct *conn,
4726 char *inbuf,char *outbuf,int length,int bufsize)
4728 START_PROFILE(SMBtranss2);
4729 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4730 END_PROFILE(SMBtranss2);
4734 /****************************************************************************
4735 Reply to a SMBtrans2.
4736 ****************************************************************************/
4738 int reply_trans2(connection_struct *conn,
4739 char *inbuf,char *outbuf,int length,int bufsize)
4742 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4743 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4744 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4746 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4747 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4748 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4749 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4750 int32 timeout = IVALS(inbuf,smb_timeout);
4752 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4753 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4754 char *params = NULL, *data = NULL;
4755 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4756 START_PROFILE(SMBtrans2);
4758 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4759 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4760 END_PROFILE(SMBtrans2);
4761 return ERROR_DOS(ERRSRV,ERRaccess);
4764 outsize = set_message(outbuf,0,0,True);
4766 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4767 is so as a sanity check */
4770 * Need to have rc=0 for ioctl to get job id for OS/2.
4771 * Network printing will fail if function is not successful.
4772 * Similar function in reply.c will be used if protocol
4773 * is LANMAN1.0 instead of LM1.2X002.
4774 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4775 * outbuf doesn't have to be set(only job id is used).
4777 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4778 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4779 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4780 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4782 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4783 DEBUG(2,("Transaction is %d\n",tran_call));
4784 END_PROFILE(SMBtrans2);
4785 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4789 /* Allocate the space for the maximum needed parameters and data */
4790 if (total_params > 0)
4791 params = (char *)SMB_MALLOC(total_params);
4793 data = (char *)SMB_MALLOC(total_data);
4795 if ((total_params && !params) || (total_data && !data)) {
4796 DEBUG(2,("Out of memory in reply_trans2\n"));
4799 END_PROFILE(SMBtrans2);
4800 return ERROR_NT(NT_STATUS_NO_MEMORY);
4803 /* Copy the param and data bytes sent with this request into
4804 the params buffer */
4805 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4806 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4808 if (num_params > total_params || num_data > total_data)
4809 exit_server("invalid params in reply_trans2");
4812 unsigned int psoff = SVAL(inbuf, smb_psoff);
4813 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4815 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4816 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4818 memcpy( params, smb_base(inbuf) + psoff, num_params);
4821 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4822 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4824 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4825 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4827 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4830 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4832 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4833 /* We need to send an interim response then receive the rest
4834 of the parameter/data bytes */
4835 outsize = set_message(outbuf,0,0,True);
4836 srv_signing_trans_stop();
4838 if (!send_smb(smbd_server_fd(),outbuf))
4839 exit_server("reply_trans2: send_smb failed.");
4841 while (num_data_sofar < total_data ||
4842 num_params_sofar < total_params) {
4844 unsigned int param_disp;
4845 unsigned int param_off;
4846 unsigned int data_disp;
4847 unsigned int data_off;
4849 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4851 /* We need to re-calcuate the new length after we've read the secondary packet. */
4852 length = smb_len(inbuf) + 4;
4855 * The sequence number for the trans reply is always
4856 * based on the last secondary received.
4859 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4862 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4863 outsize = set_message(outbuf,0,0,True);
4865 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4867 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4868 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4872 /* Revise total_params and total_data in case
4873 they have changed downwards */
4874 if (SVAL(inbuf, smb_tpscnt) < total_params)
4875 total_params = SVAL(inbuf, smb_tpscnt);
4876 if (SVAL(inbuf, smb_tdscnt) < total_data)
4877 total_data = SVAL(inbuf, smb_tdscnt);
4879 num_params = SVAL(inbuf,smb_spscnt);
4880 param_off = SVAL(inbuf, smb_spsoff);
4881 param_disp = SVAL(inbuf, smb_spsdisp);
4882 num_params_sofar += num_params;
4884 num_data = SVAL(inbuf, smb_sdscnt);
4885 data_off = SVAL(inbuf, smb_sdsoff);
4886 data_disp = SVAL(inbuf, smb_sdsdisp);
4887 num_data_sofar += num_data;
4889 if (num_params_sofar > total_params || num_data_sofar > total_data)
4893 if (param_disp + num_params > total_params)
4895 if ((param_disp + num_params < param_disp) ||
4896 (param_disp + num_params < num_params))
4898 if (param_disp > total_params)
4900 if ((smb_base(inbuf) + param_off + num_params > inbuf + length) ||
4901 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4903 if (params + param_disp < params)
4906 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
4909 if (data_disp + num_data > total_data)
4911 if ((data_disp + num_data < data_disp) ||
4912 (data_disp + num_data < num_data))
4914 if (data_disp > total_data)
4916 if ((smb_base(inbuf) + data_off + num_data > inbuf + length) ||
4917 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4919 if (data + data_disp < data)
4922 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4927 if (Protocol >= PROTOCOL_NT1) {
4928 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4931 /* Now we must call the relevant TRANS2 function */
4933 case TRANSACT2_OPEN:
4934 START_PROFILE_NESTED(Trans2_open);
4935 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4936 ¶ms, total_params, &data, total_data, max_data_bytes);
4937 END_PROFILE_NESTED(Trans2_open);
4940 case TRANSACT2_FINDFIRST:
4941 START_PROFILE_NESTED(Trans2_findfirst);
4942 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4943 ¶ms, total_params, &data, total_data, max_data_bytes);
4944 END_PROFILE_NESTED(Trans2_findfirst);
4947 case TRANSACT2_FINDNEXT:
4948 START_PROFILE_NESTED(Trans2_findnext);
4949 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4950 ¶ms, total_params, &data, total_data, max_data_bytes);
4951 END_PROFILE_NESTED(Trans2_findnext);
4954 case TRANSACT2_QFSINFO:
4955 START_PROFILE_NESTED(Trans2_qfsinfo);
4956 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4957 ¶ms, total_params, &data, total_data, max_data_bytes);
4958 END_PROFILE_NESTED(Trans2_qfsinfo);
4961 case TRANSACT2_SETFSINFO:
4962 START_PROFILE_NESTED(Trans2_setfsinfo);
4963 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4964 ¶ms, total_params, &data, total_data, max_data_bytes);
4965 END_PROFILE_NESTED(Trans2_setfsinfo);
4968 case TRANSACT2_QPATHINFO:
4969 case TRANSACT2_QFILEINFO:
4970 START_PROFILE_NESTED(Trans2_qpathinfo);
4971 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
4972 ¶ms, total_params, &data, total_data, max_data_bytes);
4973 END_PROFILE_NESTED(Trans2_qpathinfo);
4975 case TRANSACT2_SETPATHINFO:
4976 case TRANSACT2_SETFILEINFO:
4977 START_PROFILE_NESTED(Trans2_setpathinfo);
4978 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
4979 ¶ms, total_params, &data, total_data, max_data_bytes);
4980 END_PROFILE_NESTED(Trans2_setpathinfo);
4983 case TRANSACT2_FINDNOTIFYFIRST:
4984 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4985 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4986 ¶ms, total_params, &data, total_data, max_data_bytes);
4987 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4990 case TRANSACT2_FINDNOTIFYNEXT:
4991 START_PROFILE_NESTED(Trans2_findnotifynext);
4992 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4993 ¶ms, total_params, &data, total_data, max_data_bytes);
4994 END_PROFILE_NESTED(Trans2_findnotifynext);
4996 case TRANSACT2_MKDIR:
4997 START_PROFILE_NESTED(Trans2_mkdir);
4998 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4999 ¶ms, total_params, &data, total_data, max_data_bytes);
5000 END_PROFILE_NESTED(Trans2_mkdir);
5003 case TRANSACT2_GET_DFS_REFERRAL:
5004 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5005 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
5006 ¶ms, total_params, &data, total_data, max_data_bytes);
5007 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5009 case TRANSACT2_IOCTL:
5010 START_PROFILE_NESTED(Trans2_ioctl);
5011 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
5012 ¶ms, total_params, &data, total_data, max_data_bytes);
5013 END_PROFILE_NESTED(Trans2_ioctl);
5016 /* Error in request */
5017 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
5020 END_PROFILE(SMBtrans2);
5021 srv_signing_trans_stop();
5022 return ERROR_DOS(ERRSRV,ERRerror);
5025 /* As we do not know how many data packets will need to be
5026 returned here the various call_trans2xxxx calls
5027 must send their own. Thus a call_trans2xxx routine only
5028 returns a value other than -1 when it wants to send
5032 srv_signing_trans_stop();
5036 END_PROFILE(SMBtrans2);
5037 return outsize; /* If a correct response was needed the
5038 call_trans2xxx calls have already sent
5039 it. If outsize != -1 then it is returning */
5043 srv_signing_trans_stop();
5046 END_PROFILE(SMBtrans2);
5047 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);