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
7 Copyright (C) Steve French 2005
9 Extensively modified by Andrew Tridgell, 1995
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 extern enum protocol_types Protocol;
30 extern int smb_read_error;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
37 /********************************************************************
38 Roundup a value to the nearest allocation roundup size boundary.
39 Only do this for Windows clients.
40 ********************************************************************/
42 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
44 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
46 /* Only roundup for Windows clients. */
47 enum remote_arch_types ra_type = get_remote_arch();
48 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
49 val = SMB_ROUNDUP(val,rval);
54 /********************************************************************
55 Given a stat buffer return the allocated size on disk, taking into
57 ********************************************************************/
59 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
63 if(S_ISDIR(sbuf->st_mode)) {
67 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
68 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
70 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
73 if (fsp && fsp->initial_allocation_size)
74 ret = MAX(ret,fsp->initial_allocation_size);
76 return smb_roundup(conn, ret);
79 /****************************************************************************
80 Utility functions for dealing with extended attributes.
81 ****************************************************************************/
83 static const char *prohibited_ea_names[] = {
84 SAMBA_POSIX_INHERITANCE_EA_NAME,
85 SAMBA_XATTR_DOS_ATTRIB,
89 /****************************************************************************
90 Refuse to allow clients to overwrite our private xattrs.
91 ****************************************************************************/
93 static BOOL samba_private_attr_name(const char *unix_ea_name)
97 for (i = 0; prohibited_ea_names[i]; i++) {
98 if (strequal( prohibited_ea_names[i], unix_ea_name))
104 /****************************************************************************
105 Get one EA value. Fill in a struct ea_struct.
106 ****************************************************************************/
108 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
109 const char *fname, char *ea_name, struct ea_struct *pea)
111 /* Get the value of this xattr. Max size is 64k. */
112 size_t attr_size = 256;
118 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
123 if (fsp && fsp->fh->fd != -1) {
124 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
126 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
129 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
138 DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
139 dump_data(10, val, sizeret);
142 if (strnequal(ea_name, "user.", 5)) {
143 pea->name = &ea_name[5];
147 pea->value.data = (unsigned char *)val;
148 pea->value.length = (size_t)sizeret;
152 /****************************************************************************
153 Return a linked list of the total EA's. Plus the total size
154 ****************************************************************************/
156 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
157 const char *fname, size_t *pea_total_len)
159 /* Get a list of all xattrs. Max namesize is 64k. */
160 size_t ea_namelist_size = 1024;
165 struct ea_list *ea_list_head = NULL;
169 if (!lp_ea_support(SNUM(conn))) {
173 for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
174 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
175 if (fsp && fsp->fh->fd != -1) {
176 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
178 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
181 if (sizeret == -1 && errno == ERANGE) {
182 ea_namelist_size *= 2;
191 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
194 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
195 struct ea_list *listp, *tmp;
197 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
200 listp = TALLOC_P(mem_ctx, struct ea_list);
204 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
210 push_ascii_fstring(dos_ea_name, listp->ea.name);
211 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
212 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
213 (unsigned int)*pea_total_len, dos_ea_name,
214 (unsigned int)listp->ea.value.length ));
216 DLIST_ADD_END(ea_list_head, listp, tmp);
218 /* Add on 4 for total length. */
219 if (*pea_total_len) {
224 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
228 /****************************************************************************
229 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
231 ****************************************************************************/
233 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
234 connection_struct *conn, struct ea_list *ea_list)
236 unsigned int ret_data_size = 4;
239 SMB_ASSERT(total_data_size >= 4);
241 if (!lp_ea_support(SNUM(conn))) {
246 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
249 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
250 dos_namelen = strlen(dos_ea_name);
251 if (dos_namelen > 255 || dos_namelen == 0) {
254 if (ea_list->ea.value.length > 65535) {
257 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
261 /* We know we have room. */
262 SCVAL(p,0,ea_list->ea.flags);
263 SCVAL(p,1,dos_namelen);
264 SSVAL(p,2,ea_list->ea.value.length);
265 fstrcpy(p+4, dos_ea_name);
266 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
268 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
269 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
272 ret_data_size = PTR_DIFF(p, pdata);
273 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
274 SIVAL(pdata,0,ret_data_size);
275 return ret_data_size;
278 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
280 size_t total_ea_len = 0;
281 TALLOC_CTX *mem_ctx = NULL;
283 if (!lp_ea_support(SNUM(conn))) {
286 mem_ctx = talloc_init("estimate_ea_size");
287 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
288 talloc_destroy(mem_ctx);
292 /****************************************************************************
293 Ensure the EA name is case insensitive by matching any existing EA name.
294 ****************************************************************************/
296 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
299 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
300 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
302 for (; ea_list; ea_list = ea_list->next) {
303 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
304 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
305 &unix_ea_name[5], ea_list->ea.name));
306 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
310 talloc_destroy(mem_ctx);
313 /****************************************************************************
314 Set or delete an extended attribute.
315 ****************************************************************************/
317 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
319 if (!lp_ea_support(SNUM(conn))) {
320 return NT_STATUS_EAS_NOT_SUPPORTED;
323 for (;ea_list; ea_list = ea_list->next) {
325 fstring unix_ea_name;
327 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
328 fstrcat(unix_ea_name, ea_list->ea.name);
330 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
332 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
334 if (samba_private_attr_name(unix_ea_name)) {
335 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
336 return NT_STATUS_ACCESS_DENIED;
339 if (ea_list->ea.value.length == 0) {
340 /* Remove the attribute. */
341 if (fsp && (fsp->fh->fd != -1)) {
342 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
343 unix_ea_name, fsp->fsp_name));
344 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
346 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
347 unix_ea_name, fname));
348 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
351 /* Removing a non existent attribute always succeeds. */
352 if (ret == -1 && errno == ENOATTR) {
353 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
359 if (fsp && (fsp->fh->fd != -1)) {
360 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
361 unix_ea_name, fsp->fsp_name));
362 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
363 ea_list->ea.value.data, ea_list->ea.value.length, 0);
365 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
366 unix_ea_name, fname));
367 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
368 ea_list->ea.value.data, ea_list->ea.value.length, 0);
374 if (errno == ENOTSUP) {
375 return NT_STATUS_EAS_NOT_SUPPORTED;
378 return map_nt_error_from_unix(errno);
384 /****************************************************************************
385 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
386 ****************************************************************************/
388 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
390 struct ea_list *ea_list_head = NULL;
393 while (offset + 2 < data_size) {
395 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
396 unsigned int namelen = CVAL(pdata,offset);
398 offset++; /* Go past the namelen byte. */
400 /* integer wrap paranioa. */
401 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
402 (offset > data_size) || (namelen > data_size) ||
403 (offset + namelen >= data_size)) {
406 /* Ensure the name is null terminated. */
407 if (pdata[offset + namelen] != '\0') {
410 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
415 offset += (namelen + 1); /* Go past the name + terminating zero. */
416 DLIST_ADD_END(ea_list_head, eal, tmp);
417 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
423 /****************************************************************************
424 Read one EA list entry from the buffer.
425 ****************************************************************************/
427 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
429 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
431 unsigned int namelen;
441 eal->ea.flags = CVAL(pdata,0);
442 namelen = CVAL(pdata,1);
443 val_len = SVAL(pdata,2);
445 if (4 + namelen + 1 + val_len > data_size) {
449 /* Ensure the name is null terminated. */
450 if (pdata[namelen + 4] != '\0') {
453 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
458 eal->ea.value = data_blob(NULL, (size_t)val_len + 1);
459 if (!eal->ea.value.data) {
463 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
465 /* Ensure we're null terminated just in case we print the value. */
466 eal->ea.value.data[val_len] = '\0';
467 /* But don't count the null. */
468 eal->ea.value.length--;
471 *pbytes_used = 4 + namelen + 1 + val_len;
474 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
475 dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
480 /****************************************************************************
481 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
482 ****************************************************************************/
484 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
486 struct ea_list *ea_list_head = NULL;
488 size_t bytes_used = 0;
490 while (offset < data_size) {
492 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
498 DLIST_ADD_END(ea_list_head, eal, tmp);
499 offset += bytes_used;
505 /****************************************************************************
506 Count the total EA size needed.
507 ****************************************************************************/
509 static size_t ea_list_size(struct ea_list *ealist)
512 struct ea_list *listp;
515 for (listp = ealist; listp; listp = listp->next) {
516 push_ascii_fstring(dos_ea_name, listp->ea.name);
517 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
519 /* Add on 4 for total length. */
527 /****************************************************************************
528 Return a union of EA's from a file list and a list of names.
529 The TALLOC context for the two lists *MUST* be identical as we steal
530 memory from one list to add to another. JRA.
531 ****************************************************************************/
533 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
535 struct ea_list *nlistp, *flistp;
537 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
538 for (flistp = file_list; flistp; flistp = flistp->next) {
539 if (strequal(nlistp->ea.name, flistp->ea.name)) {
545 /* Copy the data from this entry. */
546 nlistp->ea.flags = flistp->ea.flags;
547 nlistp->ea.value = flistp->ea.value;
550 nlistp->ea.flags = 0;
551 ZERO_STRUCT(nlistp->ea.value);
555 *total_ea_len = ea_list_size(name_list);
559 /****************************************************************************
560 Send the required number of replies back.
561 We assume all fields other than the data fields are
562 set correctly for the type of call.
563 HACK ! Always assumes smb_setup field is zero.
564 ****************************************************************************/
566 static int send_trans2_replies(char *outbuf,
573 /* As we are using a protocol > LANMAN1 then the max_send
574 variable must have been set in the sessetupX call.
575 This takes precedence over the max_xmit field in the
576 global struct. These different max_xmit variables should
577 be merged as this is now too confusing */
579 int data_to_send = datasize;
580 int params_to_send = paramsize;
584 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
585 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
586 int data_alignment_offset = 0;
588 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
590 set_message(outbuf,10,0,True);
592 /* If there genuinely are no parameters or data to send just send the empty packet */
594 if(params_to_send == 0 && data_to_send == 0) {
596 if (!send_smb(smbd_server_fd(),outbuf))
597 exit_server("send_trans2_replies: send_smb failed.");
601 /* When sending params and data ensure that both are nicely aligned */
602 /* Only do this alignment when there is also data to send - else
603 can cause NT redirector problems. */
605 if (((params_to_send % 4) != 0) && (data_to_send != 0))
606 data_alignment_offset = 4 - (params_to_send % 4);
608 /* Space is bufsize minus Netbios over TCP header minus SMB header */
609 /* The alignment_offset is to align the param bytes on an even byte
610 boundary. NT 4.0 Beta needs this to work correctly. */
612 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
614 /* useable_space can never be more than max_send minus the alignment offset. */
616 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
618 while (params_to_send || data_to_send) {
619 /* Calculate whether we will totally or partially fill this packet */
621 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
623 /* We can never send more than useable_space */
625 * Note that 'useable_space' does not include the alignment offsets,
626 * but we must include the alignment offsets in the calculation of
627 * the length of the data we send over the wire, as the alignment offsets
628 * are sent here. Fix from Marc_Jacobsen@hp.com.
631 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
633 set_message(outbuf, 10, total_sent_thistime, True);
635 /* Set total params and data to be sent */
636 SSVAL(outbuf,smb_tprcnt,paramsize);
637 SSVAL(outbuf,smb_tdrcnt,datasize);
639 /* Calculate how many parameters and data we can fit into
640 * this packet. Parameters get precedence
643 params_sent_thistime = MIN(params_to_send,useable_space);
644 data_sent_thistime = useable_space - params_sent_thistime;
645 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
647 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
649 /* smb_proff is the offset from the start of the SMB header to the
650 parameter bytes, however the first 4 bytes of outbuf are
651 the Netbios over TCP header. Thus use smb_base() to subtract
652 them from the calculation */
654 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
656 if(params_sent_thistime == 0)
657 SSVAL(outbuf,smb_prdisp,0);
659 /* Absolute displacement of param bytes sent in this packet */
660 SSVAL(outbuf,smb_prdisp,pp - params);
662 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
663 if(data_sent_thistime == 0) {
664 SSVAL(outbuf,smb_droff,0);
665 SSVAL(outbuf,smb_drdisp, 0);
667 /* The offset of the data bytes is the offset of the
668 parameter bytes plus the number of parameters being sent this time */
669 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
670 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
671 SSVAL(outbuf,smb_drdisp, pd - pdata);
674 /* Copy the param bytes into the packet */
676 if(params_sent_thistime)
677 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
679 /* Copy in the data bytes */
680 if(data_sent_thistime)
681 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
682 data_alignment_offset,pd,data_sent_thistime);
684 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
685 params_sent_thistime, data_sent_thistime, useable_space));
686 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
687 params_to_send, data_to_send, paramsize, datasize));
689 /* Send the packet */
691 if (!send_smb(smbd_server_fd(),outbuf))
692 exit_server("send_trans2_replies: send_smb failed.");
694 pp += params_sent_thistime;
695 pd += data_sent_thistime;
697 params_to_send -= params_sent_thistime;
698 data_to_send -= data_sent_thistime;
701 if(params_to_send < 0 || data_to_send < 0) {
702 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
703 params_to_send, data_to_send));
711 /****************************************************************************
712 Reply to a TRANSACT2_OPEN.
713 ****************************************************************************/
715 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
716 char **pparams, int total_params, char **ppdata, int total_data,
717 unsigned int max_data_bytes)
719 char *params = *pparams;
720 char *pdata = *ppdata;
725 BOOL return_additional_info;
736 SMB_STRUCT_STAT sbuf;
738 BOOL bad_path = False;
740 TALLOC_CTX *ctx = NULL;
741 struct ea_list *ea_list = NULL;
746 uint32 create_disposition;
747 uint32 create_options = 0;
750 * Ensure we have enough parameters to perform the operation.
753 if (total_params < 29) {
754 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
757 flags = SVAL(params, 0);
758 deny_mode = SVAL(params, 2);
759 open_attr = SVAL(params,6);
760 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
761 if (oplock_request) {
762 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
766 return_additional_info = BITSETW(params,0);
767 open_sattr = SVAL(params, 4);
768 open_time = make_unix_date3(params+8);
770 open_ofun = SVAL(params,12);
771 open_size = IVAL(params,14);
775 return(ERROR_DOS(ERRSRV,ERRaccess));
778 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
779 if (!NT_STATUS_IS_OK(status)) {
780 return ERROR_NT(status);
783 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
784 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
785 (unsigned int)open_ofun, open_size));
787 /* XXXX we need to handle passed times, sattr and flags */
789 unix_convert(fname,conn,0,&bad_path,&sbuf);
791 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
794 if (!check_name(fname,conn)) {
795 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
798 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
803 return ERROR_DOS(ERRDOS, ERRbadaccess);
806 /* Any data in this call is an EA list. */
807 if (total_data && !lp_ea_support(SNUM(conn))) {
808 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
812 if (total_data < 10) {
813 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
816 if (IVAL(pdata,0) > total_data) {
817 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
818 IVAL(pdata,0), (unsigned int)total_data));
819 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
822 ctx = talloc_init("TRANS2_OPEN_SET_EA");
824 return ERROR_NT(NT_STATUS_NO_MEMORY);
826 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
829 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
833 fsp = open_file_ntcreate(conn,fname,&sbuf,
844 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
845 /* We have re-scheduled this call. */
848 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
851 size = get_file_size(sbuf);
852 fattr = dos_mode(conn,fname,&sbuf);
853 mtime = sbuf.st_mtime;
857 close_file(fsp,False);
858 return(ERROR_DOS(ERRDOS,ERRnoaccess));
861 if (total_data && smb_action == FILE_WAS_CREATED) {
862 status = set_ea(conn, fsp, fname, ea_list);
864 if (!NT_STATUS_IS_OK(status)) {
865 close_file(fsp,False);
866 return ERROR_NT(status);
870 /* Realloc the size of parameters and data we will return */
871 params = SMB_REALLOC(*pparams, 30);
872 if( params == NULL ) {
873 return ERROR_NT(NT_STATUS_NO_MEMORY);
877 SSVAL(params,0,fsp->fnum);
878 SSVAL(params,2,open_attr);
879 put_dos_date2(params,4, mtime);
880 SIVAL(params,8, (uint32)size);
881 SSVAL(params,12,deny_mode);
882 SSVAL(params,14,0); /* open_type - file or directory. */
883 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
885 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
886 smb_action |= EXTENDED_OPLOCK_GRANTED;
889 SSVAL(params,18,smb_action);
892 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
894 SIVAL(params,20,inode);
895 SSVAL(params,24,0); /* Padding. */
897 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
898 SIVAL(params, 26, ea_size);
900 SIVAL(params, 26, 0);
903 /* Send the required number of replies */
904 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0);
909 /*********************************************************
910 Routine to check if a given string matches exactly.
911 as a special case a mask of "." does NOT match. That
912 is required for correct wildcard semantics
913 Case can be significant or not.
914 **********************************************************/
916 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
918 if (mask[0] == '.' && mask[1] == 0)
921 return strcmp(str,mask)==0;
922 if (StrCaseCmp(str,mask) != 0) {
925 if (ms_has_wild(str)) {
931 /****************************************************************************
932 Return the filetype for UNIX extensions.
933 ****************************************************************************/
935 static uint32 unix_filetype(mode_t mode)
938 return UNIX_TYPE_FILE;
939 else if(S_ISDIR(mode))
940 return UNIX_TYPE_DIR;
942 else if(S_ISLNK(mode))
943 return UNIX_TYPE_SYMLINK;
946 else if(S_ISCHR(mode))
947 return UNIX_TYPE_CHARDEV;
950 else if(S_ISBLK(mode))
951 return UNIX_TYPE_BLKDEV;
954 else if(S_ISFIFO(mode))
955 return UNIX_TYPE_FIFO;
958 else if(S_ISSOCK(mode))
959 return UNIX_TYPE_SOCKET;
962 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
963 return UNIX_TYPE_UNKNOWN;
966 /****************************************************************************
967 Map wire perms onto standard UNIX permissions. Obey share restrictions.
968 ****************************************************************************/
970 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
974 if (perms == SMB_MODE_NO_CHANGE)
977 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
978 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
979 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
980 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
981 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
982 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
983 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
984 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
985 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
987 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
990 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
993 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
996 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
997 ret &= lp_dir_mask(SNUM(conn));
998 /* Add in force bits */
999 ret |= lp_force_dir_mode(SNUM(conn));
1001 /* Apply mode mask */
1002 ret &= lp_create_mask(SNUM(conn));
1003 /* Add in force bits */
1004 ret |= lp_force_create_mode(SNUM(conn));
1010 /****************************************************************************
1011 Get a level dependent lanman2 dir entry.
1012 ****************************************************************************/
1014 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1015 void *inbuf, void *outbuf,
1016 char *path_mask,uint32 dirtype,int info_level,
1017 int requires_resume_key,
1018 BOOL dont_descend,char **ppdata,
1019 char *base_data, int space_remaining,
1020 BOOL *out_of_space, BOOL *got_exact_match,
1021 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1025 SMB_STRUCT_STAT sbuf;
1029 char *p, *q, *pdata = *ppdata;
1033 SMB_OFF_T file_size = 0;
1034 SMB_BIG_UINT allocation_size = 0;
1036 time_t mdate=0, adate=0, cdate=0;
1038 char *last_entry_ptr;
1040 uint32 nt_extmode; /* Used for NT connections instead of mode */
1041 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1042 BOOL check_mangled_names = lp_manglednames(SNUM(conn));
1045 *out_of_space = False;
1046 *got_exact_match = False;
1051 p = strrchr_m(path_mask,'/');
1054 pstrcpy(mask,"*.*");
1058 pstrcpy(mask, path_mask);
1063 /* Needed if we run out of space */
1064 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1065 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1068 * Due to bugs in NT client redirectors we are not using
1069 * resume keys any more - set them to zero.
1070 * Check out the related comments in findfirst/findnext.
1076 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1077 (long)conn->dirptr,curr_dirpos));
1082 pstrcpy(fname,dname);
1084 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
1085 got_match = mask_match(fname, mask, conn->case_sensitive);
1087 if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False, SNUM(conn))) {
1090 * It turns out that NT matches wildcards against
1091 * both long *and* short names. This may explain some
1092 * of the wildcard wierdness from old DOS clients
1093 * that some people have been seeing.... JRA.
1097 pstrcpy( newname, fname);
1098 mangle_map( newname, True, False, SNUM(conn));
1099 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
1100 got_match = mask_match(newname, mask, conn->case_sensitive);
1104 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1105 if (dont_descend && !isdots)
1108 pstrcpy(pathreal,conn->dirpath);
1110 pstrcat(pathreal,"/");
1111 pstrcat(pathreal,dname);
1113 if (INFO_LEVEL_IS_UNIX(info_level)) {
1114 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1115 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1116 pathreal,strerror(errno)));
1119 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1121 /* Needed to show the msdfs symlinks as
1124 if(lp_host_msdfs() &&
1125 lp_msdfs_root(SNUM(conn)) &&
1126 is_msdfs_link(NULL,conn, pathreal, NULL, NULL,
1129 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1130 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1134 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1135 pathreal,strerror(errno)));
1140 mode = dos_mode(conn,pathreal,&sbuf);
1142 if (!dir_check_ftype(conn,mode,dirtype)) {
1143 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1147 file_size = get_file_size(sbuf);
1148 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1149 mdate = sbuf.st_mtime;
1150 adate = sbuf.st_atime;
1151 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1153 if (lp_dos_filetime_resolution(SNUM(conn))) {
1160 /* This is necessary, as otherwise the
1161 * desktop.ini file in this folder is
1163 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
1167 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1173 mangle_map(fname,False,True,SNUM(conn));
1178 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1180 switch (info_level) {
1181 case SMB_FIND_INFO_STANDARD:
1182 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1183 if(requires_resume_key) {
1187 put_dos_date2(p,0,cdate);
1188 put_dos_date2(p,4,adate);
1189 put_dos_date2(p,8,mdate);
1190 SIVAL(p,12,(uint32)file_size);
1191 SIVAL(p,16,(uint32)allocation_size);
1195 p += align_string(outbuf, p, 0);
1196 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1197 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1199 SCVAL(nameptr, -1, len - 2);
1201 SCVAL(nameptr, -1, 0);
1205 SCVAL(nameptr, -1, len - 1);
1207 SCVAL(nameptr, -1, 0);
1213 case SMB_FIND_EA_SIZE:
1214 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1215 if(requires_resume_key) {
1219 put_dos_date2(p,0,cdate);
1220 put_dos_date2(p,4,adate);
1221 put_dos_date2(p,8,mdate);
1222 SIVAL(p,12,(uint32)file_size);
1223 SIVAL(p,16,(uint32)allocation_size);
1226 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1227 SIVAL(p,22,ea_size); /* Extended attributes */
1231 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1232 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1245 SCVAL(nameptr,0,len);
1247 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1250 case SMB_FIND_EA_LIST:
1252 struct ea_list *file_list = NULL;
1255 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1259 if(requires_resume_key) {
1263 put_dos_date2(p,0,cdate);
1264 put_dos_date2(p,4,adate);
1265 put_dos_date2(p,8,mdate);
1266 SIVAL(p,12,(uint32)file_size);
1267 SIVAL(p,16,(uint32)allocation_size);
1269 p += 22; /* p now points to the EA area. */
1271 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1272 name_list = ea_list_union(name_list, file_list, &ea_len);
1274 /* We need to determine if this entry will fit in the space available. */
1275 /* Max string size is 255 bytes. */
1276 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1277 /* Move the dirptr back to prev_dirpos */
1278 dptr_SeekDir(conn->dirptr, prev_dirpos);
1279 *out_of_space = True;
1280 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1281 return False; /* Not finished - just out of space */
1284 /* Push the ea_data followed by the name. */
1285 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1287 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1288 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1301 SCVAL(nameptr,0,len);
1303 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1307 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1308 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1309 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1311 SIVAL(p,0,reskey); p += 4;
1312 put_long_date(p,cdate); p += 8;
1313 put_long_date(p,adate); p += 8;
1314 put_long_date(p,mdate); p += 8;
1315 put_long_date(p,mdate); p += 8;
1316 SOFF_T(p,0,file_size); p += 8;
1317 SOFF_T(p,0,allocation_size); p += 8;
1318 SIVAL(p,0,nt_extmode); p += 4;
1319 q = p; p += 4; /* q is placeholder for name length. */
1321 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1322 SIVAL(p,0,ea_size); /* Extended attributes */
1325 /* Clear the short name buffer. This is
1326 * IMPORTANT as not doing so will trigger
1327 * a Win2k client bug. JRA.
1329 if (!was_8_3 && check_mangled_names) {
1330 pstring mangled_name;
1331 pstrcpy(mangled_name, fname);
1332 mangle_map(mangled_name,True,True,SNUM(conn));
1333 mangled_name[12] = 0;
1334 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1336 memset(p + 2 + len,'\0',24 - len);
1343 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1346 SIVAL(p,0,0); /* Ensure any padding is null. */
1347 len = PTR_DIFF(p, pdata);
1348 len = (len + 3) & ~3;
1353 case SMB_FIND_FILE_DIRECTORY_INFO:
1354 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1356 SIVAL(p,0,reskey); p += 4;
1357 put_long_date(p,cdate); p += 8;
1358 put_long_date(p,adate); p += 8;
1359 put_long_date(p,mdate); p += 8;
1360 put_long_date(p,mdate); p += 8;
1361 SOFF_T(p,0,file_size); p += 8;
1362 SOFF_T(p,0,allocation_size); p += 8;
1363 SIVAL(p,0,nt_extmode); p += 4;
1364 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1367 SIVAL(p,0,0); /* Ensure any padding is null. */
1368 len = PTR_DIFF(p, pdata);
1369 len = (len + 3) & ~3;
1374 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1375 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1377 SIVAL(p,0,reskey); p += 4;
1378 put_long_date(p,cdate); p += 8;
1379 put_long_date(p,adate); p += 8;
1380 put_long_date(p,mdate); p += 8;
1381 put_long_date(p,mdate); p += 8;
1382 SOFF_T(p,0,file_size); p += 8;
1383 SOFF_T(p,0,allocation_size); p += 8;
1384 SIVAL(p,0,nt_extmode); p += 4;
1385 q = p; p += 4; /* q is placeholder for name length. */
1387 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1388 SIVAL(p,0,ea_size); /* Extended attributes */
1391 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1395 SIVAL(p,0,0); /* Ensure any padding is null. */
1396 len = PTR_DIFF(p, pdata);
1397 len = (len + 3) & ~3;
1402 case SMB_FIND_FILE_NAMES_INFO:
1403 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1405 SIVAL(p,0,reskey); p += 4;
1407 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1408 acl on a dir (tridge) */
1409 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1412 SIVAL(p,0,0); /* Ensure any padding is null. */
1413 len = PTR_DIFF(p, pdata);
1414 len = (len + 3) & ~3;
1419 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1420 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1422 SIVAL(p,0,reskey); p += 4;
1423 put_long_date(p,cdate); p += 8;
1424 put_long_date(p,adate); p += 8;
1425 put_long_date(p,mdate); p += 8;
1426 put_long_date(p,mdate); p += 8;
1427 SOFF_T(p,0,file_size); p += 8;
1428 SOFF_T(p,0,allocation_size); p += 8;
1429 SIVAL(p,0,nt_extmode); p += 4;
1430 q = p; p += 4; /* q is placeholder for name length. */
1432 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1433 SIVAL(p,0,ea_size); /* Extended attributes */
1436 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1437 SIVAL(p,0,sbuf.st_dev); p += 4;
1438 SIVAL(p,0,sbuf.st_ino); p += 4;
1439 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1442 SIVAL(p,0,0); /* Ensure any padding is null. */
1443 len = PTR_DIFF(p, pdata);
1444 len = (len + 3) & ~3;
1449 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1450 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1451 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1453 SIVAL(p,0,reskey); p += 4;
1454 put_long_date(p,cdate); p += 8;
1455 put_long_date(p,adate); p += 8;
1456 put_long_date(p,mdate); p += 8;
1457 put_long_date(p,mdate); p += 8;
1458 SOFF_T(p,0,file_size); p += 8;
1459 SOFF_T(p,0,allocation_size); p += 8;
1460 SIVAL(p,0,nt_extmode); p += 4;
1461 q = p; p += 4; /* q is placeholder for name length */
1463 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1464 SIVAL(p,0,ea_size); /* Extended attributes */
1467 /* Clear the short name buffer. This is
1468 * IMPORTANT as not doing so will trigger
1469 * a Win2k client bug. JRA.
1471 if (!was_8_3 && check_mangled_names) {
1472 pstring mangled_name;
1473 pstrcpy(mangled_name, fname);
1474 mangle_map(mangled_name,True,True,SNUM(conn));
1475 mangled_name[12] = 0;
1476 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1479 memset(p + 2 + len,'\0',24 - len);
1486 SSVAL(p,0,0); p += 2; /* Reserved ? */
1487 SIVAL(p,0,sbuf.st_dev); p += 4;
1488 SIVAL(p,0,sbuf.st_ino); p += 4;
1489 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1492 SIVAL(p,0,0); /* Ensure any padding is null. */
1493 len = PTR_DIFF(p, pdata);
1494 len = (len + 3) & ~3;
1499 /* CIFS UNIX Extension. */
1501 case SMB_FIND_FILE_UNIX:
1502 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1504 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1506 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1507 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1510 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1513 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1514 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1515 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1518 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1522 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1526 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1529 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1533 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1537 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1540 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1544 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1548 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1550 SIVAL(p,0,0); /* Ensure any padding is null. */
1552 len = PTR_DIFF(p, pdata);
1553 len = (len + 3) & ~3;
1554 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1556 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1565 if (PTR_DIFF(p,pdata) > space_remaining) {
1566 /* Move the dirptr back to prev_dirpos */
1567 dptr_SeekDir(conn->dirptr, prev_dirpos);
1568 *out_of_space = True;
1569 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1570 return False; /* Not finished - just out of space */
1573 /* Setup the last entry pointer, as an offset from base_data */
1574 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1575 /* Advance the data pointer to the next slot */
1581 /****************************************************************************
1582 Reply to a TRANS2_FINDFIRST.
1583 ****************************************************************************/
1585 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1586 char **pparams, int total_params, char **ppdata, int total_data,
1587 unsigned int max_data_bytes)
1589 /* We must be careful here that we don't return more than the
1590 allowed number of data bytes. If this means returning fewer than
1591 maxentries then so be it. We assume that the redirector has
1592 enough room for the fixed number of parameter bytes it has
1594 char *params = *pparams;
1595 char *pdata = *ppdata;
1596 uint32 dirtype = SVAL(params,0);
1597 int maxentries = SVAL(params,2);
1598 uint16 findfirst_flags = SVAL(params,4);
1599 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1600 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1601 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1602 int info_level = SVAL(params,6);
1606 int last_entry_off=0;
1610 BOOL finished = False;
1611 BOOL dont_descend = False;
1612 BOOL out_of_space = False;
1613 int space_remaining;
1614 BOOL bad_path = False;
1615 SMB_STRUCT_STAT sbuf;
1616 TALLOC_CTX *ea_ctx = NULL;
1617 struct ea_list *ea_list = NULL;
1618 NTSTATUS ntstatus = NT_STATUS_OK;
1620 if (total_params < 12) {
1621 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1624 *directory = *mask = 0;
1626 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1627 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1628 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1629 info_level, max_data_bytes));
1632 /* W2K3 seems to treat zero as 1. */
1636 switch (info_level) {
1637 case SMB_FIND_INFO_STANDARD:
1638 case SMB_FIND_EA_SIZE:
1639 case SMB_FIND_EA_LIST:
1640 case SMB_FIND_FILE_DIRECTORY_INFO:
1641 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1642 case SMB_FIND_FILE_NAMES_INFO:
1643 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1644 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1645 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1647 case SMB_FIND_FILE_UNIX:
1648 if (!lp_unix_extensions())
1649 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1652 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1655 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1656 if (!NT_STATUS_IS_OK(ntstatus)) {
1657 return ERROR_NT(ntstatus);
1660 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1662 unix_convert(directory,conn,0,&bad_path,&sbuf);
1664 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1666 if(!check_name(directory,conn)) {
1667 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1670 p = strrchr_m(directory,'/');
1672 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1673 if((directory[0] == '.') && (directory[1] == '\0'))
1676 pstrcpy(mask,directory);
1677 pstrcpy(directory,"./");
1683 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1685 if (info_level == SMB_FIND_EA_LIST) {
1688 if (total_data < 4) {
1689 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1692 ea_size = IVAL(pdata,0);
1693 if (ea_size != total_data) {
1694 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1695 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1696 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1699 if (!lp_ea_support(SNUM(conn))) {
1700 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1703 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1704 return ERROR_NT(NT_STATUS_NO_MEMORY);
1707 /* Pull out the list of names. */
1708 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1710 talloc_destroy(ea_ctx);
1711 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1715 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1716 if( pdata == NULL ) {
1717 talloc_destroy(ea_ctx);
1718 return ERROR_NT(NT_STATUS_NO_MEMORY);
1723 /* Realloc the params space */
1724 params = SMB_REALLOC(*pparams, 10);
1725 if (params == NULL) {
1726 talloc_destroy(ea_ctx);
1727 return ERROR_NT(NT_STATUS_NO_MEMORY);
1731 /* Save the wildcard match and attribs we are using on this directory -
1732 needed as lanman2 assumes these are being saved between calls */
1734 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, dirtype);
1736 talloc_destroy(ea_ctx);
1737 return(UNIXERROR(ERRDOS,ERRbadfile));
1740 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1742 /* We don't need to check for VOL here as this is returned by
1743 a different TRANS2 call. */
1745 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1746 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1747 dont_descend = True;
1750 space_remaining = max_data_bytes;
1751 out_of_space = False;
1753 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1754 BOOL got_exact_match = False;
1756 /* this is a heuristic to avoid seeking the dirptr except when
1757 absolutely necessary. It allows for a filename of about 40 chars */
1758 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1759 out_of_space = True;
1762 finished = !get_lanman2_dir_entry(conn,
1764 mask,dirtype,info_level,
1765 requires_resume_key,dont_descend,
1766 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1767 &last_entry_off, ea_list, ea_ctx);
1770 if (finished && out_of_space)
1773 if (!finished && !out_of_space)
1777 * As an optimisation if we know we aren't looking
1778 * for a wildcard name (ie. the name matches the wildcard exactly)
1779 * then we can finish on any (first) match.
1780 * This speeds up large directory searches. JRA.
1786 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1789 talloc_destroy(ea_ctx);
1791 /* Check if we can close the dirptr */
1792 if(close_after_first || (finished && close_if_end)) {
1793 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1794 dptr_close(&dptr_num);
1798 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1799 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1800 * the protocol level is less than NT1. Tested with smbclient. JRA.
1801 * This should fix the OS/2 client bug #2335.
1804 if(numentries == 0) {
1805 dptr_close(&dptr_num);
1806 if (Protocol < PROTOCOL_NT1) {
1807 return ERROR_DOS(ERRDOS,ERRnofiles);
1809 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1813 /* At this point pdata points to numentries directory entries. */
1815 /* Set up the return parameter block */
1816 SSVAL(params,0,dptr_num);
1817 SSVAL(params,2,numentries);
1818 SSVAL(params,4,finished);
1819 SSVAL(params,6,0); /* Never an EA error */
1820 SSVAL(params,8,last_entry_off);
1822 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1824 if ((! *directory) && dptr_path(dptr_num))
1825 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1827 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1828 smb_fn_name(CVAL(inbuf,smb_com)),
1829 mask, directory, dirtype, numentries ) );
1832 * Force a name mangle here to ensure that the
1833 * mask as an 8.3 name is top of the mangled cache.
1834 * The reasons for this are subtle. Don't remove
1835 * this code unless you know what you are doing
1836 * (see PR#13758). JRA.
1839 if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn)))
1840 mangle_map(mask, True, True, SNUM(conn));
1845 /****************************************************************************
1846 Reply to a TRANS2_FINDNEXT.
1847 ****************************************************************************/
1849 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1850 char **pparams, int total_params, char **ppdata, int total_data,
1851 unsigned int max_data_bytes)
1853 /* We must be careful here that we don't return more than the
1854 allowed number of data bytes. If this means returning fewer than
1855 maxentries then so be it. We assume that the redirector has
1856 enough room for the fixed number of parameter bytes it has
1858 char *params = *pparams;
1859 char *pdata = *ppdata;
1860 int dptr_num = SVAL(params,0);
1861 int maxentries = SVAL(params,2);
1862 uint16 info_level = SVAL(params,4);
1863 uint32 resume_key = IVAL(params,6);
1864 uint16 findnext_flags = SVAL(params,10);
1865 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1866 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1867 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1868 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1869 pstring resume_name;
1875 int i, last_entry_off=0;
1876 BOOL finished = False;
1877 BOOL dont_descend = False;
1878 BOOL out_of_space = False;
1879 int space_remaining;
1880 TALLOC_CTX *ea_ctx = NULL;
1881 struct ea_list *ea_list = NULL;
1882 NTSTATUS ntstatus = NT_STATUS_OK;
1884 if (total_params < 12) {
1885 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1888 *mask = *directory = *resume_name = 0;
1890 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1891 if (!NT_STATUS_IS_OK(ntstatus)) {
1892 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1893 complain (it thinks we're asking for the directory above the shared
1894 path or an invalid name). Catch this as the resume name is only compared, never used in
1895 a file access. JRA. */
1896 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1897 pstrcpy(resume_name, "..");
1898 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1899 pstrcpy(resume_name, ".");
1901 return ERROR_NT(ntstatus);
1905 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1906 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1907 resume_key = %d resume name = %s continue=%d level = %d\n",
1908 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1909 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1912 /* W2K3 seems to treat zero as 1. */
1916 switch (info_level) {
1917 case SMB_FIND_INFO_STANDARD:
1918 case SMB_FIND_EA_SIZE:
1919 case SMB_FIND_EA_LIST:
1920 case SMB_FIND_FILE_DIRECTORY_INFO:
1921 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1922 case SMB_FIND_FILE_NAMES_INFO:
1923 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1925 case SMB_FIND_FILE_UNIX:
1926 if (!lp_unix_extensions())
1927 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1930 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1933 if (info_level == SMB_FIND_EA_LIST) {
1936 if (total_data < 4) {
1937 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1940 ea_size = IVAL(pdata,0);
1941 if (ea_size != total_data) {
1942 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1943 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1944 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1947 if (!lp_ea_support(SNUM(conn))) {
1948 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1951 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1952 return ERROR_NT(NT_STATUS_NO_MEMORY);
1955 /* Pull out the list of names. */
1956 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1958 talloc_destroy(ea_ctx);
1959 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1963 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1965 talloc_destroy(ea_ctx);
1966 return ERROR_NT(NT_STATUS_NO_MEMORY);
1971 /* Realloc the params space */
1972 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1973 if( params == NULL ) {
1974 talloc_destroy(ea_ctx);
1975 return ERROR_NT(NT_STATUS_NO_MEMORY);
1980 /* Check that the dptr is valid */
1981 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
1982 talloc_destroy(ea_ctx);
1983 return ERROR_DOS(ERRDOS,ERRnofiles);
1986 string_set(&conn->dirpath,dptr_path(dptr_num));
1988 /* Get the wildcard mask from the dptr */
1989 if((p = dptr_wcard(dptr_num))== NULL) {
1990 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1991 talloc_destroy(ea_ctx);
1992 return ERROR_DOS(ERRDOS,ERRnofiles);
1996 pstrcpy(directory,conn->dirpath);
1998 /* Get the attr mask from the dptr */
1999 dirtype = dptr_attr(dptr_num);
2001 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2002 dptr_num, mask, dirtype,
2004 dptr_TellDir(conn->dirptr)));
2006 /* We don't need to check for VOL here as this is returned by
2007 a different TRANS2 call. */
2009 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2010 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2011 dont_descend = True;
2014 space_remaining = max_data_bytes;
2015 out_of_space = False;
2018 * Seek to the correct position. We no longer use the resume key but
2019 * depend on the last file name instead.
2022 if(*resume_name && !continue_bit) {
2025 long current_pos = 0;
2027 * Remember, mangle_map is called by
2028 * get_lanman2_dir_entry(), so the resume name
2029 * could be mangled. Ensure we check the unmangled name.
2032 if (mangle_is_mangled(resume_name, SNUM(conn))) {
2033 mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn));
2037 * Fix for NT redirector problem triggered by resume key indexes
2038 * changing between directory scans. We now return a resume key of 0
2039 * and instead look for the filename to continue from (also given
2040 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2041 * findfirst/findnext (as is usual) then the directory pointer
2042 * should already be at the correct place.
2045 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2046 } /* end if resume_name && !continue_bit */
2048 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2049 BOOL got_exact_match = False;
2051 /* this is a heuristic to avoid seeking the dirptr except when
2052 absolutely necessary. It allows for a filename of about 40 chars */
2053 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2054 out_of_space = True;
2057 finished = !get_lanman2_dir_entry(conn,
2059 mask,dirtype,info_level,
2060 requires_resume_key,dont_descend,
2061 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2062 &last_entry_off, ea_list, ea_ctx);
2065 if (finished && out_of_space)
2068 if (!finished && !out_of_space)
2072 * As an optimisation if we know we aren't looking
2073 * for a wildcard name (ie. the name matches the wildcard exactly)
2074 * then we can finish on any (first) match.
2075 * This speeds up large directory searches. JRA.
2081 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2084 talloc_destroy(ea_ctx);
2086 /* Check if we can close the dirptr */
2087 if(close_after_request || (finished && close_if_end)) {
2088 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2089 dptr_close(&dptr_num); /* This frees up the saved mask */
2092 /* Set up the return parameter block */
2093 SSVAL(params,0,numentries);
2094 SSVAL(params,2,finished);
2095 SSVAL(params,4,0); /* Never an EA error */
2096 SSVAL(params,6,last_entry_off);
2098 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2100 if ((! *directory) && dptr_path(dptr_num))
2101 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2103 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2104 smb_fn_name(CVAL(inbuf,smb_com)),
2105 mask, directory, dirtype, numentries ) );
2110 /****************************************************************************
2111 Reply to a TRANS2_QFSINFO (query filesystem info).
2112 ****************************************************************************/
2114 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2115 char **pparams, int total_params, char **ppdata, int total_data,
2116 unsigned int max_data_bytes)
2118 char *pdata = *ppdata;
2119 char *params = *pparams;
2120 uint16 info_level = SVAL(params,0);
2123 char *vname = volume_label(SNUM(conn));
2124 int snum = SNUM(conn);
2125 char *fstype = lp_fstype(SNUM(conn));
2128 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2130 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2131 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2132 return ERROR_DOS(ERRSRV,ERRinvdevice);
2135 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2136 if ( pdata == NULL ) {
2137 return ERROR_NT(NT_STATUS_NO_MEMORY);
2141 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2143 switch (info_level) {
2144 case SMB_INFO_ALLOCATION:
2146 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2148 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2149 return(UNIXERROR(ERRHRD,ERRgeneral));
2152 block_size = lp_block_size(snum);
2153 if (bsize < block_size) {
2154 SMB_BIG_UINT factor = block_size/bsize;
2159 if (bsize > block_size) {
2160 SMB_BIG_UINT factor = bsize/block_size;
2165 bytes_per_sector = 512;
2166 sectors_per_unit = bsize/bytes_per_sector;
2168 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2169 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2170 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2172 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2173 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2174 SIVAL(pdata,l1_cUnit,dsize);
2175 SIVAL(pdata,l1_cUnitAvail,dfree);
2176 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2180 case SMB_INFO_VOLUME:
2181 /* Return volume name */
2183 * Add volume serial number - hash of a combination of
2184 * the called hostname and the service name.
2186 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2188 * Win2k3 and previous mess this up by sending a name length
2189 * one byte short. I believe only older clients (OS/2 Win9x) use
2190 * this call so try fixing this by adding a terminating null to
2191 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2193 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2194 SCVAL(pdata,l2_vol_cch,len);
2195 data_len = l2_vol_szVolLabel + len;
2196 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2197 (unsigned)st.st_ctime, len, vname));
2200 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2201 case SMB_FS_ATTRIBUTE_INFORMATION:
2204 #if defined(HAVE_SYS_QUOTAS)
2205 quota_flag = FILE_VOLUME_QUOTAS;
2208 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2209 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2210 quota_flag); /* FS ATTRIBUTES */
2212 SIVAL(pdata,4,255); /* Max filename component length */
2213 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2214 and will think we can't do long filenames */
2215 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2217 data_len = 12 + len;
2220 case SMB_QUERY_FS_LABEL_INFO:
2221 case SMB_FS_LABEL_INFORMATION:
2222 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2227 case SMB_QUERY_FS_VOLUME_INFO:
2228 case SMB_FS_VOLUME_INFORMATION:
2231 * Add volume serial number - hash of a combination of
2232 * the called hostname and the service name.
2234 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2235 (str_checksum(get_local_machine_name())<<16));
2237 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2238 SIVAL(pdata,12,len);
2240 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2241 (int)strlen(vname),vname, lp_servicename(snum)));
2244 case SMB_QUERY_FS_SIZE_INFO:
2245 case SMB_FS_SIZE_INFORMATION:
2247 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2249 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2250 return(UNIXERROR(ERRHRD,ERRgeneral));
2252 block_size = lp_block_size(snum);
2253 if (bsize < block_size) {
2254 SMB_BIG_UINT factor = block_size/bsize;
2259 if (bsize > block_size) {
2260 SMB_BIG_UINT factor = bsize/block_size;
2265 bytes_per_sector = 512;
2266 sectors_per_unit = bsize/bytes_per_sector;
2267 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2268 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2269 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2270 SBIG_UINT(pdata,0,dsize);
2271 SBIG_UINT(pdata,8,dfree);
2272 SIVAL(pdata,16,sectors_per_unit);
2273 SIVAL(pdata,20,bytes_per_sector);
2277 case SMB_FS_FULL_SIZE_INFORMATION:
2279 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2281 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2282 return(UNIXERROR(ERRHRD,ERRgeneral));
2284 block_size = lp_block_size(snum);
2285 if (bsize < block_size) {
2286 SMB_BIG_UINT factor = block_size/bsize;
2291 if (bsize > block_size) {
2292 SMB_BIG_UINT factor = bsize/block_size;
2297 bytes_per_sector = 512;
2298 sectors_per_unit = bsize/bytes_per_sector;
2299 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2300 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2301 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2302 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2303 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2304 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2305 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2306 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2310 case SMB_QUERY_FS_DEVICE_INFO:
2311 case SMB_FS_DEVICE_INFORMATION:
2313 SIVAL(pdata,0,0); /* dev type */
2314 SIVAL(pdata,4,0); /* characteristics */
2317 #ifdef HAVE_SYS_QUOTAS
2318 case SMB_FS_QUOTA_INFORMATION:
2320 * what we have to send --metze:
2322 * Unknown1: 24 NULL bytes
2323 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2324 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2325 * Quota Flags: 2 byte :
2326 * Unknown3: 6 NULL bytes
2330 * details for Quota Flags:
2332 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2333 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2334 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2335 * 0x0001 Enable Quotas: enable quota for this fs
2339 /* we need to fake up a fsp here,
2340 * because its not send in this call
2343 SMB_NTQUOTA_STRUCT quotas;
2346 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_QUERY_POSIX_FS_INFO:
2410 vfs_statvfs_struct svfs;
2412 if (!lp_unix_extensions())
2413 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2415 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2419 SIVAL(pdata,0,svfs.OptimalTransferSize);
2420 SIVAL(pdata,4,svfs.BlockSize);
2421 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2422 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2423 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2424 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2425 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2426 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2427 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2429 } else if (rc == EOPNOTSUPP) {
2430 return ERROR_DOS(ERRDOS, ERRunknownlevel);
2431 #endif /* EOPNOTSUPP */
2433 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2434 return ERROR_DOS(ERRSRV,ERRerror);
2439 case SMB_MAC_QUERY_FS_INFO:
2441 * Thursby MAC extension... ONLY on NTFS filesystems
2442 * once we do streams then we don't need this
2444 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2446 SIVAL(pdata,84,0x100); /* Don't support mac... */
2451 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2455 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2457 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2462 /****************************************************************************
2463 Reply to a TRANS2_SETFSINFO (set filesystem info).
2464 ****************************************************************************/
2466 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2467 char **pparams, int total_params, char **ppdata, int total_data,
2468 unsigned int max_data_bytes)
2470 char *pdata = *ppdata;
2471 char *params = *pparams;
2475 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2478 if (total_params < 4) {
2479 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2481 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2484 info_level = SVAL(params,2);
2486 switch(info_level) {
2487 case SMB_SET_CIFS_UNIX_INFO:
2489 uint16 client_unix_major;
2490 uint16 client_unix_minor;
2491 uint32 client_unix_cap_low;
2492 uint32 client_unix_cap_high;
2494 if (!lp_unix_extensions()) {
2495 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2498 /* There should be 12 bytes of capabilities set. */
2499 if (total_data < 8) {
2500 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2502 client_unix_major = SVAL(pdata,0);
2503 client_unix_minor = SVAL(pdata,2);
2504 client_unix_cap_low = IVAL(pdata,4);
2505 client_unix_cap_high = IVAL(pdata,8);
2506 /* Just print these values for now. */
2507 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2508 cap_low = 0x%x, cap_high = 0x%x\n",
2509 (unsigned int)client_unix_major,
2510 (unsigned int)client_unix_minor,
2511 (unsigned int)client_unix_cap_low,
2512 (unsigned int)client_unix_cap_high ));
2514 /* Here is where we must switch to posix pathname processing... */
2515 lp_set_posix_pathnames();
2516 mangle_change_to_posix();
2519 case SMB_FS_QUOTA_INFORMATION:
2521 files_struct *fsp = NULL;
2522 SMB_NTQUOTA_STRUCT quotas;
2524 ZERO_STRUCT(quotas);
2527 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2528 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2529 lp_servicename(SNUM(conn)),conn->user));
2530 return ERROR_DOS(ERRSRV,ERRaccess);
2533 /* note: normaly there're 48 bytes,
2534 * but we didn't use the last 6 bytes for now
2537 fsp = file_fsp(params,0);
2538 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2539 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2540 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2543 if (total_data < 42) {
2544 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2546 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2549 /* unknown_1 24 NULL bytes in pdata*/
2551 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2552 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2553 #ifdef LARGE_SMB_OFF_T
2554 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2555 #else /* LARGE_SMB_OFF_T */
2556 if ((IVAL(pdata,28) != 0)&&
2557 ((quotas.softlim != 0xFFFFFFFF)||
2558 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2559 /* more than 32 bits? */
2560 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2562 #endif /* LARGE_SMB_OFF_T */
2564 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2565 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2566 #ifdef LARGE_SMB_OFF_T
2567 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2568 #else /* LARGE_SMB_OFF_T */
2569 if ((IVAL(pdata,36) != 0)&&
2570 ((quotas.hardlim != 0xFFFFFFFF)||
2571 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2572 /* more than 32 bits? */
2573 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2575 #endif /* LARGE_SMB_OFF_T */
2577 /* quota_flags 2 bytes **/
2578 quotas.qflags = SVAL(pdata,40);
2580 /* unknown_2 6 NULL bytes follow*/
2582 /* now set the quotas */
2583 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2584 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2585 return ERROR_DOS(ERRSRV,ERRerror);
2591 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2593 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2598 * sending this reply works fine,
2599 * but I'm not sure it's the same
2600 * like windows do...
2603 outsize = set_message(outbuf,10,0,True);
2608 /****************************************************************************
2609 Utility function to set bad path error.
2610 ****************************************************************************/
2612 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2614 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2615 err, (int)bad_path ));
2619 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2621 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2624 return UNIXERROR(def_class,def_code);
2627 #if defined(HAVE_POSIX_ACLS)
2628 /****************************************************************************
2629 Utility function to count the number of entries in a POSIX acl.
2630 ****************************************************************************/
2632 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2634 unsigned int ace_count = 0;
2635 int entry_id = SMB_ACL_FIRST_ENTRY;
2636 SMB_ACL_ENTRY_T entry;
2638 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2640 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2641 entry_id = SMB_ACL_NEXT_ENTRY;
2648 /****************************************************************************
2649 Utility function to marshall a POSIX acl into wire format.
2650 ****************************************************************************/
2652 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2654 int entry_id = SMB_ACL_FIRST_ENTRY;
2655 SMB_ACL_ENTRY_T entry;
2657 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2658 SMB_ACL_TAG_T tagtype;
2659 SMB_ACL_PERMSET_T permset;
2660 unsigned char perms = 0;
2661 unsigned int own_grp;
2664 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2665 entry_id = SMB_ACL_NEXT_ENTRY;
2668 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2669 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2673 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2674 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2678 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2679 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2680 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2682 SCVAL(pdata,1,perms);
2685 case SMB_ACL_USER_OBJ:
2686 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2687 own_grp = (unsigned int)pst->st_uid;
2688 SIVAL(pdata,2,own_grp);
2693 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2695 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2697 own_grp = (unsigned int)*puid;
2698 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2699 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2700 SIVAL(pdata,2,own_grp);
2704 case SMB_ACL_GROUP_OBJ:
2705 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2706 own_grp = (unsigned int)pst->st_gid;
2707 SIVAL(pdata,2,own_grp);
2712 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2714 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2716 own_grp = (unsigned int)*pgid;
2717 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2718 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2719 SIVAL(pdata,2,own_grp);
2724 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2725 SIVAL(pdata,2,0xFFFFFFFF);
2726 SIVAL(pdata,6,0xFFFFFFFF);
2729 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2730 SIVAL(pdata,2,0xFFFFFFFF);
2731 SIVAL(pdata,6,0xFFFFFFFF);
2734 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2737 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2744 /****************************************************************************
2745 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2746 file name or file id).
2747 ****************************************************************************/
2749 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2750 unsigned int tran_call,
2751 char **pparams, int total_params, char **ppdata, int total_data,
2752 unsigned int max_data_bytes)
2754 char *params = *pparams;
2755 char *pdata = *ppdata;
2759 SMB_OFF_T file_size=0;
2760 SMB_BIG_UINT allocation_size=0;
2761 unsigned int data_size = 0;
2762 unsigned int param_size = 2;
2763 SMB_STRUCT_STAT sbuf;
2764 pstring fname, dos_fname;
2769 BOOL bad_path = False;
2770 BOOL delete_pending = False;
2773 files_struct *fsp = NULL;
2774 TALLOC_CTX *ea_ctx = NULL;
2775 struct ea_list *ea_list = NULL;
2776 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2779 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2783 if (tran_call == TRANSACT2_QFILEINFO) {
2784 if (total_params < 4) {
2785 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2788 fsp = file_fsp(params,0);
2789 info_level = SVAL(params,2);
2791 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2793 if(fsp && (fsp->fake_file_handle)) {
2795 * This is actually for the QUOTA_FAKE_FILE --metze
2798 pstrcpy(fname, fsp->fsp_name);
2799 /* We know this name is ok, it's already passed the checks. */
2801 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2803 * This is actually a QFILEINFO on a directory
2804 * handle (returned from an NT SMB). NT5.0 seems
2805 * to do this call. JRA.
2807 /* We know this name is ok, it's already passed the checks. */
2808 pstrcpy(fname, fsp->fsp_name);
2810 if (INFO_LEVEL_IS_UNIX(info_level)) {
2811 /* Always do lstat for UNIX calls. */
2812 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2813 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2814 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2816 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2817 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2818 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2822 get_delete_on_close_flag(sbuf.st_dev,
2827 * Original code - this is an open file.
2829 CHECK_FSP(fsp,conn);
2831 pstrcpy(fname, fsp->fsp_name);
2832 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2833 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2834 return(UNIXERROR(ERRDOS,ERRbadfid));
2836 pos = fsp->fh->position_information;
2838 get_delete_on_close_flag(sbuf.st_dev,
2841 access_mask = fsp->access_mask;
2844 NTSTATUS status = NT_STATUS_OK;
2847 if (total_params < 6) {
2848 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2851 info_level = SVAL(params,0);
2853 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2855 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2856 if (!NT_STATUS_IS_OK(status)) {
2857 return ERROR_NT(status);
2860 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2862 unix_convert(fname,conn,0,&bad_path,&sbuf);
2864 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2866 if (!check_name(fname,conn)) {
2867 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2868 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2871 if (INFO_LEVEL_IS_UNIX(info_level)) {
2872 /* Always do lstat for UNIX calls. */
2873 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2874 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2875 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2877 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2878 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2879 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2882 delete_pending = get_delete_on_close_flag(sbuf.st_dev,
2885 if (delete_pending) {
2886 return ERROR_NT(NT_STATUS_DELETE_PENDING);
2890 nlink = sbuf.st_nlink;
2892 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2893 /* NTFS does not seem to count ".." */
2897 if ((nlink > 0) && delete_pending) {
2901 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2902 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2904 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2905 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2907 p = strrchr_m(fname,'/');
2913 mode = dos_mode(conn,fname,&sbuf);
2915 mode = FILE_ATTRIBUTE_NORMAL;
2917 fullpathname = fname;
2918 file_size = get_file_size(sbuf);
2920 /* This is necessary, as otherwise the desktop.ini file in
2921 * this folder is ignored */
2922 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2926 /* Pull any EA list from the data portion. */
2927 if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2930 if (total_data < 4) {
2931 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2933 ea_size = IVAL(pdata,0);
2935 if (total_data > 0 && ea_size != total_data) {
2936 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2937 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2938 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2941 if (!lp_ea_support(SNUM(conn))) {
2942 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2945 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2946 return ERROR_NT(NT_STATUS_NO_MEMORY);
2949 /* Pull out the list of names. */
2950 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2952 talloc_destroy(ea_ctx);
2953 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2957 params = SMB_REALLOC(*pparams,2);
2958 if (params == NULL) {
2959 talloc_destroy(ea_ctx);
2960 return ERROR_NT(NT_STATUS_NO_MEMORY);
2964 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2965 pdata = SMB_REALLOC(*ppdata, data_size);
2966 if ( pdata == NULL ) {
2967 talloc_destroy(ea_ctx);
2968 return ERROR_NT(NT_STATUS_NO_MEMORY);
2972 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2974 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2977 if (fsp->pending_modtime) {
2978 /* the pending modtime overrides the current modtime */
2979 sbuf.st_mtime = fsp->pending_modtime;
2982 /* Do we have this path open ? */
2983 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2984 if (fsp1 && fsp1->pending_modtime) {
2985 /* the pending modtime overrides the current modtime */
2986 sbuf.st_mtime = fsp1->pending_modtime;
2988 if (fsp1 && fsp1->initial_allocation_size) {
2989 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
2993 if (lp_dos_filetime_resolution(SNUM(conn))) {
2995 sbuf.st_atime &= ~1;
2996 sbuf.st_ctime &= ~1;
2997 sbuf.st_mtime &= ~1;
3000 /* NT expects the name to be in an exact form of the *full*
3001 filename. See the trans2 torture test */
3002 if (strequal(base_name,".")) {
3003 pstrcpy(dos_fname, "\\");
3005 pstr_sprintf(dos_fname, "\\%s", fname);
3006 string_replace(dos_fname, '/', '\\');
3009 switch (info_level) {
3010 case SMB_INFO_STANDARD:
3011 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3013 put_dos_date2(pdata,l1_fdateCreation,c_time);
3014 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
3015 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
3016 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3017 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3018 SSVAL(pdata,l1_attrFile,mode);
3021 case SMB_INFO_QUERY_EA_SIZE:
3023 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3024 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3026 put_dos_date2(pdata,0,c_time);
3027 put_dos_date2(pdata,4,sbuf.st_atime);
3028 put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */
3029 SIVAL(pdata,12,(uint32)file_size);
3030 SIVAL(pdata,16,(uint32)allocation_size);
3031 SSVAL(pdata,20,mode);
3032 SIVAL(pdata,22,ea_size);
3036 case SMB_INFO_IS_NAME_VALID:
3037 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3038 if (tran_call == TRANSACT2_QFILEINFO) {
3039 /* os/2 needs this ? really ?*/
3040 return ERROR_DOS(ERRDOS,ERRbadfunc);
3046 case SMB_INFO_QUERY_EAS_FROM_LIST:
3048 size_t total_ea_len = 0;
3049 struct ea_list *ea_file_list = NULL;
3051 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3053 ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3054 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3056 if (!ea_list || (total_ea_len > data_size)) {
3057 talloc_destroy(ea_ctx);
3059 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3063 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3064 talloc_destroy(ea_ctx);
3068 case SMB_INFO_QUERY_ALL_EAS:
3070 /* We have data_size bytes to put EA's into. */
3071 size_t total_ea_len = 0;
3073 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3075 ea_ctx = talloc_init("ea_ctx");
3077 return ERROR_NT(NT_STATUS_NO_MEMORY);
3080 ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3081 if (!ea_list || (total_ea_len > data_size)) {
3082 talloc_destroy(ea_ctx);
3084 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3088 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3089 talloc_destroy(ea_ctx);
3093 case SMB_FILE_BASIC_INFORMATION:
3094 case SMB_QUERY_FILE_BASIC_INFO:
3096 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3097 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3098 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3100 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3104 put_long_date(pdata,c_time);
3105 put_long_date(pdata+8,sbuf.st_atime);
3106 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3107 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3108 SIVAL(pdata,32,mode);
3110 DEBUG(5,("SMB_QFBI - "));
3112 time_t create_time = c_time;
3113 DEBUG(5,("create: %s ", ctime(&create_time)));
3115 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3116 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3117 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3118 DEBUG(5,("mode: %x\n", mode));
3121 case SMB_FILE_STANDARD_INFORMATION:
3122 case SMB_QUERY_FILE_STANDARD_INFO:
3124 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3126 SOFF_T(pdata,0,allocation_size);
3127 SOFF_T(pdata,8,file_size);
3128 SIVAL(pdata,16,nlink);
3129 SCVAL(pdata,20,delete_pending?1:0);
3130 SCVAL(pdata,21,(mode&aDIR)?1:0);
3131 SSVAL(pdata,22,0); /* Padding. */
3134 case SMB_FILE_EA_INFORMATION:
3135 case SMB_QUERY_FILE_EA_INFO:
3137 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3138 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3140 SIVAL(pdata,0,ea_size);
3144 /* Get the 8.3 name - used if NT SMB was negotiated. */
3145 case SMB_QUERY_FILE_ALT_NAME_INFO:
3146 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3150 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3151 pstrcpy(short_name,base_name);
3152 /* Mangle if not already 8.3 */
3153 if(!mangle_is_8_3(short_name, True, SNUM(conn))) {
3154 mangle_map(short_name,True,True,SNUM(conn));
3156 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3157 data_size = 4 + len;
3162 case SMB_QUERY_FILE_NAME_INFO:
3164 this must be *exactly* right for ACLs on mapped drives to work
3166 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3167 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3168 data_size = 4 + len;
3172 case SMB_FILE_ALLOCATION_INFORMATION:
3173 case SMB_QUERY_FILE_ALLOCATION_INFO:
3174 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3176 SOFF_T(pdata,0,allocation_size);
3179 case SMB_FILE_END_OF_FILE_INFORMATION:
3180 case SMB_QUERY_FILE_END_OF_FILEINFO:
3181 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3183 SOFF_T(pdata,0,file_size);
3186 case SMB_QUERY_FILE_ALL_INFO:
3187 case SMB_FILE_ALL_INFORMATION:
3189 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3190 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3191 put_long_date(pdata,c_time);
3192 put_long_date(pdata+8,sbuf.st_atime);
3193 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3194 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3195 SIVAL(pdata,32,mode);
3196 SIVAL(pdata,36,0); /* padding. */
3198 SOFF_T(pdata,0,allocation_size);
3199 SOFF_T(pdata,8,file_size);
3200 SIVAL(pdata,16,nlink);
3201 SCVAL(pdata,20,delete_pending);
3202 SCVAL(pdata,21,(mode&aDIR)?1:0);
3205 SIVAL(pdata,0,ea_size);
3206 pdata += 4; /* EA info */
3207 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3210 data_size = PTR_DIFF(pdata,(*ppdata));
3213 case SMB_FILE_INTERNAL_INFORMATION:
3214 /* This should be an index number - looks like
3217 I think this causes us to fail the IFSKIT
3218 BasicFileInformationTest. -tpot */
3220 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3221 SIVAL(pdata,0,sbuf.st_dev);
3222 SIVAL(pdata,4,sbuf.st_ino);
3226 case SMB_FILE_ACCESS_INFORMATION:
3227 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3228 SIVAL(pdata,0,access_mask);
3232 case SMB_FILE_NAME_INFORMATION:
3233 /* Pathname with leading '\'. */
3236 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
3237 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3238 SIVAL(pdata,0,byte_len);
3239 data_size = 4 + byte_len;
3243 case SMB_FILE_DISPOSITION_INFORMATION:
3244 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3246 SCVAL(pdata,0,delete_pending);
3249 case SMB_FILE_POSITION_INFORMATION:
3250 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3252 SOFF_T(pdata,0,pos);
3255 case SMB_FILE_MODE_INFORMATION:
3256 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3257 SIVAL(pdata,0,mode);
3261 case SMB_FILE_ALIGNMENT_INFORMATION:
3262 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3263 SIVAL(pdata,0,0); /* No alignment needed. */
3269 * NT4 server just returns "invalid query" to this - if we try to answer
3270 * it then NTws gets a BSOD! (tridge).
3271 * W2K seems to want this. JRA.
3273 case SMB_QUERY_FILE_STREAM_INFO:
3275 case SMB_FILE_STREAM_INFORMATION:
3276 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3280 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
3281 SIVAL(pdata,0,0); /* ??? */
3282 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3283 SOFF_T(pdata,8,file_size);
3284 SIVAL(pdata,16,allocation_size);
3285 SIVAL(pdata,20,0); /* ??? */
3286 data_size = 24 + byte_len;
3290 case SMB_QUERY_COMPRESSION_INFO:
3291 case SMB_FILE_COMPRESSION_INFORMATION:
3292 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3293 SOFF_T(pdata,0,file_size);
3294 SIVAL(pdata,8,0); /* ??? */
3295 SIVAL(pdata,12,0); /* ??? */
3299 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3300 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3301 put_long_date(pdata,c_time);
3302 put_long_date(pdata+8,sbuf.st_atime);
3303 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3304 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3305 SIVAL(pdata,32,allocation_size);
3306 SOFF_T(pdata,40,file_size);
3307 SIVAL(pdata,48,mode);
3308 SIVAL(pdata,52,0); /* ??? */
3312 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3313 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3314 SIVAL(pdata,0,mode);
3320 * CIFS UNIX Extensions.
3323 case SMB_QUERY_FILE_UNIX_BASIC:
3325 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3326 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3328 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3331 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3334 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3335 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3336 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3339 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3343 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3347 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3350 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3354 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3358 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3361 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3365 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3368 data_size = PTR_DIFF(pdata,(*ppdata));
3372 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3374 for (i=0; i<100; i++)
3375 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3381 case SMB_QUERY_FILE_UNIX_LINK:
3385 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3387 if(!S_ISLNK(sbuf.st_mode))
3388 return(UNIXERROR(ERRSRV,ERRbadlink));
3390 return(UNIXERROR(ERRDOS,ERRbadlink));
3392 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3394 return(UNIXERROR(ERRDOS,ERRnoaccess));
3396 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3398 data_size = PTR_DIFF(pdata,(*ppdata));
3403 #if defined(HAVE_POSIX_ACLS)
3404 case SMB_QUERY_POSIX_ACL:
3406 SMB_ACL_T file_acl = NULL;
3407 SMB_ACL_T def_acl = NULL;
3408 uint16 num_file_acls = 0;
3409 uint16 num_def_acls = 0;
3411 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3412 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3414 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3417 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3418 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3420 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3423 if (S_ISDIR(sbuf.st_mode)) {
3424 if (fsp && fsp->is_directory) {
3425 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3427 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3429 def_acl = free_empty_sys_acl(conn, def_acl);
3432 num_file_acls = count_acl_entries(conn, file_acl);
3433 num_def_acls = count_acl_entries(conn, def_acl);
3435 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3436 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3438 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3439 SMB_POSIX_ACL_HEADER_SIZE) ));
3441 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3444 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3446 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3449 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3450 SSVAL(pdata,2,num_file_acls);
3451 SSVAL(pdata,4,num_def_acls);
3452 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3454 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3457 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3459 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3461 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3463 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3466 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3468 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3472 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3475 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3477 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3483 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3486 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3491 /****************************************************************************
3492 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3494 ****************************************************************************/
3496 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3498 BOOL bad_path_oldname = False;
3499 BOOL bad_path_newname = False;
3500 SMB_STRUCT_STAT sbuf1, sbuf2;
3501 pstring last_component_oldname;
3502 pstring last_component_newname;
3503 NTSTATUS status = NT_STATUS_OK;
3509 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3510 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3513 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3514 if (bad_path_oldname) {
3515 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3518 /* Quick check for "." and ".." */
3519 if (last_component_oldname[0] == '.') {
3520 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3521 return NT_STATUS_OBJECT_NAME_INVALID;
3525 /* source must already exist. */
3526 if (!VALID_STAT(sbuf1)) {
3527 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3530 if (!check_name(oldname,conn)) {
3531 return NT_STATUS_ACCESS_DENIED;
3534 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3535 if (bad_path_newname) {
3536 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3539 /* Quick check for "." and ".." */
3540 if (last_component_newname[0] == '.') {
3541 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3542 return NT_STATUS_OBJECT_NAME_INVALID;
3546 /* Disallow if newname already exists. */
3547 if (VALID_STAT(sbuf2)) {
3548 return NT_STATUS_OBJECT_NAME_COLLISION;
3551 if (!check_name(newname,conn)) {
3552 return NT_STATUS_ACCESS_DENIED;
3555 /* No links from a directory. */
3556 if (S_ISDIR(sbuf1.st_mode)) {
3557 return NT_STATUS_FILE_IS_A_DIRECTORY;
3560 /* Ensure this is within the share. */
3561 if (!reduce_name(conn, oldname) != 0)
3562 return NT_STATUS_ACCESS_DENIED;
3564 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3566 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3567 status = map_nt_error_from_unix(errno);
3568 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3569 nt_errstr(status), newname, oldname));
3575 /****************************************************************************
3576 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3577 ****************************************************************************/
3579 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3580 unsigned int tran_call,
3581 char **pparams, int total_params, char **ppdata, int total_data,
3582 unsigned int max_data_bytes)
3584 char *params = *pparams;
3585 char *pdata = *ppdata;
3590 SMB_STRUCT_STAT sbuf;
3593 BOOL bad_path = False;
3594 files_struct *fsp = NULL;
3595 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3596 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3597 mode_t unixmode = 0;
3598 NTSTATUS status = NT_STATUS_OK;
3601 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3606 if (tran_call == TRANSACT2_SETFILEINFO) {
3607 if (total_params < 4) {
3608 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3611 fsp = file_fsp(params,0);
3612 info_level = SVAL(params,2);
3614 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3616 * This is actually a SETFILEINFO on a directory
3617 * handle (returned from an NT SMB). NT5.0 seems
3618 * to do this call. JRA.
3620 pstrcpy(fname, fsp->fsp_name);
3621 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3622 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3623 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3625 } else if (fsp && fsp->print_file) {
3627 * Doing a DELETE_ON_CLOSE should cancel a print job.
3629 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3630 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
3632 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3635 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3638 return (UNIXERROR(ERRDOS,ERRbadpath));
3641 * Original code - this is an open file.
3643 CHECK_FSP(fsp,conn);
3645 pstrcpy(fname, fsp->fsp_name);
3648 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3649 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3650 return(UNIXERROR(ERRDOS,ERRbadfid));
3655 if (total_params < 6) {
3656 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3659 info_level = SVAL(params,0);
3660 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3661 if (!NT_STATUS_IS_OK(status)) {
3662 return ERROR_NT(status);
3664 unix_convert(fname,conn,0,&bad_path,&sbuf);
3666 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3670 * For CIFS UNIX extensions the target name may not exist.
3673 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3674 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3675 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3678 if(!check_name(fname, conn)) {
3679 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3684 if (!CAN_WRITE(conn))
3685 return ERROR_DOS(ERRSRV,ERRaccess);
3687 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3688 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3690 if (VALID_STAT(sbuf))
3691 unixmode = sbuf.st_mode;
3693 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3694 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3696 /* Realloc the parameter size */
3697 params = SMB_REALLOC(*pparams,2);
3698 if(params == NULL) {
3699 return ERROR_NT(NT_STATUS_NO_MEMORY);
3705 if (fsp && fsp->pending_modtime) {
3706 /* the pending modtime overrides the current modtime */
3707 sbuf.st_mtime = fsp->pending_modtime;
3710 size = get_file_size(sbuf);
3711 tvs.modtime = sbuf.st_mtime;
3712 tvs.actime = sbuf.st_atime;
3713 dosmode = dos_mode(conn,fname,&sbuf);
3714 unixmode = sbuf.st_mode;
3716 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3717 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3719 switch (info_level) {
3720 case SMB_INFO_STANDARD:
3722 if (total_data < 12) {
3723 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3727 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3729 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3733 case SMB_INFO_SET_EA:
3735 struct ea_list *ea_list = NULL;
3736 TALLOC_CTX *ctx = NULL;
3738 if (total_data < 10) {
3739 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3742 if (IVAL(pdata,0) > total_data) {
3743 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3744 IVAL(pdata,0), (unsigned int)total_data));
3745 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3748 ctx = talloc_init("SMB_INFO_SET_EA");
3750 return ERROR_NT(NT_STATUS_NO_MEMORY);
3752 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3754 talloc_destroy(ctx);
3755 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3757 status = set_ea(conn, fsp, fname, ea_list);
3758 talloc_destroy(ctx);
3760 if (!NT_STATUS_IS_OK(status)) {
3761 return ERROR_NT(status);
3764 /* We're done. We only get EA info in this call. */
3766 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3771 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3772 /* XXXX um, i don't think this is right.
3773 it's also not in the cifs6.txt spec.
3775 case SMB_INFO_QUERY_EAS_FROM_LIST:
3776 if (total_data < 28)
3777 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3779 tvs.actime = make_unix_date2(pdata+8);
3780 tvs.modtime = make_unix_date2(pdata+12);
3781 size = IVAL(pdata,16);
3782 dosmode = IVAL(pdata,24);
3785 /* XXXX nor this. not in cifs6.txt, either. */
3786 case SMB_INFO_QUERY_ALL_EAS:
3787 if (total_data < 28)
3788 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3790 tvs.actime = make_unix_date2(pdata+8);
3791 tvs.modtime = make_unix_date2(pdata+12);
3792 size = IVAL(pdata,16);
3793 dosmode = IVAL(pdata,24);
3797 case SMB_SET_FILE_BASIC_INFO:
3798 case SMB_FILE_BASIC_INFORMATION:
3800 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3802 time_t changed_time;
3804 if (total_data < 36) {
3805 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3808 /* Ignore create time at offset pdata. */
3811 tvs.actime = interpret_long_date(pdata+8);
3813 write_time = interpret_long_date(pdata+16);
3814 changed_time = interpret_long_date(pdata+24);
3816 tvs.modtime = MIN(write_time, changed_time);
3818 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3819 tvs.modtime = write_time;
3821 /* Prefer a defined time to an undefined one. */
3822 if (null_mtime(tvs.modtime)) {
3823 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3827 dosmode = IVAL(pdata,32);
3831 case SMB_FILE_ALLOCATION_INFORMATION:
3832 case SMB_SET_FILE_ALLOCATION_INFO:
3835 SMB_BIG_UINT allocation_size;
3837 if (total_data < 8) {
3838 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3841 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3842 #ifdef LARGE_SMB_OFF_T
3843 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3844 #else /* LARGE_SMB_OFF_T */
3845 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3846 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3847 #endif /* LARGE_SMB_OFF_T */
3848 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3849 fname, (double)allocation_size ));
3851 if (allocation_size) {
3852 allocation_size = smb_roundup(conn, allocation_size);
3855 if(allocation_size != get_file_size(sbuf)) {
3856 SMB_STRUCT_STAT new_sbuf;
3858 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3859 fname, (double)allocation_size ));
3862 files_struct *new_fsp = NULL;
3864 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
3866 FILE_SHARE_READ|FILE_SHARE_WRITE,
3869 FILE_ATTRIBUTE_NORMAL,
3873 if (new_fsp == NULL) {
3874 return(UNIXERROR(ERRDOS,ERRbadpath));
3876 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3877 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
3878 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3879 new_fsp->fnum, strerror(errno)));
3882 close_file(new_fsp,True);
3884 ret = vfs_allocate_file_space(fsp, allocation_size);
3885 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3886 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3887 fsp->fnum, strerror(errno)));
3892 return ERROR_NT(NT_STATUS_DISK_FULL);
3894 /* Allocate can truncate size... */
3895 size = get_file_size(new_sbuf);
3901 case SMB_FILE_END_OF_FILE_INFORMATION:
3902 case SMB_SET_FILE_END_OF_FILE_INFO:
3904 if (total_data < 8) {
3905 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3908 size = IVAL(pdata,0);
3909 #ifdef LARGE_SMB_OFF_T
3910 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3911 #else /* LARGE_SMB_OFF_T */
3912 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3913 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3914 #endif /* LARGE_SMB_OFF_T */
3915 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3919 case SMB_FILE_DISPOSITION_INFORMATION:
3920 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3922 BOOL delete_on_close;
3924 if (total_data < 1) {
3925 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3928 delete_on_close = (CVAL(pdata,0) ? True : False);
3930 /* Just ignore this set on a path. */
3931 if (tran_call != TRANSACT2_SETFILEINFO)
3935 return(UNIXERROR(ERRDOS,ERRbadfid));
3937 status = can_set_delete_on_close(fsp, delete_on_close,
3940 if (!NT_STATUS_IS_OK(status)) {
3941 return ERROR_NT(status);
3944 /* The set is across all open files on this dev/inode pair. */
3945 if (!set_delete_on_close(fsp, delete_on_close)) {
3946 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3950 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3954 case SMB_FILE_POSITION_INFORMATION:
3956 SMB_BIG_UINT position_information;
3958 if (total_data < 8) {
3959 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3962 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3963 #ifdef LARGE_SMB_OFF_T
3964 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3965 #else /* LARGE_SMB_OFF_T */
3966 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3967 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3968 #endif /* LARGE_SMB_OFF_T */
3969 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3970 fname, (double)position_information ));
3972 fsp->fh->position_information = position_information;
3975 /* We're done. We only get position info in this call. */
3977 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3981 /* From tridge Samba4 :
3982 * MODE_INFORMATION in setfileinfo (I have no
3983 * idea what "mode information" on a file is - it takes a value of 0,
3984 * 2, 4 or 6. What could it be?).
3987 case SMB_FILE_MODE_INFORMATION:
3991 if (total_data < 4) {
3992 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3994 mode = IVAL(pdata,0);
3995 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
3996 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3999 /* We're done. We only get mode info in this call. */
4001 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4006 * CIFS UNIX extensions.
4009 case SMB_SET_FILE_UNIX_BASIC:
4011 uint32 raw_unixmode;
4013 if (total_data < 100) {
4014 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4017 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4018 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4019 size=IVAL(pdata,0); /* first 8 Bytes are size */
4020 #ifdef LARGE_SMB_OFF_T
4021 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4022 #else /* LARGE_SMB_OFF_T */
4023 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
4024 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4025 #endif /* LARGE_SMB_OFF_T */
4027 pdata+=24; /* ctime & st_blocks are not changed */
4028 tvs.actime = interpret_long_date(pdata); /* access_time */
4029 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
4031 set_owner = (uid_t)IVAL(pdata,0);
4033 set_grp = (gid_t)IVAL(pdata,0);
4035 raw_unixmode = IVAL(pdata,28);
4036 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4037 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4039 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4040 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4041 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4043 if (!VALID_STAT(sbuf)) {
4046 * The only valid use of this is to create character and block
4047 * devices, and named pipes. This is deprecated (IMHO) and
4048 * a new info level should be used for mknod. JRA.
4051 uint32 file_type = IVAL(pdata,0);
4052 #if defined(HAVE_MAKEDEV)
4053 uint32 dev_major = IVAL(pdata,4);
4054 uint32 dev_minor = IVAL(pdata,12);
4057 uid_t myuid = geteuid();
4058 gid_t mygid = getegid();
4059 SMB_DEV_T dev = (SMB_DEV_T)0;
4061 if (tran_call == TRANSACT2_SETFILEINFO)
4062 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4064 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4065 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4068 #if defined(HAVE_MAKEDEV)
4069 dev = makedev(dev_major, dev_minor);
4072 /* We can only create as the owner/group we are. */
4074 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4075 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4076 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4077 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4079 switch (file_type) {
4080 #if defined(S_IFIFO)
4081 case UNIX_TYPE_FIFO:
4082 unixmode |= S_IFIFO;
4085 #if defined(S_IFSOCK)
4086 case UNIX_TYPE_SOCKET:
4087 unixmode |= S_IFSOCK;
4090 #if defined(S_IFCHR)
4091 case UNIX_TYPE_CHARDEV:
4092 unixmode |= S_IFCHR;
4095 #if defined(S_IFBLK)
4096 case UNIX_TYPE_BLKDEV:
4097 unixmode |= S_IFBLK;
4101 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4104 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4105 0%o for file %s\n", (double)dev, unixmode, fname ));
4107 /* Ok - do the mknod. */
4108 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4109 return(UNIXERROR(ERRDOS,ERRnoaccess));
4111 inherit_access_acl(conn, fname, unixmode);
4114 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4119 * Deal with the UNIX specific mode set.
4122 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4123 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4124 (unsigned int)unixmode, fname ));
4125 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4126 return(UNIXERROR(ERRDOS,ERRnoaccess));
4130 * Deal with the UNIX specific uid set.
4133 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4134 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4135 (unsigned int)set_owner, fname ));
4136 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4137 return(UNIXERROR(ERRDOS,ERRnoaccess));
4141 * Deal with the UNIX specific gid set.
4144 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4145 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4146 (unsigned int)set_owner, fname ));
4147 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4148 return(UNIXERROR(ERRDOS,ERRnoaccess));
4153 case SMB_SET_FILE_UNIX_LINK:
4155 pstring link_target;
4156 char *newname = fname;
4158 /* Set a symbolic link. */
4159 /* Don't allow this if follow links is false. */
4161 if (!lp_symlinks(SNUM(conn)))
4162 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4164 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4166 /* !widelinks forces the target path to be within the share. */
4167 /* This means we can interpret the target as a pathname. */
4168 if (!lp_widelinks(SNUM(conn))) {
4170 char *last_dirp = NULL;
4172 unix_format(link_target);
4173 if (*link_target == '/') {
4174 /* No absolute paths allowed. */
4175 return(UNIXERROR(ERRDOS,ERRnoaccess));
4177 pstrcpy(rel_name, newname);
4178 last_dirp = strrchr_m(rel_name, '/');
4180 last_dirp[1] = '\0';
4182 pstrcpy(rel_name, "./");
4184 pstrcat(rel_name, link_target);
4186 if (!check_name(rel_name, conn)) {
4187 return(UNIXERROR(ERRDOS,ERRnoaccess));
4191 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4192 fname, link_target ));
4194 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4195 return(UNIXERROR(ERRDOS,ERRnoaccess));
4197 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4201 case SMB_SET_FILE_UNIX_HLINK:
4204 char *newname = fname;
4206 /* Set a hard link. */
4207 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
4208 if (!NT_STATUS_IS_OK(status)) {
4209 return ERROR_NT(status);
4212 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4215 status = hardlink_internals(conn, oldname, newname);
4216 if (!NT_STATUS_IS_OK(status)) {
4217 return ERROR_NT(status);
4221 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4225 case SMB_FILE_RENAME_INFORMATION:
4234 if (total_data < 12) {
4235 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4238 overwrite = (CVAL(pdata,0) ? True : False);
4239 root_fid = IVAL(pdata,4);
4240 len = IVAL(pdata,8);
4241 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
4242 if (!NT_STATUS_IS_OK(status)) {
4243 return ERROR_NT(status);
4246 /* Check the new name has no '/' characters. */
4247 if (strchr_m(newname, '/'))
4248 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4250 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4252 /* Create the base directory. */
4253 pstrcpy(base_name, fname);
4254 p = strrchr_m(base_name, '/');
4257 /* Append the new name. */
4258 pstrcat(base_name, "/");
4259 pstrcat(base_name, newname);
4262 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4263 fsp->fnum, fsp->fsp_name, base_name ));
4264 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4266 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4268 status = rename_internals(conn, fname, base_name, 0, overwrite);
4270 if (!NT_STATUS_IS_OK(status)) {
4271 return ERROR_NT(status);
4273 process_pending_change_notify_queue((time_t)0);
4275 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4279 #if defined(HAVE_POSIX_ACLS)
4280 case SMB_SET_POSIX_ACL:
4282 uint16 posix_acl_version;
4283 uint16 num_file_acls;
4284 uint16 num_def_acls;
4285 BOOL valid_file_acls = True;
4286 BOOL valid_def_acls = True;
4288 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4289 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4291 posix_acl_version = SVAL(pdata,0);
4292 num_file_acls = SVAL(pdata,2);
4293 num_def_acls = SVAL(pdata,4);
4295 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4296 valid_file_acls = False;
4300 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4301 valid_def_acls = False;
4305 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4306 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4309 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4310 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4311 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4314 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4315 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4316 return(UNIXERROR(ERRDOS,ERRnoaccess));
4319 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4320 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4321 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4322 return(UNIXERROR(ERRDOS,ERRnoaccess));
4326 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4332 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4335 /* get some defaults (no modifications) if any info is zero or -1. */
4336 if (null_mtime(tvs.actime)) {
4337 tvs.actime = sbuf.st_atime;
4340 if (null_mtime(tvs.modtime)) {
4341 tvs.modtime = sbuf.st_mtime;
4344 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4345 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4346 DEBUG(6,("size: %.0f ", (double)size));
4349 if (S_ISDIR(sbuf.st_mode))
4355 DEBUG(6,("dosmode: %x\n" , dosmode));
4357 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4358 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4359 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4360 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4363 * Only do this test if we are not explicitly
4364 * changing the size of a file.
4367 size = get_file_size(sbuf);
4371 * Try and set the times, size and mode of this file -
4372 * if they are different from the current values
4375 /* check the mode isn't different, before changing it */
4376 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4378 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4380 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4381 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4382 return(UNIXERROR(ERRDOS,ERRnoaccess));
4387 if (size != get_file_size(sbuf)) {
4391 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4392 fname, (double)size ));
4395 files_struct *new_fsp = NULL;
4397 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
4399 FILE_SHARE_READ|FILE_SHARE_WRITE,
4402 FILE_ATTRIBUTE_NORMAL,
4406 if (new_fsp == NULL) {
4407 return(UNIXERROR(ERRDOS,ERRbadpath));
4409 ret = vfs_set_filelen(new_fsp, size);
4410 close_file(new_fsp,True);
4412 ret = vfs_set_filelen(fsp, size);
4416 return (UNIXERROR(ERRHRD,ERRdiskfull));
4421 * Finally the times.
4423 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4426 * This was a setfileinfo on an open file.
4427 * NT does this a lot. We also need to
4428 * set the time here, as it can be read by
4429 * FindFirst/FindNext and with the patch for bug #2045
4430 * in smbd/fileio.c it ensures that this timestamp is
4431 * kept sticky even after a write. We save the request
4432 * away and will set it on file close and after a write. JRA.
4435 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4436 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4437 fsp_set_pending_modtime(fsp, tvs.modtime);
4441 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4443 if(file_utime(conn, fname, &tvs)!=0) {
4444 return(UNIXERROR(ERRDOS,ERRnoaccess));
4449 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4454 /****************************************************************************
4455 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4456 ****************************************************************************/
4458 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4459 char **pparams, int total_params, char **ppdata, int total_data,
4460 unsigned int max_data_bytes)
4462 char *params = *pparams;
4463 char *pdata = *ppdata;
4466 SMB_STRUCT_STAT sbuf;
4467 BOOL bad_path = False;
4468 NTSTATUS status = NT_STATUS_OK;
4469 TALLOC_CTX *ctx = NULL;
4470 struct ea_list *ea_list = NULL;
4472 if (!CAN_WRITE(conn))
4473 return ERROR_DOS(ERRSRV,ERRaccess);
4475 if (total_params < 4) {
4476 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4479 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4480 if (!NT_STATUS_IS_OK(status)) {
4481 return ERROR_NT(status);
4484 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4486 unix_convert(directory,conn,0,&bad_path,&sbuf);
4488 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4491 /* Any data in this call is an EA list. */
4492 if (total_data && !lp_ea_support(SNUM(conn))) {
4493 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4497 if (total_data < 10) {
4498 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4501 if (IVAL(pdata,0) > total_data) {
4502 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4503 IVAL(pdata,0), (unsigned int)total_data));
4504 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4507 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4509 return ERROR_NT(NT_STATUS_NO_MEMORY);
4511 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4513 talloc_destroy(ctx);
4514 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4518 if (check_name(directory,conn)) {
4519 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4523 talloc_destroy(ctx);
4524 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4525 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4528 /* Try and set any given EA. */
4530 status = set_ea(conn, NULL, directory, ea_list);
4531 talloc_destroy(ctx);
4532 if (!NT_STATUS_IS_OK(status)) {
4533 return ERROR_NT(status);
4537 /* Realloc the parameter and data sizes */
4538 params = SMB_REALLOC(*pparams,2);
4539 if(params == NULL) {
4540 return ERROR_NT(NT_STATUS_NO_MEMORY);
4546 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4551 /****************************************************************************
4552 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4553 We don't actually do this - we just send a null response.
4554 ****************************************************************************/
4556 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4557 char **pparams, int total_params, char **ppdata, int total_data,
4558 unsigned int max_data_bytes)
4560 static uint16 fnf_handle = 257;
4561 char *params = *pparams;
4564 if (total_params < 6) {
4565 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4568 info_level = SVAL(params,4);
4569 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4571 switch (info_level) {
4576 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4579 /* Realloc the parameter and data sizes */
4580 params = SMB_REALLOC(*pparams,6);
4581 if(params == NULL) {
4582 return ERROR_NT(NT_STATUS_NO_MEMORY);
4586 SSVAL(params,0,fnf_handle);
4587 SSVAL(params,2,0); /* No changes */
4588 SSVAL(params,4,0); /* No EA errors */
4595 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4600 /****************************************************************************
4601 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4602 changes). Currently this does nothing.
4603 ****************************************************************************/
4605 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4606 char **pparams, int total_params, char **ppdata, int total_data,
4607 unsigned int max_data_bytes)
4609 char *params = *pparams;
4611 DEBUG(3,("call_trans2findnotifynext\n"));
4613 /* Realloc the parameter and data sizes */
4614 params = SMB_REALLOC(*pparams,4);
4615 if(params == NULL) {
4616 return ERROR_NT(NT_STATUS_NO_MEMORY);
4620 SSVAL(params,0,0); /* No changes */
4621 SSVAL(params,2,0); /* No EA errors */
4623 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4628 /****************************************************************************
4629 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4630 ****************************************************************************/
4632 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4633 char **pparams, int total_params, char **ppdata, int total_data,
4634 unsigned int max_data_bytes)
4636 char *params = *pparams;
4639 int max_referral_level;
4641 DEBUG(10,("call_trans2getdfsreferral\n"));
4643 if (total_params < 2) {
4644 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4647 max_referral_level = SVAL(params,0);
4649 if(!lp_host_msdfs())
4650 return ERROR_DOS(ERRDOS,ERRbadfunc);
4652 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4653 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4654 return UNIXERROR(ERRDOS,ERRbadfile);
4656 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4657 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4662 #define LMCAT_SPL 0x53
4663 #define LMFUNC_GETJOBID 0x60
4665 /****************************************************************************
4666 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4667 ****************************************************************************/
4669 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4670 char **pparams, int total_params, char **ppdata, int total_data,
4671 unsigned int max_data_bytes)
4673 char *pdata = *ppdata;
4674 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4676 /* check for an invalid fid before proceeding */
4679 return(ERROR_DOS(ERRDOS,ERRbadfid));
4681 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4682 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4683 pdata = SMB_REALLOC(*ppdata, 32);
4685 return ERROR_NT(NT_STATUS_NO_MEMORY);
4689 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4690 CAN ACCEPT THIS IN UNICODE. JRA. */
4692 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4693 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4694 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4695 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4698 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4699 return ERROR_DOS(ERRSRV,ERRerror);
4703 /****************************************************************************
4704 Reply to a SMBfindclose (stop trans2 directory search).
4705 ****************************************************************************/
4707 int reply_findclose(connection_struct *conn,
4708 char *inbuf,char *outbuf,int length,int bufsize)
4711 int dptr_num=SVALS(inbuf,smb_vwv0);
4712 START_PROFILE(SMBfindclose);
4714 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4716 dptr_close(&dptr_num);
4718 outsize = set_message(outbuf,0,0,True);
4720 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4722 END_PROFILE(SMBfindclose);
4726 /****************************************************************************
4727 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4728 ****************************************************************************/
4730 int reply_findnclose(connection_struct *conn,
4731 char *inbuf,char *outbuf,int length,int bufsize)
4735 START_PROFILE(SMBfindnclose);
4737 dptr_num = SVAL(inbuf,smb_vwv0);
4739 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4741 /* We never give out valid handles for a
4742 findnotifyfirst - so any dptr_num is ok here.
4745 outsize = set_message(outbuf,0,0,True);
4747 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4749 END_PROFILE(SMBfindnclose);
4753 /****************************************************************************
4754 Reply to a SMBtranss2 - just ignore it!
4755 ****************************************************************************/
4757 int reply_transs2(connection_struct *conn,
4758 char *inbuf,char *outbuf,int length,int bufsize)
4760 START_PROFILE(SMBtranss2);
4761 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4762 END_PROFILE(SMBtranss2);
4766 /****************************************************************************
4767 Reply to a SMBtrans2.
4768 ****************************************************************************/
4770 int reply_trans2(connection_struct *conn,
4771 char *inbuf,char *outbuf,int length,int bufsize)
4774 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4775 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4776 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4778 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4779 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4780 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4781 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4782 int32 timeout = IVALS(inbuf,smb_timeout);
4784 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4785 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4786 char *params = NULL, *data = NULL;
4787 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4788 START_PROFILE(SMBtrans2);
4790 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4791 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4792 END_PROFILE(SMBtrans2);
4793 return ERROR_DOS(ERRSRV,ERRaccess);
4796 outsize = set_message(outbuf,0,0,True);
4798 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4799 is so as a sanity check */
4802 * Need to have rc=0 for ioctl to get job id for OS/2.
4803 * Network printing will fail if function is not successful.
4804 * Similar function in reply.c will be used if protocol
4805 * is LANMAN1.0 instead of LM1.2X002.
4806 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4807 * outbuf doesn't have to be set(only job id is used).
4809 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4810 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4811 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4812 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4814 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4815 DEBUG(2,("Transaction is %d\n",tran_call));
4816 END_PROFILE(SMBtrans2);
4817 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4821 /* Allocate the space for the maximum needed parameters and data */
4822 if (total_params > 0)
4823 params = (char *)SMB_MALLOC(total_params);
4825 data = (char *)SMB_MALLOC(total_data);
4827 if ((total_params && !params) || (total_data && !data)) {
4828 DEBUG(2,("Out of memory in reply_trans2\n"));
4831 END_PROFILE(SMBtrans2);
4832 return ERROR_NT(NT_STATUS_NO_MEMORY);
4835 /* Copy the param and data bytes sent with this request into
4836 the params buffer */
4837 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4838 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4840 if (num_params > total_params || num_data > total_data)
4841 exit_server("invalid params in reply_trans2");
4844 unsigned int psoff = SVAL(inbuf, smb_psoff);
4845 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4847 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4848 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4850 memcpy( params, smb_base(inbuf) + psoff, num_params);
4853 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4854 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4856 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4857 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4859 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4862 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4864 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4865 /* We need to send an interim response then receive the rest
4866 of the parameter/data bytes */
4867 outsize = set_message(outbuf,0,0,True);
4868 srv_signing_trans_stop();
4870 if (!send_smb(smbd_server_fd(),outbuf))
4871 exit_server("reply_trans2: send_smb failed.");
4873 while (num_data_sofar < total_data ||
4874 num_params_sofar < total_params) {
4876 unsigned int param_disp;
4877 unsigned int param_off;
4878 unsigned int data_disp;
4879 unsigned int data_off;
4881 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4883 /* We need to re-calcuate the new length after we've read the secondary packet. */
4884 length = smb_len(inbuf) + 4;
4887 * The sequence number for the trans reply is always
4888 * based on the last secondary received.
4891 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4894 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4895 outsize = set_message(outbuf,0,0,True);
4897 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4899 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4900 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4904 /* Revise total_params and total_data in case
4905 they have changed downwards */
4906 if (SVAL(inbuf, smb_tpscnt) < total_params)
4907 total_params = SVAL(inbuf, smb_tpscnt);
4908 if (SVAL(inbuf, smb_tdscnt) < total_data)
4909 total_data = SVAL(inbuf, smb_tdscnt);
4911 num_params = SVAL(inbuf,smb_spscnt);
4912 param_off = SVAL(inbuf, smb_spsoff);
4913 param_disp = SVAL(inbuf, smb_spsdisp);
4914 num_params_sofar += num_params;
4916 num_data = SVAL(inbuf, smb_sdscnt);
4917 data_off = SVAL(inbuf, smb_sdsoff);
4918 data_disp = SVAL(inbuf, smb_sdsdisp);
4919 num_data_sofar += num_data;
4921 if (num_params_sofar > total_params || num_data_sofar > total_data)
4925 if (param_disp + num_params > total_params)
4927 if ((param_disp + num_params < param_disp) ||
4928 (param_disp + num_params < num_params))
4930 if (param_disp > total_params)
4932 if ((smb_base(inbuf) + param_off + num_params > inbuf + length) ||
4933 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4935 if (params + param_disp < params)
4938 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
4941 if (data_disp + num_data > total_data)
4943 if ((data_disp + num_data < data_disp) ||
4944 (data_disp + num_data < num_data))
4946 if (data_disp > total_data)
4948 if ((smb_base(inbuf) + data_off + num_data > inbuf + length) ||
4949 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4951 if (data + data_disp < data)
4954 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4959 if (Protocol >= PROTOCOL_NT1) {
4960 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4963 /* Now we must call the relevant TRANS2 function */
4965 case TRANSACT2_OPEN:
4966 START_PROFILE_NESTED(Trans2_open);
4967 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4968 ¶ms, total_params, &data, total_data, max_data_bytes);
4969 END_PROFILE_NESTED(Trans2_open);
4972 case TRANSACT2_FINDFIRST:
4973 START_PROFILE_NESTED(Trans2_findfirst);
4974 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4975 ¶ms, total_params, &data, total_data, max_data_bytes);
4976 END_PROFILE_NESTED(Trans2_findfirst);
4979 case TRANSACT2_FINDNEXT:
4980 START_PROFILE_NESTED(Trans2_findnext);
4981 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4982 ¶ms, total_params, &data, total_data, max_data_bytes);
4983 END_PROFILE_NESTED(Trans2_findnext);
4986 case TRANSACT2_QFSINFO:
4987 START_PROFILE_NESTED(Trans2_qfsinfo);
4988 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4989 ¶ms, total_params, &data, total_data, max_data_bytes);
4990 END_PROFILE_NESTED(Trans2_qfsinfo);
4993 case TRANSACT2_SETFSINFO:
4994 START_PROFILE_NESTED(Trans2_setfsinfo);
4995 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4996 ¶ms, total_params, &data, total_data, max_data_bytes);
4997 END_PROFILE_NESTED(Trans2_setfsinfo);
5000 case TRANSACT2_QPATHINFO:
5001 case TRANSACT2_QFILEINFO:
5002 START_PROFILE_NESTED(Trans2_qpathinfo);
5003 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5004 ¶ms, total_params, &data, total_data, max_data_bytes);
5005 END_PROFILE_NESTED(Trans2_qpathinfo);
5007 case TRANSACT2_SETPATHINFO:
5008 case TRANSACT2_SETFILEINFO:
5009 START_PROFILE_NESTED(Trans2_setpathinfo);
5010 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5011 ¶ms, total_params, &data, total_data, max_data_bytes);
5012 END_PROFILE_NESTED(Trans2_setpathinfo);
5015 case TRANSACT2_FINDNOTIFYFIRST:
5016 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5017 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
5018 ¶ms, total_params, &data, total_data, max_data_bytes);
5019 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5022 case TRANSACT2_FINDNOTIFYNEXT:
5023 START_PROFILE_NESTED(Trans2_findnotifynext);
5024 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
5025 ¶ms, total_params, &data, total_data, max_data_bytes);
5026 END_PROFILE_NESTED(Trans2_findnotifynext);
5028 case TRANSACT2_MKDIR:
5029 START_PROFILE_NESTED(Trans2_mkdir);
5030 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
5031 ¶ms, total_params, &data, total_data, max_data_bytes);
5032 END_PROFILE_NESTED(Trans2_mkdir);
5035 case TRANSACT2_GET_DFS_REFERRAL:
5036 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5037 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
5038 ¶ms, total_params, &data, total_data, max_data_bytes);
5039 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5041 case TRANSACT2_IOCTL:
5042 START_PROFILE_NESTED(Trans2_ioctl);
5043 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
5044 ¶ms, total_params, &data, total_data, max_data_bytes);
5045 END_PROFILE_NESTED(Trans2_ioctl);
5048 /* Error in request */
5049 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
5052 END_PROFILE(SMBtrans2);
5053 srv_signing_trans_stop();
5054 return ERROR_DOS(ERRSRV,ERRerror);
5057 /* As we do not know how many data packets will need to be
5058 returned here the various call_trans2xxxx calls
5059 must send their own. Thus a call_trans2xxx routine only
5060 returns a value other than -1 when it wants to send
5064 srv_signing_trans_stop();
5068 END_PROFILE(SMBtrans2);
5069 return outsize; /* If a correct response was needed the
5070 call_trans2xxx calls have already sent
5071 it. If outsize != -1 then it is returning */
5075 srv_signing_trans_stop();
5078 END_PROFILE(SMBtrans2);
5079 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);