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);
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 && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
808 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
811 if (total_data != 4) {
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);
831 } else if (IVAL(pdata,0) != 4) {
832 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
835 fsp = open_file_ntcreate(conn,fname,&sbuf,
846 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
847 /* We have re-scheduled this call. */
850 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
853 size = get_file_size(sbuf);
854 fattr = dos_mode(conn,fname,&sbuf);
855 mtime = sbuf.st_mtime;
859 close_file(fsp,False);
860 return(ERROR_DOS(ERRDOS,ERRnoaccess));
863 if (total_data && smb_action == FILE_WAS_CREATED) {
864 status = set_ea(conn, fsp, fname, ea_list);
866 if (!NT_STATUS_IS_OK(status)) {
867 close_file(fsp,False);
868 return ERROR_NT(status);
872 /* Realloc the size of parameters and data we will return */
873 params = SMB_REALLOC(*pparams, 30);
874 if( params == NULL ) {
875 return ERROR_NT(NT_STATUS_NO_MEMORY);
879 SSVAL(params,0,fsp->fnum);
880 SSVAL(params,2,open_attr);
881 srv_put_dos_date2(params,4, mtime);
882 SIVAL(params,8, (uint32)size);
883 SSVAL(params,12,deny_mode);
884 SSVAL(params,14,0); /* open_type - file or directory. */
885 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
887 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
888 smb_action |= EXTENDED_OPLOCK_GRANTED;
891 SSVAL(params,18,smb_action);
894 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
896 SIVAL(params,20,inode);
897 SSVAL(params,24,0); /* Padding. */
899 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
900 SIVAL(params, 26, ea_size);
902 SIVAL(params, 26, 0);
905 /* Send the required number of replies */
906 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0);
911 /*********************************************************
912 Routine to check if a given string matches exactly.
913 as a special case a mask of "." does NOT match. That
914 is required for correct wildcard semantics
915 Case can be significant or not.
916 **********************************************************/
918 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
920 if (mask[0] == '.' && mask[1] == 0)
923 return strcmp(str,mask)==0;
924 if (StrCaseCmp(str,mask) != 0) {
927 if (ms_has_wild(str)) {
933 /****************************************************************************
934 Return the filetype for UNIX extensions.
935 ****************************************************************************/
937 static uint32 unix_filetype(mode_t mode)
940 return UNIX_TYPE_FILE;
941 else if(S_ISDIR(mode))
942 return UNIX_TYPE_DIR;
944 else if(S_ISLNK(mode))
945 return UNIX_TYPE_SYMLINK;
948 else if(S_ISCHR(mode))
949 return UNIX_TYPE_CHARDEV;
952 else if(S_ISBLK(mode))
953 return UNIX_TYPE_BLKDEV;
956 else if(S_ISFIFO(mode))
957 return UNIX_TYPE_FIFO;
960 else if(S_ISSOCK(mode))
961 return UNIX_TYPE_SOCKET;
964 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
965 return UNIX_TYPE_UNKNOWN;
968 /****************************************************************************
969 Map wire perms onto standard UNIX permissions. Obey share restrictions.
970 ****************************************************************************/
972 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
976 if (perms == SMB_MODE_NO_CHANGE)
979 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
980 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
981 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
982 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
983 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
984 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
985 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
986 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
987 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
989 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
992 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
995 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
998 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
999 ret &= lp_dir_mask(SNUM(conn));
1000 /* Add in force bits */
1001 ret |= lp_force_dir_mode(SNUM(conn));
1003 /* Apply mode mask */
1004 ret &= lp_create_mask(SNUM(conn));
1005 /* Add in force bits */
1006 ret |= lp_force_create_mode(SNUM(conn));
1012 /****************************************************************************
1013 Get a level dependent lanman2 dir entry.
1014 ****************************************************************************/
1016 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1017 void *inbuf, void *outbuf,
1018 char *path_mask,uint32 dirtype,int info_level,
1019 int requires_resume_key,
1020 BOOL dont_descend,char **ppdata,
1021 char *base_data, int space_remaining,
1022 BOOL *out_of_space, BOOL *got_exact_match,
1023 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1027 SMB_STRUCT_STAT sbuf;
1031 char *p, *q, *pdata = *ppdata;
1035 SMB_OFF_T file_size = 0;
1036 SMB_BIG_UINT allocation_size = 0;
1038 time_t mdate=0, adate=0, cdate=0;
1040 char *last_entry_ptr;
1042 uint32 nt_extmode; /* Used for NT connections instead of mode */
1043 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1044 BOOL check_mangled_names = lp_manglednames(SNUM(conn));
1047 *out_of_space = False;
1048 *got_exact_match = False;
1053 p = strrchr_m(path_mask,'/');
1056 pstrcpy(mask,"*.*");
1060 pstrcpy(mask, path_mask);
1065 /* Needed if we run out of space */
1066 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1067 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1070 * Due to bugs in NT client redirectors we are not using
1071 * resume keys any more - set them to zero.
1072 * Check out the related comments in findfirst/findnext.
1078 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1079 (long)conn->dirptr,curr_dirpos));
1084 pstrcpy(fname,dname);
1086 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
1087 got_match = mask_match(fname, mask, conn->case_sensitive);
1089 if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False, SNUM(conn))) {
1092 * It turns out that NT matches wildcards against
1093 * both long *and* short names. This may explain some
1094 * of the wildcard wierdness from old DOS clients
1095 * that some people have been seeing.... JRA.
1099 pstrcpy( newname, fname);
1100 mangle_map( newname, True, False, SNUM(conn));
1101 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
1102 got_match = mask_match(newname, mask, conn->case_sensitive);
1106 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1107 if (dont_descend && !isdots)
1110 pstrcpy(pathreal,conn->dirpath);
1112 pstrcat(pathreal,"/");
1113 pstrcat(pathreal,dname);
1115 if (INFO_LEVEL_IS_UNIX(info_level)) {
1116 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1117 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1118 pathreal,strerror(errno)));
1121 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1123 /* Needed to show the msdfs symlinks as
1126 if(lp_host_msdfs() &&
1127 lp_msdfs_root(SNUM(conn)) &&
1128 is_msdfs_link(NULL,conn, pathreal, NULL, NULL,
1131 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1132 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1136 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1137 pathreal,strerror(errno)));
1142 mode = dos_mode(conn,pathreal,&sbuf);
1144 if (!dir_check_ftype(conn,mode,dirtype)) {
1145 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1149 file_size = get_file_size(sbuf);
1150 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1151 mdate = sbuf.st_mtime;
1152 adate = sbuf.st_atime;
1153 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1155 if (lp_dos_filetime_resolution(SNUM(conn))) {
1162 /* This is necessary, as otherwise the
1163 * desktop.ini file in this folder is
1165 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
1169 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1175 mangle_map(fname,False,True,SNUM(conn));
1180 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1182 switch (info_level) {
1183 case SMB_FIND_INFO_STANDARD:
1184 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1185 if(requires_resume_key) {
1189 srv_put_dos_date2(p,0,cdate);
1190 srv_put_dos_date2(p,4,adate);
1191 srv_put_dos_date2(p,8,mdate);
1192 SIVAL(p,12,(uint32)file_size);
1193 SIVAL(p,16,(uint32)allocation_size);
1197 p += align_string(outbuf, p, 0);
1198 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1199 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1201 SCVAL(nameptr, -1, len - 2);
1203 SCVAL(nameptr, -1, 0);
1207 SCVAL(nameptr, -1, len - 1);
1209 SCVAL(nameptr, -1, 0);
1215 case SMB_FIND_EA_SIZE:
1216 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1217 if(requires_resume_key) {
1221 srv_put_dos_date2(p,0,cdate);
1222 srv_put_dos_date2(p,4,adate);
1223 srv_put_dos_date2(p,8,mdate);
1224 SIVAL(p,12,(uint32)file_size);
1225 SIVAL(p,16,(uint32)allocation_size);
1228 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1229 SIVAL(p,22,ea_size); /* Extended attributes */
1233 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1234 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1247 SCVAL(nameptr,0,len);
1249 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1252 case SMB_FIND_EA_LIST:
1254 struct ea_list *file_list = NULL;
1257 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1261 if(requires_resume_key) {
1265 srv_put_dos_date2(p,0,cdate);
1266 srv_put_dos_date2(p,4,adate);
1267 srv_put_dos_date2(p,8,mdate);
1268 SIVAL(p,12,(uint32)file_size);
1269 SIVAL(p,16,(uint32)allocation_size);
1271 p += 22; /* p now points to the EA area. */
1273 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1274 name_list = ea_list_union(name_list, file_list, &ea_len);
1276 /* We need to determine if this entry will fit in the space available. */
1277 /* Max string size is 255 bytes. */
1278 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1279 /* Move the dirptr back to prev_dirpos */
1280 dptr_SeekDir(conn->dirptr, prev_dirpos);
1281 *out_of_space = True;
1282 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1283 return False; /* Not finished - just out of space */
1286 /* Push the ea_data followed by the name. */
1287 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1289 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1290 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1303 SCVAL(nameptr,0,len);
1305 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1309 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1310 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1311 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1313 SIVAL(p,0,reskey); p += 4;
1314 put_long_date(p,cdate); p += 8;
1315 put_long_date(p,adate); p += 8;
1316 put_long_date(p,mdate); p += 8;
1317 put_long_date(p,mdate); p += 8;
1318 SOFF_T(p,0,file_size); p += 8;
1319 SOFF_T(p,0,allocation_size); p += 8;
1320 SIVAL(p,0,nt_extmode); p += 4;
1321 q = p; p += 4; /* q is placeholder for name length. */
1323 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1324 SIVAL(p,0,ea_size); /* Extended attributes */
1327 /* Clear the short name buffer. This is
1328 * IMPORTANT as not doing so will trigger
1329 * a Win2k client bug. JRA.
1331 if (!was_8_3 && check_mangled_names) {
1332 pstring mangled_name;
1333 pstrcpy(mangled_name, fname);
1334 mangle_map(mangled_name,True,True,SNUM(conn));
1335 mangled_name[12] = 0;
1336 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1338 memset(p + 2 + len,'\0',24 - len);
1345 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1348 SIVAL(p,0,0); /* Ensure any padding is null. */
1349 len = PTR_DIFF(p, pdata);
1350 len = (len + 3) & ~3;
1355 case SMB_FIND_FILE_DIRECTORY_INFO:
1356 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1358 SIVAL(p,0,reskey); p += 4;
1359 put_long_date(p,cdate); p += 8;
1360 put_long_date(p,adate); p += 8;
1361 put_long_date(p,mdate); p += 8;
1362 put_long_date(p,mdate); p += 8;
1363 SOFF_T(p,0,file_size); p += 8;
1364 SOFF_T(p,0,allocation_size); p += 8;
1365 SIVAL(p,0,nt_extmode); p += 4;
1366 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1369 SIVAL(p,0,0); /* Ensure any padding is null. */
1370 len = PTR_DIFF(p, pdata);
1371 len = (len + 3) & ~3;
1376 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1377 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1379 SIVAL(p,0,reskey); p += 4;
1380 put_long_date(p,cdate); p += 8;
1381 put_long_date(p,adate); p += 8;
1382 put_long_date(p,mdate); p += 8;
1383 put_long_date(p,mdate); p += 8;
1384 SOFF_T(p,0,file_size); p += 8;
1385 SOFF_T(p,0,allocation_size); p += 8;
1386 SIVAL(p,0,nt_extmode); p += 4;
1387 q = p; p += 4; /* q is placeholder for name length. */
1389 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1390 SIVAL(p,0,ea_size); /* Extended attributes */
1393 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1397 SIVAL(p,0,0); /* Ensure any padding is null. */
1398 len = PTR_DIFF(p, pdata);
1399 len = (len + 3) & ~3;
1404 case SMB_FIND_FILE_NAMES_INFO:
1405 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1407 SIVAL(p,0,reskey); p += 4;
1409 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1410 acl on a dir (tridge) */
1411 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1414 SIVAL(p,0,0); /* Ensure any padding is null. */
1415 len = PTR_DIFF(p, pdata);
1416 len = (len + 3) & ~3;
1421 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1422 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1424 SIVAL(p,0,reskey); p += 4;
1425 put_long_date(p,cdate); p += 8;
1426 put_long_date(p,adate); p += 8;
1427 put_long_date(p,mdate); p += 8;
1428 put_long_date(p,mdate); p += 8;
1429 SOFF_T(p,0,file_size); p += 8;
1430 SOFF_T(p,0,allocation_size); p += 8;
1431 SIVAL(p,0,nt_extmode); p += 4;
1432 q = p; p += 4; /* q is placeholder for name length. */
1434 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1435 SIVAL(p,0,ea_size); /* Extended attributes */
1438 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1439 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1440 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1441 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1444 SIVAL(p,0,0); /* Ensure any padding is null. */
1445 len = PTR_DIFF(p, pdata);
1446 len = (len + 3) & ~3;
1451 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1452 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1453 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1455 SIVAL(p,0,reskey); p += 4;
1456 put_long_date(p,cdate); p += 8;
1457 put_long_date(p,adate); p += 8;
1458 put_long_date(p,mdate); p += 8;
1459 put_long_date(p,mdate); p += 8;
1460 SOFF_T(p,0,file_size); p += 8;
1461 SOFF_T(p,0,allocation_size); p += 8;
1462 SIVAL(p,0,nt_extmode); p += 4;
1463 q = p; p += 4; /* q is placeholder for name length */
1465 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1466 SIVAL(p,0,ea_size); /* Extended attributes */
1469 /* Clear the short name buffer. This is
1470 * IMPORTANT as not doing so will trigger
1471 * a Win2k client bug. JRA.
1473 if (!was_8_3 && check_mangled_names) {
1474 pstring mangled_name;
1475 pstrcpy(mangled_name, fname);
1476 mangle_map(mangled_name,True,True,SNUM(conn));
1477 mangled_name[12] = 0;
1478 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1481 memset(p + 2 + len,'\0',24 - len);
1488 SSVAL(p,0,0); p += 2; /* Reserved ? */
1489 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1490 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1491 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1494 SIVAL(p,0,0); /* Ensure any padding is null. */
1495 len = PTR_DIFF(p, pdata);
1496 len = (len + 3) & ~3;
1501 /* CIFS UNIX Extension. */
1503 case SMB_FIND_FILE_UNIX:
1504 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1506 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1508 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1509 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1512 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1515 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1516 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1517 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1520 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1524 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1528 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1531 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1535 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1539 SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1542 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1546 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1550 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1552 SIVAL(p,0,0); /* Ensure any padding is null. */
1554 len = PTR_DIFF(p, pdata);
1555 len = (len + 3) & ~3;
1556 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1558 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1567 if (PTR_DIFF(p,pdata) > space_remaining) {
1568 /* Move the dirptr back to prev_dirpos */
1569 dptr_SeekDir(conn->dirptr, prev_dirpos);
1570 *out_of_space = True;
1571 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1572 return False; /* Not finished - just out of space */
1575 /* Setup the last entry pointer, as an offset from base_data */
1576 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1577 /* Advance the data pointer to the next slot */
1583 /****************************************************************************
1584 Reply to a TRANS2_FINDFIRST.
1585 ****************************************************************************/
1587 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1588 char **pparams, int total_params, char **ppdata, int total_data,
1589 unsigned int max_data_bytes)
1591 /* We must be careful here that we don't return more than the
1592 allowed number of data bytes. If this means returning fewer than
1593 maxentries then so be it. We assume that the redirector has
1594 enough room for the fixed number of parameter bytes it has
1596 char *params = *pparams;
1597 char *pdata = *ppdata;
1598 uint32 dirtype = SVAL(params,0);
1599 int maxentries = SVAL(params,2);
1600 uint16 findfirst_flags = SVAL(params,4);
1601 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1602 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1603 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1604 int info_level = SVAL(params,6);
1608 int last_entry_off=0;
1612 BOOL finished = False;
1613 BOOL dont_descend = False;
1614 BOOL out_of_space = False;
1615 int space_remaining;
1616 BOOL bad_path = False;
1617 BOOL mask_contains_wcard = False;
1618 SMB_STRUCT_STAT sbuf;
1619 TALLOC_CTX *ea_ctx = NULL;
1620 struct ea_list *ea_list = NULL;
1621 NTSTATUS ntstatus = NT_STATUS_OK;
1623 if (total_params < 12) {
1624 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1627 *directory = *mask = 0;
1629 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1630 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1631 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1632 info_level, max_data_bytes));
1635 /* W2K3 seems to treat zero as 1. */
1639 switch (info_level) {
1640 case SMB_FIND_INFO_STANDARD:
1641 case SMB_FIND_EA_SIZE:
1642 case SMB_FIND_EA_LIST:
1643 case SMB_FIND_FILE_DIRECTORY_INFO:
1644 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1645 case SMB_FIND_FILE_NAMES_INFO:
1646 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1647 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1648 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1650 case SMB_FIND_FILE_UNIX:
1651 if (!lp_unix_extensions())
1652 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1655 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1658 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1659 if (!NT_STATUS_IS_OK(ntstatus)) {
1660 return ERROR_NT(ntstatus);
1663 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1665 unix_convert(directory,conn,0,&bad_path,&sbuf);
1667 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1669 if(!check_name(directory,conn)) {
1670 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1673 p = strrchr_m(directory,'/');
1675 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1676 if((directory[0] == '.') && (directory[1] == '\0')) {
1678 mask_contains_wcard = True;
1680 pstrcpy(mask,directory);
1682 pstrcpy(directory,"./");
1688 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1690 if (info_level == SMB_FIND_EA_LIST) {
1693 if (total_data < 4) {
1694 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1697 ea_size = IVAL(pdata,0);
1698 if (ea_size != total_data) {
1699 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1700 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1701 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1704 if (!lp_ea_support(SNUM(conn))) {
1705 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1708 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1709 return ERROR_NT(NT_STATUS_NO_MEMORY);
1712 /* Pull out the list of names. */
1713 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1715 talloc_destroy(ea_ctx);
1716 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1720 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1721 if( pdata == NULL ) {
1722 talloc_destroy(ea_ctx);
1723 return ERROR_NT(NT_STATUS_NO_MEMORY);
1728 /* Realloc the params space */
1729 params = SMB_REALLOC(*pparams, 10);
1730 if (params == NULL) {
1731 talloc_destroy(ea_ctx);
1732 return ERROR_NT(NT_STATUS_NO_MEMORY);
1736 /* Save the wildcard match and attribs we are using on this directory -
1737 needed as lanman2 assumes these are being saved between calls */
1739 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1741 talloc_destroy(ea_ctx);
1742 return(UNIXERROR(ERRDOS,ERRbadfile));
1745 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1747 /* We don't need to check for VOL here as this is returned by
1748 a different TRANS2 call. */
1750 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1751 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1752 dont_descend = True;
1755 space_remaining = max_data_bytes;
1756 out_of_space = False;
1758 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1759 BOOL got_exact_match = False;
1761 /* this is a heuristic to avoid seeking the dirptr except when
1762 absolutely necessary. It allows for a filename of about 40 chars */
1763 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1764 out_of_space = True;
1767 finished = !get_lanman2_dir_entry(conn,
1769 mask,dirtype,info_level,
1770 requires_resume_key,dont_descend,
1771 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1772 &last_entry_off, ea_list, ea_ctx);
1775 if (finished && out_of_space)
1778 if (!finished && !out_of_space)
1782 * As an optimisation if we know we aren't looking
1783 * for a wildcard name (ie. the name matches the wildcard exactly)
1784 * then we can finish on any (first) match.
1785 * This speeds up large directory searches. JRA.
1791 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1794 talloc_destroy(ea_ctx);
1796 /* Check if we can close the dirptr */
1797 if(close_after_first || (finished && close_if_end)) {
1798 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1799 dptr_close(&dptr_num);
1803 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1804 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1805 * the protocol level is less than NT1. Tested with smbclient. JRA.
1806 * This should fix the OS/2 client bug #2335.
1809 if(numentries == 0) {
1810 dptr_close(&dptr_num);
1811 if (Protocol < PROTOCOL_NT1) {
1812 return ERROR_DOS(ERRDOS,ERRnofiles);
1814 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1818 /* At this point pdata points to numentries directory entries. */
1820 /* Set up the return parameter block */
1821 SSVAL(params,0,dptr_num);
1822 SSVAL(params,2,numentries);
1823 SSVAL(params,4,finished);
1824 SSVAL(params,6,0); /* Never an EA error */
1825 SSVAL(params,8,last_entry_off);
1827 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1829 if ((! *directory) && dptr_path(dptr_num))
1830 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1832 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1833 smb_fn_name(CVAL(inbuf,smb_com)),
1834 mask, directory, dirtype, numentries ) );
1837 * Force a name mangle here to ensure that the
1838 * mask as an 8.3 name is top of the mangled cache.
1839 * The reasons for this are subtle. Don't remove
1840 * this code unless you know what you are doing
1841 * (see PR#13758). JRA.
1844 if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn)))
1845 mangle_map(mask, True, True, SNUM(conn));
1850 /****************************************************************************
1851 Reply to a TRANS2_FINDNEXT.
1852 ****************************************************************************/
1854 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1855 char **pparams, int total_params, char **ppdata, int total_data,
1856 unsigned int max_data_bytes)
1858 /* We must be careful here that we don't return more than the
1859 allowed number of data bytes. If this means returning fewer than
1860 maxentries then so be it. We assume that the redirector has
1861 enough room for the fixed number of parameter bytes it has
1863 char *params = *pparams;
1864 char *pdata = *ppdata;
1865 int dptr_num = SVAL(params,0);
1866 int maxentries = SVAL(params,2);
1867 uint16 info_level = SVAL(params,4);
1868 uint32 resume_key = IVAL(params,6);
1869 uint16 findnext_flags = SVAL(params,10);
1870 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1871 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1872 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1873 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1874 BOOL mask_contains_wcard = False;
1875 pstring resume_name;
1881 int i, last_entry_off=0;
1882 BOOL finished = False;
1883 BOOL dont_descend = False;
1884 BOOL out_of_space = False;
1885 int space_remaining;
1886 TALLOC_CTX *ea_ctx = NULL;
1887 struct ea_list *ea_list = NULL;
1888 NTSTATUS ntstatus = NT_STATUS_OK;
1890 if (total_params < 12) {
1891 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1894 *mask = *directory = *resume_name = 0;
1896 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1897 if (!NT_STATUS_IS_OK(ntstatus)) {
1898 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1899 complain (it thinks we're asking for the directory above the shared
1900 path or an invalid name). Catch this as the resume name is only compared, never used in
1901 a file access. JRA. */
1902 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1903 pstrcpy(resume_name, "..");
1904 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1905 pstrcpy(resume_name, ".");
1907 return ERROR_NT(ntstatus);
1911 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1912 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1913 resume_key = %d resume name = %s continue=%d level = %d\n",
1914 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1915 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1918 /* W2K3 seems to treat zero as 1. */
1922 switch (info_level) {
1923 case SMB_FIND_INFO_STANDARD:
1924 case SMB_FIND_EA_SIZE:
1925 case SMB_FIND_EA_LIST:
1926 case SMB_FIND_FILE_DIRECTORY_INFO:
1927 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1928 case SMB_FIND_FILE_NAMES_INFO:
1929 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1930 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1931 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1933 case SMB_FIND_FILE_UNIX:
1934 if (!lp_unix_extensions())
1935 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1938 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1941 if (info_level == SMB_FIND_EA_LIST) {
1944 if (total_data < 4) {
1945 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1948 ea_size = IVAL(pdata,0);
1949 if (ea_size != total_data) {
1950 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1951 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1952 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1955 if (!lp_ea_support(SNUM(conn))) {
1956 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1959 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1960 return ERROR_NT(NT_STATUS_NO_MEMORY);
1963 /* Pull out the list of names. */
1964 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1966 talloc_destroy(ea_ctx);
1967 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1971 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1973 talloc_destroy(ea_ctx);
1974 return ERROR_NT(NT_STATUS_NO_MEMORY);
1979 /* Realloc the params space */
1980 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1981 if( params == NULL ) {
1982 talloc_destroy(ea_ctx);
1983 return ERROR_NT(NT_STATUS_NO_MEMORY);
1988 /* Check that the dptr is valid */
1989 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
1990 talloc_destroy(ea_ctx);
1991 return ERROR_DOS(ERRDOS,ERRnofiles);
1994 string_set(&conn->dirpath,dptr_path(dptr_num));
1996 /* Get the wildcard mask from the dptr */
1997 if((p = dptr_wcard(dptr_num))== NULL) {
1998 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1999 talloc_destroy(ea_ctx);
2000 return ERROR_DOS(ERRDOS,ERRnofiles);
2004 pstrcpy(directory,conn->dirpath);
2006 /* Get the attr mask from the dptr */
2007 dirtype = dptr_attr(dptr_num);
2009 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2010 dptr_num, mask, dirtype,
2012 dptr_TellDir(conn->dirptr)));
2014 /* We don't need to check for VOL here as this is returned by
2015 a different TRANS2 call. */
2017 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2018 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2019 dont_descend = True;
2022 space_remaining = max_data_bytes;
2023 out_of_space = False;
2026 * Seek to the correct position. We no longer use the resume key but
2027 * depend on the last file name instead.
2030 if(*resume_name && !continue_bit) {
2033 long current_pos = 0;
2035 * Remember, mangle_map is called by
2036 * get_lanman2_dir_entry(), so the resume name
2037 * could be mangled. Ensure we check the unmangled name.
2040 if (mangle_is_mangled(resume_name, SNUM(conn))) {
2041 mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn));
2045 * Fix for NT redirector problem triggered by resume key indexes
2046 * changing between directory scans. We now return a resume key of 0
2047 * and instead look for the filename to continue from (also given
2048 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2049 * findfirst/findnext (as is usual) then the directory pointer
2050 * should already be at the correct place.
2053 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2054 } /* end if resume_name && !continue_bit */
2056 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2057 BOOL got_exact_match = False;
2059 /* this is a heuristic to avoid seeking the dirptr except when
2060 absolutely necessary. It allows for a filename of about 40 chars */
2061 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2062 out_of_space = True;
2065 finished = !get_lanman2_dir_entry(conn,
2067 mask,dirtype,info_level,
2068 requires_resume_key,dont_descend,
2069 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2070 &last_entry_off, ea_list, ea_ctx);
2073 if (finished && out_of_space)
2076 if (!finished && !out_of_space)
2080 * As an optimisation if we know we aren't looking
2081 * for a wildcard name (ie. the name matches the wildcard exactly)
2082 * then we can finish on any (first) match.
2083 * This speeds up large directory searches. JRA.
2089 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2092 talloc_destroy(ea_ctx);
2094 /* Check if we can close the dirptr */
2095 if(close_after_request || (finished && close_if_end)) {
2096 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2097 dptr_close(&dptr_num); /* This frees up the saved mask */
2100 /* Set up the return parameter block */
2101 SSVAL(params,0,numentries);
2102 SSVAL(params,2,finished);
2103 SSVAL(params,4,0); /* Never an EA error */
2104 SSVAL(params,6,last_entry_off);
2106 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2108 if ((! *directory) && dptr_path(dptr_num))
2109 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2111 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2112 smb_fn_name(CVAL(inbuf,smb_com)),
2113 mask, directory, dirtype, numentries ) );
2118 /****************************************************************************
2119 Reply to a TRANS2_QFSINFO (query filesystem info).
2120 ****************************************************************************/
2122 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2123 char **pparams, int total_params, char **ppdata, int total_data,
2124 unsigned int max_data_bytes)
2126 char *pdata = *ppdata;
2127 char *params = *pparams;
2128 uint16 info_level = SVAL(params,0);
2131 char *vname = volume_label(SNUM(conn));
2132 int snum = SNUM(conn);
2133 char *fstype = lp_fstype(SNUM(conn));
2136 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2138 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2139 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2140 return ERROR_DOS(ERRSRV,ERRinvdevice);
2143 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2144 if ( pdata == NULL ) {
2145 return ERROR_NT(NT_STATUS_NO_MEMORY);
2149 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2151 switch (info_level) {
2152 case SMB_INFO_ALLOCATION:
2154 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2156 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2157 return(UNIXERROR(ERRHRD,ERRgeneral));
2160 block_size = lp_block_size(snum);
2161 if (bsize < block_size) {
2162 SMB_BIG_UINT factor = block_size/bsize;
2167 if (bsize > block_size) {
2168 SMB_BIG_UINT factor = bsize/block_size;
2173 bytes_per_sector = 512;
2174 sectors_per_unit = bsize/bytes_per_sector;
2176 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2177 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2178 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2180 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2181 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2182 SIVAL(pdata,l1_cUnit,dsize);
2183 SIVAL(pdata,l1_cUnitAvail,dfree);
2184 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2188 case SMB_INFO_VOLUME:
2189 /* Return volume name */
2191 * Add volume serial number - hash of a combination of
2192 * the called hostname and the service name.
2194 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2196 * Win2k3 and previous mess this up by sending a name length
2197 * one byte short. I believe only older clients (OS/2 Win9x) use
2198 * this call so try fixing this by adding a terminating null to
2199 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2201 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2202 SCVAL(pdata,l2_vol_cch,len);
2203 data_len = l2_vol_szVolLabel + len;
2204 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2205 (unsigned)st.st_ctime, len, vname));
2208 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2209 case SMB_FS_ATTRIBUTE_INFORMATION:
2212 #if defined(HAVE_SYS_QUOTAS)
2213 quota_flag = FILE_VOLUME_QUOTAS;
2216 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2217 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2218 quota_flag); /* FS ATTRIBUTES */
2220 SIVAL(pdata,4,255); /* Max filename component length */
2221 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2222 and will think we can't do long filenames */
2223 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2225 data_len = 12 + len;
2228 case SMB_QUERY_FS_LABEL_INFO:
2229 case SMB_FS_LABEL_INFORMATION:
2230 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2235 case SMB_QUERY_FS_VOLUME_INFO:
2236 case SMB_FS_VOLUME_INFORMATION:
2239 * Add volume serial number - hash of a combination of
2240 * the called hostname and the service name.
2242 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2243 (str_checksum(get_local_machine_name())<<16));
2245 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2246 SIVAL(pdata,12,len);
2248 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2249 (int)strlen(vname),vname, lp_servicename(snum)));
2252 case SMB_QUERY_FS_SIZE_INFO:
2253 case SMB_FS_SIZE_INFORMATION:
2255 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2257 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2258 return(UNIXERROR(ERRHRD,ERRgeneral));
2260 block_size = lp_block_size(snum);
2261 if (bsize < block_size) {
2262 SMB_BIG_UINT factor = block_size/bsize;
2267 if (bsize > block_size) {
2268 SMB_BIG_UINT factor = bsize/block_size;
2273 bytes_per_sector = 512;
2274 sectors_per_unit = bsize/bytes_per_sector;
2275 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2276 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2277 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2278 SBIG_UINT(pdata,0,dsize);
2279 SBIG_UINT(pdata,8,dfree);
2280 SIVAL(pdata,16,sectors_per_unit);
2281 SIVAL(pdata,20,bytes_per_sector);
2285 case SMB_FS_FULL_SIZE_INFORMATION:
2287 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2289 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2290 return(UNIXERROR(ERRHRD,ERRgeneral));
2292 block_size = lp_block_size(snum);
2293 if (bsize < block_size) {
2294 SMB_BIG_UINT factor = block_size/bsize;
2299 if (bsize > block_size) {
2300 SMB_BIG_UINT factor = bsize/block_size;
2305 bytes_per_sector = 512;
2306 sectors_per_unit = bsize/bytes_per_sector;
2307 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2308 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2309 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2310 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2311 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2312 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2313 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2314 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2318 case SMB_QUERY_FS_DEVICE_INFO:
2319 case SMB_FS_DEVICE_INFORMATION:
2321 SIVAL(pdata,0,0); /* dev type */
2322 SIVAL(pdata,4,0); /* characteristics */
2325 #ifdef HAVE_SYS_QUOTAS
2326 case SMB_FS_QUOTA_INFORMATION:
2328 * what we have to send --metze:
2330 * Unknown1: 24 NULL bytes
2331 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2332 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2333 * Quota Flags: 2 byte :
2334 * Unknown3: 6 NULL bytes
2338 * details for Quota Flags:
2340 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2341 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2342 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2343 * 0x0001 Enable Quotas: enable quota for this fs
2347 /* we need to fake up a fsp here,
2348 * because its not send in this call
2351 SMB_NTQUOTA_STRUCT quotas;
2354 ZERO_STRUCT(quotas);
2360 if (current_user.uid != 0) {
2361 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2362 lp_servicename(SNUM(conn)),conn->user));
2363 return ERROR_DOS(ERRDOS,ERRnoaccess);
2366 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2367 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2368 return ERROR_DOS(ERRSRV,ERRerror);
2373 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2375 /* Unknown1 24 NULL bytes*/
2376 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2377 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2378 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2380 /* Default Soft Quota 8 bytes */
2381 SBIG_UINT(pdata,24,quotas.softlim);
2383 /* Default Hard Quota 8 bytes */
2384 SBIG_UINT(pdata,32,quotas.hardlim);
2386 /* Quota flag 2 bytes */
2387 SSVAL(pdata,40,quotas.qflags);
2389 /* Unknown3 6 NULL bytes */
2395 #endif /* HAVE_SYS_QUOTAS */
2396 case SMB_FS_OBJECTID_INFORMATION:
2401 * Query the version and capabilities of the CIFS UNIX extensions
2405 case SMB_QUERY_CIFS_UNIX_INFO:
2406 if (!lp_unix_extensions())
2407 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2409 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2410 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2411 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(CIFS_UNIX_POSIX_ACLS_CAP|
2412 CIFS_UNIX_POSIX_PATHNAMES_CAP))); /* We have POSIX ACLs and pathname capability. */
2415 case SMB_QUERY_POSIX_FS_INFO:
2418 vfs_statvfs_struct svfs;
2420 if (!lp_unix_extensions())
2421 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2423 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2427 SIVAL(pdata,0,svfs.OptimalTransferSize);
2428 SIVAL(pdata,4,svfs.BlockSize);
2429 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2430 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2431 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2432 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2433 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2434 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2435 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2437 } else if (rc == EOPNOTSUPP) {
2438 return ERROR_DOS(ERRDOS, ERRunknownlevel);
2439 #endif /* EOPNOTSUPP */
2441 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2442 return ERROR_DOS(ERRSRV,ERRerror);
2447 case SMB_MAC_QUERY_FS_INFO:
2449 * Thursby MAC extension... ONLY on NTFS filesystems
2450 * once we do streams then we don't need this
2452 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2454 SIVAL(pdata,84,0x100); /* Don't support mac... */
2459 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2463 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2465 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2470 /****************************************************************************
2471 Reply to a TRANS2_SETFSINFO (set filesystem info).
2472 ****************************************************************************/
2474 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2475 char **pparams, int total_params, char **ppdata, int total_data,
2476 unsigned int max_data_bytes)
2478 char *pdata = *ppdata;
2479 char *params = *pparams;
2483 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2486 if (total_params < 4) {
2487 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2489 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2492 info_level = SVAL(params,2);
2494 switch(info_level) {
2495 case SMB_SET_CIFS_UNIX_INFO:
2497 uint16 client_unix_major;
2498 uint16 client_unix_minor;
2499 uint32 client_unix_cap_low;
2500 uint32 client_unix_cap_high;
2502 if (!lp_unix_extensions()) {
2503 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2506 /* There should be 12 bytes of capabilities set. */
2507 if (total_data < 8) {
2508 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2510 client_unix_major = SVAL(pdata,0);
2511 client_unix_minor = SVAL(pdata,2);
2512 client_unix_cap_low = IVAL(pdata,4);
2513 client_unix_cap_high = IVAL(pdata,8);
2514 /* Just print these values for now. */
2515 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2516 cap_low = 0x%x, cap_high = 0x%x\n",
2517 (unsigned int)client_unix_major,
2518 (unsigned int)client_unix_minor,
2519 (unsigned int)client_unix_cap_low,
2520 (unsigned int)client_unix_cap_high ));
2522 /* Here is where we must switch to posix pathname processing... */
2523 lp_set_posix_pathnames();
2524 mangle_change_to_posix();
2527 case SMB_FS_QUOTA_INFORMATION:
2529 files_struct *fsp = NULL;
2530 SMB_NTQUOTA_STRUCT quotas;
2532 ZERO_STRUCT(quotas);
2535 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2536 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2537 lp_servicename(SNUM(conn)),conn->user));
2538 return ERROR_DOS(ERRSRV,ERRaccess);
2541 /* note: normaly there're 48 bytes,
2542 * but we didn't use the last 6 bytes for now
2545 fsp = file_fsp(params,0);
2546 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2547 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2548 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2551 if (total_data < 42) {
2552 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2554 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2557 /* unknown_1 24 NULL bytes in pdata*/
2559 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2560 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2561 #ifdef LARGE_SMB_OFF_T
2562 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2563 #else /* LARGE_SMB_OFF_T */
2564 if ((IVAL(pdata,28) != 0)&&
2565 ((quotas.softlim != 0xFFFFFFFF)||
2566 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2567 /* more than 32 bits? */
2568 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2570 #endif /* LARGE_SMB_OFF_T */
2572 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2573 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2574 #ifdef LARGE_SMB_OFF_T
2575 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2576 #else /* LARGE_SMB_OFF_T */
2577 if ((IVAL(pdata,36) != 0)&&
2578 ((quotas.hardlim != 0xFFFFFFFF)||
2579 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2580 /* more than 32 bits? */
2581 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2583 #endif /* LARGE_SMB_OFF_T */
2585 /* quota_flags 2 bytes **/
2586 quotas.qflags = SVAL(pdata,40);
2588 /* unknown_2 6 NULL bytes follow*/
2590 /* now set the quotas */
2591 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2592 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2593 return ERROR_DOS(ERRSRV,ERRerror);
2599 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2601 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2606 * sending this reply works fine,
2607 * but I'm not sure it's the same
2608 * like windows do...
2611 outsize = set_message(outbuf,10,0,True);
2616 /****************************************************************************
2617 Utility function to set bad path error.
2618 ****************************************************************************/
2620 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2622 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2623 err, (int)bad_path ));
2627 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2629 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2632 return UNIXERROR(def_class,def_code);
2635 #if defined(HAVE_POSIX_ACLS)
2636 /****************************************************************************
2637 Utility function to count the number of entries in a POSIX acl.
2638 ****************************************************************************/
2640 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2642 unsigned int ace_count = 0;
2643 int entry_id = SMB_ACL_FIRST_ENTRY;
2644 SMB_ACL_ENTRY_T entry;
2646 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2648 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2649 entry_id = SMB_ACL_NEXT_ENTRY;
2656 /****************************************************************************
2657 Utility function to marshall a POSIX acl into wire format.
2658 ****************************************************************************/
2660 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2662 int entry_id = SMB_ACL_FIRST_ENTRY;
2663 SMB_ACL_ENTRY_T entry;
2665 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2666 SMB_ACL_TAG_T tagtype;
2667 SMB_ACL_PERMSET_T permset;
2668 unsigned char perms = 0;
2669 unsigned int own_grp;
2672 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2673 entry_id = SMB_ACL_NEXT_ENTRY;
2676 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2677 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2681 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2682 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2686 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2687 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2688 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2690 SCVAL(pdata,1,perms);
2693 case SMB_ACL_USER_OBJ:
2694 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2695 own_grp = (unsigned int)pst->st_uid;
2696 SIVAL(pdata,2,own_grp);
2701 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2703 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2705 own_grp = (unsigned int)*puid;
2706 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2707 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2708 SIVAL(pdata,2,own_grp);
2712 case SMB_ACL_GROUP_OBJ:
2713 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2714 own_grp = (unsigned int)pst->st_gid;
2715 SIVAL(pdata,2,own_grp);
2720 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2722 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2724 own_grp = (unsigned int)*pgid;
2725 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2726 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2727 SIVAL(pdata,2,own_grp);
2732 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2733 SIVAL(pdata,2,0xFFFFFFFF);
2734 SIVAL(pdata,6,0xFFFFFFFF);
2737 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2738 SIVAL(pdata,2,0xFFFFFFFF);
2739 SIVAL(pdata,6,0xFFFFFFFF);
2742 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2745 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2752 /****************************************************************************
2753 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2754 file name or file id).
2755 ****************************************************************************/
2757 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2758 unsigned int tran_call,
2759 char **pparams, int total_params, char **ppdata, int total_data,
2760 unsigned int max_data_bytes)
2762 char *params = *pparams;
2763 char *pdata = *ppdata;
2767 SMB_OFF_T file_size=0;
2768 SMB_BIG_UINT allocation_size=0;
2769 unsigned int data_size = 0;
2770 unsigned int param_size = 2;
2771 SMB_STRUCT_STAT sbuf;
2772 pstring fname, dos_fname;
2777 BOOL bad_path = False;
2778 BOOL delete_pending = False;
2781 files_struct *fsp = NULL;
2782 TALLOC_CTX *ea_ctx = NULL;
2783 struct ea_list *ea_list = NULL;
2784 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2787 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2791 if (tran_call == TRANSACT2_QFILEINFO) {
2792 if (total_params < 4) {
2793 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2796 fsp = file_fsp(params,0);
2797 info_level = SVAL(params,2);
2799 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2801 if(fsp && (fsp->fake_file_handle)) {
2803 * This is actually for the QUOTA_FAKE_FILE --metze
2806 pstrcpy(fname, fsp->fsp_name);
2807 /* We know this name is ok, it's already passed the checks. */
2809 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2811 * This is actually a QFILEINFO on a directory
2812 * handle (returned from an NT SMB). NT5.0 seems
2813 * to do this call. JRA.
2815 /* We know this name is ok, it's already passed the checks. */
2816 pstrcpy(fname, fsp->fsp_name);
2818 if (INFO_LEVEL_IS_UNIX(info_level)) {
2819 /* Always do lstat for UNIX calls. */
2820 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2821 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2822 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2824 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2825 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2826 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2830 get_delete_on_close_flag(sbuf.st_dev,
2835 * Original code - this is an open file.
2837 CHECK_FSP(fsp,conn);
2839 pstrcpy(fname, fsp->fsp_name);
2840 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2841 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2842 return(UNIXERROR(ERRDOS,ERRbadfid));
2844 pos = fsp->fh->position_information;
2846 get_delete_on_close_flag(sbuf.st_dev,
2849 access_mask = fsp->access_mask;
2852 NTSTATUS status = NT_STATUS_OK;
2855 if (total_params < 6) {
2856 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2859 info_level = SVAL(params,0);
2861 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2863 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
2864 if (!NT_STATUS_IS_OK(status)) {
2865 return ERROR_NT(status);
2868 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2870 unix_convert(fname,conn,0,&bad_path,&sbuf);
2872 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2874 if (!check_name(fname,conn)) {
2875 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2876 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2879 if (INFO_LEVEL_IS_UNIX(info_level)) {
2880 /* Always do lstat for UNIX calls. */
2881 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2882 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2883 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2885 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2886 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2887 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2890 delete_pending = get_delete_on_close_flag(sbuf.st_dev,
2893 if (delete_pending) {
2894 return ERROR_NT(NT_STATUS_DELETE_PENDING);
2898 nlink = sbuf.st_nlink;
2900 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2901 /* NTFS does not seem to count ".." */
2905 if ((nlink > 0) && delete_pending) {
2909 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2910 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2912 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2913 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2915 p = strrchr_m(fname,'/');
2921 mode = dos_mode(conn,fname,&sbuf);
2923 mode = FILE_ATTRIBUTE_NORMAL;
2925 fullpathname = fname;
2926 file_size = get_file_size(sbuf);
2928 /* This is necessary, as otherwise the desktop.ini file in
2929 * this folder is ignored */
2930 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2934 /* Pull any EA list from the data portion. */
2935 if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2938 if (total_data < 4) {
2939 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2941 ea_size = IVAL(pdata,0);
2943 if (total_data > 0 && ea_size != total_data) {
2944 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2945 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2946 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2949 if (!lp_ea_support(SNUM(conn))) {
2950 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2953 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2954 return ERROR_NT(NT_STATUS_NO_MEMORY);
2957 /* Pull out the list of names. */
2958 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2960 talloc_destroy(ea_ctx);
2961 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2965 params = SMB_REALLOC(*pparams,2);
2966 if (params == NULL) {
2967 talloc_destroy(ea_ctx);
2968 return ERROR_NT(NT_STATUS_NO_MEMORY);
2972 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2973 pdata = SMB_REALLOC(*ppdata, data_size);
2974 if ( pdata == NULL ) {
2975 talloc_destroy(ea_ctx);
2976 return ERROR_NT(NT_STATUS_NO_MEMORY);
2980 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2982 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2985 if (fsp->pending_modtime) {
2986 /* the pending modtime overrides the current modtime */
2987 sbuf.st_mtime = fsp->pending_modtime;
2990 /* Do we have this path open ? */
2991 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2992 if (fsp1 && fsp1->pending_modtime) {
2993 /* the pending modtime overrides the current modtime */
2994 sbuf.st_mtime = fsp1->pending_modtime;
2996 if (fsp1 && fsp1->initial_allocation_size) {
2997 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3001 if (lp_dos_filetime_resolution(SNUM(conn))) {
3003 sbuf.st_atime &= ~1;
3004 sbuf.st_ctime &= ~1;
3005 sbuf.st_mtime &= ~1;
3008 /* NT expects the name to be in an exact form of the *full*
3009 filename. See the trans2 torture test */
3010 if (strequal(base_name,".")) {
3011 pstrcpy(dos_fname, "\\");
3013 pstr_sprintf(dos_fname, "\\%s", fname);
3014 string_replace(dos_fname, '/', '\\');
3017 switch (info_level) {
3018 case SMB_INFO_STANDARD:
3019 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3021 srv_put_dos_date2(pdata,l1_fdateCreation,c_time);
3022 srv_put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
3023 srv_put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
3024 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3025 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3026 SSVAL(pdata,l1_attrFile,mode);
3029 case SMB_INFO_QUERY_EA_SIZE:
3031 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3032 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3034 srv_put_dos_date2(pdata,0,c_time);
3035 srv_put_dos_date2(pdata,4,sbuf.st_atime);
3036 srv_put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */
3037 SIVAL(pdata,12,(uint32)file_size);
3038 SIVAL(pdata,16,(uint32)allocation_size);
3039 SSVAL(pdata,20,mode);
3040 SIVAL(pdata,22,ea_size);
3044 case SMB_INFO_IS_NAME_VALID:
3045 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3046 if (tran_call == TRANSACT2_QFILEINFO) {
3047 /* os/2 needs this ? really ?*/
3048 return ERROR_DOS(ERRDOS,ERRbadfunc);
3054 case SMB_INFO_QUERY_EAS_FROM_LIST:
3056 size_t total_ea_len = 0;
3057 struct ea_list *ea_file_list = NULL;
3059 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3061 ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3062 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3064 if (!ea_list || (total_ea_len > data_size)) {
3065 talloc_destroy(ea_ctx);
3067 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3071 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3072 talloc_destroy(ea_ctx);
3076 case SMB_INFO_QUERY_ALL_EAS:
3078 /* We have data_size bytes to put EA's into. */
3079 size_t total_ea_len = 0;
3081 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3083 ea_ctx = talloc_init("ea_ctx");
3085 return ERROR_NT(NT_STATUS_NO_MEMORY);
3088 ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3089 if (!ea_list || (total_ea_len > data_size)) {
3090 talloc_destroy(ea_ctx);
3092 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3096 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3097 talloc_destroy(ea_ctx);
3101 case SMB_FILE_BASIC_INFORMATION:
3102 case SMB_QUERY_FILE_BASIC_INFO:
3104 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3105 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3106 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3108 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3112 put_long_date(pdata,c_time);
3113 put_long_date(pdata+8,sbuf.st_atime);
3114 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3115 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3116 SIVAL(pdata,32,mode);
3118 DEBUG(5,("SMB_QFBI - "));
3120 time_t create_time = c_time;
3121 DEBUG(5,("create: %s ", ctime(&create_time)));
3123 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3124 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3125 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3126 DEBUG(5,("mode: %x\n", mode));
3129 case SMB_FILE_STANDARD_INFORMATION:
3130 case SMB_QUERY_FILE_STANDARD_INFO:
3132 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3134 SOFF_T(pdata,0,allocation_size);
3135 SOFF_T(pdata,8,file_size);
3136 SIVAL(pdata,16,nlink);
3137 SCVAL(pdata,20,delete_pending?1:0);
3138 SCVAL(pdata,21,(mode&aDIR)?1:0);
3139 SSVAL(pdata,22,0); /* Padding. */
3142 case SMB_FILE_EA_INFORMATION:
3143 case SMB_QUERY_FILE_EA_INFO:
3145 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3146 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3148 SIVAL(pdata,0,ea_size);
3152 /* Get the 8.3 name - used if NT SMB was negotiated. */
3153 case SMB_QUERY_FILE_ALT_NAME_INFO:
3154 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3158 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3159 pstrcpy(short_name,base_name);
3160 /* Mangle if not already 8.3 */
3161 if(!mangle_is_8_3(short_name, True, SNUM(conn))) {
3162 mangle_map(short_name,True,True,SNUM(conn));
3164 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3165 data_size = 4 + len;
3170 case SMB_QUERY_FILE_NAME_INFO:
3172 this must be *exactly* right for ACLs on mapped drives to work
3174 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3175 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3176 data_size = 4 + len;
3180 case SMB_FILE_ALLOCATION_INFORMATION:
3181 case SMB_QUERY_FILE_ALLOCATION_INFO:
3182 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3184 SOFF_T(pdata,0,allocation_size);
3187 case SMB_FILE_END_OF_FILE_INFORMATION:
3188 case SMB_QUERY_FILE_END_OF_FILEINFO:
3189 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3191 SOFF_T(pdata,0,file_size);
3194 case SMB_QUERY_FILE_ALL_INFO:
3195 case SMB_FILE_ALL_INFORMATION:
3197 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3198 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3199 put_long_date(pdata,c_time);
3200 put_long_date(pdata+8,sbuf.st_atime);
3201 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3202 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3203 SIVAL(pdata,32,mode);
3204 SIVAL(pdata,36,0); /* padding. */
3206 SOFF_T(pdata,0,allocation_size);
3207 SOFF_T(pdata,8,file_size);
3208 SIVAL(pdata,16,nlink);
3209 SCVAL(pdata,20,delete_pending);
3210 SCVAL(pdata,21,(mode&aDIR)?1:0);
3213 SIVAL(pdata,0,ea_size);
3214 pdata += 4; /* EA info */
3215 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3218 data_size = PTR_DIFF(pdata,(*ppdata));
3221 case SMB_FILE_INTERNAL_INFORMATION:
3222 /* This should be an index number - looks like
3225 I think this causes us to fail the IFSKIT
3226 BasicFileInformationTest. -tpot */
3228 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3229 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3230 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3234 case SMB_FILE_ACCESS_INFORMATION:
3235 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3236 SIVAL(pdata,0,access_mask);
3240 case SMB_FILE_NAME_INFORMATION:
3241 /* Pathname with leading '\'. */
3244 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
3245 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3246 SIVAL(pdata,0,byte_len);
3247 data_size = 4 + byte_len;
3251 case SMB_FILE_DISPOSITION_INFORMATION:
3252 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3254 SCVAL(pdata,0,delete_pending);
3257 case SMB_FILE_POSITION_INFORMATION:
3258 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3260 SOFF_T(pdata,0,pos);
3263 case SMB_FILE_MODE_INFORMATION:
3264 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3265 SIVAL(pdata,0,mode);
3269 case SMB_FILE_ALIGNMENT_INFORMATION:
3270 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3271 SIVAL(pdata,0,0); /* No alignment needed. */
3277 * NT4 server just returns "invalid query" to this - if we try to answer
3278 * it then NTws gets a BSOD! (tridge).
3279 * W2K seems to want this. JRA.
3281 case SMB_QUERY_FILE_STREAM_INFO:
3283 case SMB_FILE_STREAM_INFORMATION:
3284 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3288 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
3289 SIVAL(pdata,0,0); /* ??? */
3290 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3291 SOFF_T(pdata,8,file_size);
3292 SIVAL(pdata,16,allocation_size);
3293 SIVAL(pdata,20,0); /* ??? */
3294 data_size = 24 + byte_len;
3298 case SMB_QUERY_COMPRESSION_INFO:
3299 case SMB_FILE_COMPRESSION_INFORMATION:
3300 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3301 SOFF_T(pdata,0,file_size);
3302 SIVAL(pdata,8,0); /* ??? */
3303 SIVAL(pdata,12,0); /* ??? */
3307 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3308 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3309 put_long_date(pdata,c_time);
3310 put_long_date(pdata+8,sbuf.st_atime);
3311 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3312 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3313 SIVAL(pdata,32,allocation_size);
3314 SOFF_T(pdata,40,file_size);
3315 SIVAL(pdata,48,mode);
3316 SIVAL(pdata,52,0); /* ??? */
3320 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3321 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3322 SIVAL(pdata,0,mode);
3328 * CIFS UNIX Extensions.
3331 case SMB_QUERY_FILE_UNIX_BASIC:
3333 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3334 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3336 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3339 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3342 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3343 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3344 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3347 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3351 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3355 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3358 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3362 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3366 SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3369 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3373 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3376 data_size = PTR_DIFF(pdata,(*ppdata));
3380 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3382 for (i=0; i<100; i++)
3383 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3389 case SMB_QUERY_FILE_UNIX_LINK:
3393 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3395 if(!S_ISLNK(sbuf.st_mode))
3396 return(UNIXERROR(ERRSRV,ERRbadlink));
3398 return(UNIXERROR(ERRDOS,ERRbadlink));
3400 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3402 return(UNIXERROR(ERRDOS,ERRnoaccess));
3404 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3406 data_size = PTR_DIFF(pdata,(*ppdata));
3411 #if defined(HAVE_POSIX_ACLS)
3412 case SMB_QUERY_POSIX_ACL:
3414 SMB_ACL_T file_acl = NULL;
3415 SMB_ACL_T def_acl = NULL;
3416 uint16 num_file_acls = 0;
3417 uint16 num_def_acls = 0;
3419 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3420 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3422 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3425 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3426 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3428 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3431 if (S_ISDIR(sbuf.st_mode)) {
3432 if (fsp && fsp->is_directory) {
3433 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3435 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3437 def_acl = free_empty_sys_acl(conn, def_acl);
3440 num_file_acls = count_acl_entries(conn, file_acl);
3441 num_def_acls = count_acl_entries(conn, def_acl);
3443 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3444 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3446 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3447 SMB_POSIX_ACL_HEADER_SIZE) ));
3449 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3452 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3454 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3457 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3458 SSVAL(pdata,2,num_file_acls);
3459 SSVAL(pdata,4,num_def_acls);
3460 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3462 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3465 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3467 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3469 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3471 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3474 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3476 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3480 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3483 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3485 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3491 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3494 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3499 /****************************************************************************
3500 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3502 ****************************************************************************/
3504 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3506 BOOL bad_path_oldname = False;
3507 BOOL bad_path_newname = False;
3508 SMB_STRUCT_STAT sbuf1, sbuf2;
3509 pstring last_component_oldname;
3510 pstring last_component_newname;
3511 NTSTATUS status = NT_STATUS_OK;
3517 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3518 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3521 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3522 if (bad_path_oldname) {
3523 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3526 /* Quick check for "." and ".." */
3527 if (last_component_oldname[0] == '.') {
3528 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3529 return NT_STATUS_OBJECT_NAME_INVALID;
3533 /* source must already exist. */
3534 if (!VALID_STAT(sbuf1)) {
3535 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3538 if (!check_name(oldname,conn)) {
3539 return NT_STATUS_ACCESS_DENIED;
3542 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3543 if (bad_path_newname) {
3544 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3547 /* Quick check for "." and ".." */
3548 if (last_component_newname[0] == '.') {
3549 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3550 return NT_STATUS_OBJECT_NAME_INVALID;
3554 /* Disallow if newname already exists. */
3555 if (VALID_STAT(sbuf2)) {
3556 return NT_STATUS_OBJECT_NAME_COLLISION;
3559 if (!check_name(newname,conn)) {
3560 return NT_STATUS_ACCESS_DENIED;
3563 /* No links from a directory. */
3564 if (S_ISDIR(sbuf1.st_mode)) {
3565 return NT_STATUS_FILE_IS_A_DIRECTORY;
3568 /* Ensure this is within the share. */
3569 if (!reduce_name(conn, oldname) != 0)
3570 return NT_STATUS_ACCESS_DENIED;
3572 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3574 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3575 status = map_nt_error_from_unix(errno);
3576 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3577 nt_errstr(status), newname, oldname));
3583 /****************************************************************************
3584 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3585 ****************************************************************************/
3587 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3588 unsigned int tran_call,
3589 char **pparams, int total_params, char **ppdata, int total_data,
3590 unsigned int max_data_bytes)
3592 char *params = *pparams;
3593 char *pdata = *ppdata;
3598 SMB_STRUCT_STAT sbuf;
3601 BOOL bad_path = False;
3602 files_struct *fsp = NULL;
3603 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3604 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3605 mode_t unixmode = 0;
3606 NTSTATUS status = NT_STATUS_OK;
3609 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3614 if (tran_call == TRANSACT2_SETFILEINFO) {
3615 if (total_params < 4) {
3616 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3619 fsp = file_fsp(params,0);
3620 info_level = SVAL(params,2);
3622 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3624 * This is actually a SETFILEINFO on a directory
3625 * handle (returned from an NT SMB). NT5.0 seems
3626 * to do this call. JRA.
3628 pstrcpy(fname, fsp->fsp_name);
3629 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3630 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3631 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3633 } else if (fsp && fsp->print_file) {
3635 * Doing a DELETE_ON_CLOSE should cancel a print job.
3637 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3638 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
3640 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3643 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3646 return (UNIXERROR(ERRDOS,ERRbadpath));
3649 * Original code - this is an open file.
3651 CHECK_FSP(fsp,conn);
3653 pstrcpy(fname, fsp->fsp_name);
3656 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3657 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3658 return(UNIXERROR(ERRDOS,ERRbadfid));
3663 if (total_params < 6) {
3664 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3667 info_level = SVAL(params,0);
3668 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
3669 if (!NT_STATUS_IS_OK(status)) {
3670 return ERROR_NT(status);
3672 unix_convert(fname,conn,0,&bad_path,&sbuf);
3674 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3678 * For CIFS UNIX extensions the target name may not exist.
3681 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3682 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3683 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3686 if(!check_name(fname, conn)) {
3687 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3692 if (!CAN_WRITE(conn))
3693 return ERROR_DOS(ERRSRV,ERRaccess);
3695 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3696 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3698 if (VALID_STAT(sbuf))
3699 unixmode = sbuf.st_mode;
3701 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3702 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3704 /* Realloc the parameter size */
3705 params = SMB_REALLOC(*pparams,2);
3706 if(params == NULL) {
3707 return ERROR_NT(NT_STATUS_NO_MEMORY);
3713 if (fsp && fsp->pending_modtime) {
3714 /* the pending modtime overrides the current modtime */
3715 sbuf.st_mtime = fsp->pending_modtime;
3718 size = get_file_size(sbuf);
3719 tvs.modtime = sbuf.st_mtime;
3720 tvs.actime = sbuf.st_atime;
3721 dosmode = dos_mode(conn,fname,&sbuf);
3722 unixmode = sbuf.st_mode;
3724 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3725 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3727 switch (info_level) {
3728 case SMB_INFO_STANDARD:
3730 if (total_data < 12) {
3731 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3735 tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
3737 tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
3741 case SMB_INFO_SET_EA:
3743 struct ea_list *ea_list = NULL;
3744 TALLOC_CTX *ctx = NULL;
3746 if (total_data < 10) {
3748 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3749 length. They seem to have no effect. Bug #3212. JRA */
3751 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3752 /* We're done. We only get EA info in this call. */
3754 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3758 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3761 if (IVAL(pdata,0) > total_data) {
3762 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3763 IVAL(pdata,0), (unsigned int)total_data));
3764 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3767 ctx = talloc_init("SMB_INFO_SET_EA");
3769 return ERROR_NT(NT_STATUS_NO_MEMORY);
3771 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3773 talloc_destroy(ctx);
3774 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3776 status = set_ea(conn, fsp, fname, ea_list);
3777 talloc_destroy(ctx);
3779 if (!NT_STATUS_IS_OK(status)) {
3780 return ERROR_NT(status);
3783 /* We're done. We only get EA info in this call. */
3785 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3790 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3791 /* XXXX um, i don't think this is right.
3792 it's also not in the cifs6.txt spec.
3794 case SMB_INFO_QUERY_EAS_FROM_LIST:
3795 if (total_data < 28)
3796 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3798 tvs.actime = make_unix_date2(pdata+8);
3799 tvs.modtime = make_unix_date2(pdata+12);
3800 size = IVAL(pdata,16);
3801 dosmode = IVAL(pdata,24);
3804 /* XXXX nor this. not in cifs6.txt, either. */
3805 case SMB_INFO_QUERY_ALL_EAS:
3806 if (total_data < 28)
3807 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3809 tvs.actime = make_unix_date2(pdata+8);
3810 tvs.modtime = make_unix_date2(pdata+12);
3811 size = IVAL(pdata,16);
3812 dosmode = IVAL(pdata,24);
3816 case SMB_SET_FILE_BASIC_INFO:
3817 case SMB_FILE_BASIC_INFORMATION:
3819 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3821 time_t changed_time;
3823 if (total_data < 36) {
3824 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3827 /* Ignore create time at offset pdata. */
3830 tvs.actime = interpret_long_date(pdata+8);
3832 write_time = interpret_long_date(pdata+16);
3833 changed_time = interpret_long_date(pdata+24);
3835 tvs.modtime = MIN(write_time, changed_time);
3837 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3838 tvs.modtime = write_time;
3840 /* Prefer a defined time to an undefined one. */
3841 if (null_mtime(tvs.modtime)) {
3842 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3846 dosmode = IVAL(pdata,32);
3850 case SMB_FILE_ALLOCATION_INFORMATION:
3851 case SMB_SET_FILE_ALLOCATION_INFO:
3854 SMB_BIG_UINT allocation_size;
3856 if (total_data < 8) {
3857 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3860 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3861 #ifdef LARGE_SMB_OFF_T
3862 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3863 #else /* LARGE_SMB_OFF_T */
3864 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3865 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3866 #endif /* LARGE_SMB_OFF_T */
3867 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3868 fname, (double)allocation_size ));
3870 if (allocation_size) {
3871 allocation_size = smb_roundup(conn, allocation_size);
3874 if(allocation_size != get_file_size(sbuf)) {
3875 SMB_STRUCT_STAT new_sbuf;
3877 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3878 fname, (double)allocation_size ));
3881 files_struct *new_fsp = NULL;
3883 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
3885 FILE_SHARE_READ|FILE_SHARE_WRITE,
3888 FILE_ATTRIBUTE_NORMAL,
3892 if (new_fsp == NULL) {
3893 return(UNIXERROR(ERRDOS,ERRbadpath));
3895 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3896 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
3897 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3898 new_fsp->fnum, strerror(errno)));
3901 close_file(new_fsp,True);
3903 ret = vfs_allocate_file_space(fsp, allocation_size);
3904 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3905 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3906 fsp->fnum, strerror(errno)));
3911 return ERROR_NT(NT_STATUS_DISK_FULL);
3913 /* Allocate can truncate size... */
3914 size = get_file_size(new_sbuf);
3920 case SMB_FILE_END_OF_FILE_INFORMATION:
3921 case SMB_SET_FILE_END_OF_FILE_INFO:
3923 if (total_data < 8) {
3924 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3927 size = IVAL(pdata,0);
3928 #ifdef LARGE_SMB_OFF_T
3929 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3930 #else /* LARGE_SMB_OFF_T */
3931 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3932 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3933 #endif /* LARGE_SMB_OFF_T */
3934 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3938 case SMB_FILE_DISPOSITION_INFORMATION:
3939 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3941 BOOL delete_on_close;
3943 if (total_data < 1) {
3944 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3947 delete_on_close = (CVAL(pdata,0) ? True : False);
3949 /* Just ignore this set on a path. */
3950 if (tran_call != TRANSACT2_SETFILEINFO)
3954 return(UNIXERROR(ERRDOS,ERRbadfid));
3956 status = can_set_delete_on_close(fsp, delete_on_close,
3959 if (!NT_STATUS_IS_OK(status)) {
3960 return ERROR_NT(status);
3963 /* The set is across all open files on this dev/inode pair. */
3964 if (!set_delete_on_close(fsp, delete_on_close)) {
3965 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3969 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3973 case SMB_FILE_POSITION_INFORMATION:
3975 SMB_BIG_UINT position_information;
3977 if (total_data < 8) {
3978 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3981 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3982 #ifdef LARGE_SMB_OFF_T
3983 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3984 #else /* LARGE_SMB_OFF_T */
3985 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3986 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3987 #endif /* LARGE_SMB_OFF_T */
3988 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3989 fname, (double)position_information ));
3991 fsp->fh->position_information = position_information;
3994 /* We're done. We only get position info in this call. */
3996 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4000 /* From tridge Samba4 :
4001 * MODE_INFORMATION in setfileinfo (I have no
4002 * idea what "mode information" on a file is - it takes a value of 0,
4003 * 2, 4 or 6. What could it be?).
4006 case SMB_FILE_MODE_INFORMATION:
4010 if (total_data < 4) {
4011 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4013 mode = IVAL(pdata,0);
4014 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4015 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4018 /* We're done. We only get mode info in this call. */
4020 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4025 * CIFS UNIX extensions.
4028 case SMB_SET_FILE_UNIX_BASIC:
4030 uint32 raw_unixmode;
4032 if (total_data < 100) {
4033 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4036 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4037 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4038 size=IVAL(pdata,0); /* first 8 Bytes are size */
4039 #ifdef LARGE_SMB_OFF_T
4040 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4041 #else /* LARGE_SMB_OFF_T */
4042 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
4043 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4044 #endif /* LARGE_SMB_OFF_T */
4046 pdata+=24; /* ctime & st_blocks are not changed */
4047 tvs.actime = interpret_long_date(pdata); /* access_time */
4048 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
4050 set_owner = (uid_t)IVAL(pdata,0);
4052 set_grp = (gid_t)IVAL(pdata,0);
4054 raw_unixmode = IVAL(pdata,28);
4055 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4056 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4058 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4059 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4060 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4062 if (!VALID_STAT(sbuf)) {
4065 * The only valid use of this is to create character and block
4066 * devices, and named pipes. This is deprecated (IMHO) and
4067 * a new info level should be used for mknod. JRA.
4070 uint32 file_type = IVAL(pdata,0);
4071 #if defined(HAVE_MAKEDEV)
4072 uint32 dev_major = IVAL(pdata,4);
4073 uint32 dev_minor = IVAL(pdata,12);
4076 uid_t myuid = geteuid();
4077 gid_t mygid = getegid();
4078 SMB_DEV_T dev = (SMB_DEV_T)0;
4080 if (tran_call == TRANSACT2_SETFILEINFO)
4081 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4083 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4084 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4087 #if defined(HAVE_MAKEDEV)
4088 dev = makedev(dev_major, dev_minor);
4091 /* We can only create as the owner/group we are. */
4093 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4094 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4095 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4096 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4098 switch (file_type) {
4099 #if defined(S_IFIFO)
4100 case UNIX_TYPE_FIFO:
4101 unixmode |= S_IFIFO;
4104 #if defined(S_IFSOCK)
4105 case UNIX_TYPE_SOCKET:
4106 unixmode |= S_IFSOCK;
4109 #if defined(S_IFCHR)
4110 case UNIX_TYPE_CHARDEV:
4111 unixmode |= S_IFCHR;
4114 #if defined(S_IFBLK)
4115 case UNIX_TYPE_BLKDEV:
4116 unixmode |= S_IFBLK;
4120 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4123 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4124 0%o for file %s\n", (double)dev, unixmode, fname ));
4126 /* Ok - do the mknod. */
4127 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4128 return(UNIXERROR(ERRDOS,ERRnoaccess));
4130 inherit_access_acl(conn, fname, unixmode);
4133 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4138 * Deal with the UNIX specific mode set.
4141 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4142 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4143 (unsigned int)unixmode, fname ));
4144 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4145 return(UNIXERROR(ERRDOS,ERRnoaccess));
4149 * Deal with the UNIX specific uid set.
4152 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4153 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4154 (unsigned int)set_owner, fname ));
4155 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4156 return(UNIXERROR(ERRDOS,ERRnoaccess));
4160 * Deal with the UNIX specific gid set.
4163 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4164 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4165 (unsigned int)set_owner, fname ));
4166 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4167 return(UNIXERROR(ERRDOS,ERRnoaccess));
4172 case SMB_SET_FILE_UNIX_LINK:
4174 pstring link_target;
4175 char *newname = fname;
4177 /* Set a symbolic link. */
4178 /* Don't allow this if follow links is false. */
4180 if (!lp_symlinks(SNUM(conn)))
4181 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4183 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4185 /* !widelinks forces the target path to be within the share. */
4186 /* This means we can interpret the target as a pathname. */
4187 if (!lp_widelinks(SNUM(conn))) {
4189 char *last_dirp = NULL;
4191 unix_format(link_target);
4192 if (*link_target == '/') {
4193 /* No absolute paths allowed. */
4194 return(UNIXERROR(ERRDOS,ERRnoaccess));
4196 pstrcpy(rel_name, newname);
4197 last_dirp = strrchr_m(rel_name, '/');
4199 last_dirp[1] = '\0';
4201 pstrcpy(rel_name, "./");
4203 pstrcat(rel_name, link_target);
4205 if (!check_name(rel_name, conn)) {
4206 return(UNIXERROR(ERRDOS,ERRnoaccess));
4210 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4211 fname, link_target ));
4213 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4214 return(UNIXERROR(ERRDOS,ERRnoaccess));
4216 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4220 case SMB_SET_FILE_UNIX_HLINK:
4223 char *newname = fname;
4225 /* Set a hard link. */
4226 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
4227 if (!NT_STATUS_IS_OK(status)) {
4228 return ERROR_NT(status);
4231 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4234 status = hardlink_internals(conn, oldname, newname);
4235 if (!NT_STATUS_IS_OK(status)) {
4236 return ERROR_NT(status);
4240 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4244 case SMB_FILE_RENAME_INFORMATION:
4253 if (total_data < 12) {
4254 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4257 overwrite = (CVAL(pdata,0) ? True : False);
4258 root_fid = IVAL(pdata,4);
4259 len = IVAL(pdata,8);
4260 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
4261 if (!NT_STATUS_IS_OK(status)) {
4262 return ERROR_NT(status);
4265 /* Check the new name has no '/' characters. */
4266 if (strchr_m(newname, '/'))
4267 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4269 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4271 /* Create the base directory. */
4272 pstrcpy(base_name, fname);
4273 p = strrchr_m(base_name, '/');
4276 /* Append the new name. */
4277 pstrcat(base_name, "/");
4278 pstrcat(base_name, newname);
4281 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4282 fsp->fnum, fsp->fsp_name, base_name ));
4283 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4285 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4287 status = rename_internals(conn, fname, base_name, 0, overwrite, False);
4289 if (!NT_STATUS_IS_OK(status)) {
4290 return ERROR_NT(status);
4292 process_pending_change_notify_queue((time_t)0);
4294 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4298 #if defined(HAVE_POSIX_ACLS)
4299 case SMB_SET_POSIX_ACL:
4301 uint16 posix_acl_version;
4302 uint16 num_file_acls;
4303 uint16 num_def_acls;
4304 BOOL valid_file_acls = True;
4305 BOOL valid_def_acls = True;
4307 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4308 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4310 posix_acl_version = SVAL(pdata,0);
4311 num_file_acls = SVAL(pdata,2);
4312 num_def_acls = SVAL(pdata,4);
4314 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4315 valid_file_acls = False;
4319 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4320 valid_def_acls = False;
4324 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4325 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4328 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4329 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4330 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4333 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4334 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4335 return(UNIXERROR(ERRDOS,ERRnoaccess));
4338 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4339 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4340 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4341 return(UNIXERROR(ERRDOS,ERRnoaccess));
4345 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4351 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4354 /* get some defaults (no modifications) if any info is zero or -1. */
4355 if (null_mtime(tvs.actime)) {
4356 tvs.actime = sbuf.st_atime;
4359 if (null_mtime(tvs.modtime)) {
4360 tvs.modtime = sbuf.st_mtime;
4363 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4364 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4365 DEBUG(6,("size: %.0f ", (double)size));
4368 if (S_ISDIR(sbuf.st_mode))
4374 DEBUG(6,("dosmode: %x\n" , dosmode));
4376 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4377 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4378 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4379 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4382 * Only do this test if we are not explicitly
4383 * changing the size of a file.
4386 size = get_file_size(sbuf);
4390 * Try and set the times, size and mode of this file -
4391 * if they are different from the current values
4394 /* check the mode isn't different, before changing it */
4395 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4397 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4399 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4400 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4401 return(UNIXERROR(ERRDOS,ERRnoaccess));
4406 if (size != get_file_size(sbuf)) {
4410 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4411 fname, (double)size ));
4414 files_struct *new_fsp = NULL;
4416 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
4418 FILE_SHARE_READ|FILE_SHARE_WRITE,
4421 FILE_ATTRIBUTE_NORMAL,
4425 if (new_fsp == NULL) {
4426 return(UNIXERROR(ERRDOS,ERRbadpath));
4428 ret = vfs_set_filelen(new_fsp, size);
4429 close_file(new_fsp,True);
4431 ret = vfs_set_filelen(fsp, size);
4435 return (UNIXERROR(ERRHRD,ERRdiskfull));
4440 * Finally the times.
4442 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4445 * This was a setfileinfo on an open file.
4446 * NT does this a lot. We also need to
4447 * set the time here, as it can be read by
4448 * FindFirst/FindNext and with the patch for bug #2045
4449 * in smbd/fileio.c it ensures that this timestamp is
4450 * kept sticky even after a write. We save the request
4451 * away and will set it on file close and after a write. JRA.
4454 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4455 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4456 fsp_set_pending_modtime(fsp, tvs.modtime);
4460 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4462 if(file_utime(conn, fname, &tvs)!=0) {
4463 return(UNIXERROR(ERRDOS,ERRnoaccess));
4468 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4473 /****************************************************************************
4474 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4475 ****************************************************************************/
4477 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4478 char **pparams, int total_params, char **ppdata, int total_data,
4479 unsigned int max_data_bytes)
4481 char *params = *pparams;
4482 char *pdata = *ppdata;
4485 SMB_STRUCT_STAT sbuf;
4486 BOOL bad_path = False;
4487 NTSTATUS status = NT_STATUS_OK;
4488 TALLOC_CTX *ctx = NULL;
4489 struct ea_list *ea_list = NULL;
4491 if (!CAN_WRITE(conn))
4492 return ERROR_DOS(ERRSRV,ERRaccess);
4494 if (total_params < 4) {
4495 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4498 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status);
4499 if (!NT_STATUS_IS_OK(status)) {
4500 return ERROR_NT(status);
4503 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4505 unix_convert(directory,conn,0,&bad_path,&sbuf);
4507 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4510 /* Any data in this call is an EA list. */
4511 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
4512 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4516 * OS/2 workplace shell seems to send SET_EA requests of "null"
4517 * length (4 bytes containing IVAL 4).
4518 * They seem to have no effect. Bug #3212. JRA.
4521 if (total_data != 4) {
4522 if (total_data < 10) {
4523 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4526 if (IVAL(pdata,0) > total_data) {
4527 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4528 IVAL(pdata,0), (unsigned int)total_data));
4529 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4532 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4534 return ERROR_NT(NT_STATUS_NO_MEMORY);
4536 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4538 talloc_destroy(ctx);
4539 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4541 } else if (IVAL(pdata,0) != 4) {
4542 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4545 if (check_name(directory,conn)) {
4546 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4550 talloc_destroy(ctx);
4551 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4552 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4555 /* Try and set any given EA. */
4557 status = set_ea(conn, NULL, directory, ea_list);
4558 talloc_destroy(ctx);
4559 if (!NT_STATUS_IS_OK(status)) {
4560 return ERROR_NT(status);
4564 /* Realloc the parameter and data sizes */
4565 params = SMB_REALLOC(*pparams,2);
4566 if(params == NULL) {
4567 return ERROR_NT(NT_STATUS_NO_MEMORY);
4573 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4578 /****************************************************************************
4579 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4580 We don't actually do this - we just send a null response.
4581 ****************************************************************************/
4583 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4584 char **pparams, int total_params, char **ppdata, int total_data,
4585 unsigned int max_data_bytes)
4587 static uint16 fnf_handle = 257;
4588 char *params = *pparams;
4591 if (total_params < 6) {
4592 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4595 info_level = SVAL(params,4);
4596 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4598 switch (info_level) {
4603 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4606 /* Realloc the parameter and data sizes */
4607 params = SMB_REALLOC(*pparams,6);
4608 if(params == NULL) {
4609 return ERROR_NT(NT_STATUS_NO_MEMORY);
4613 SSVAL(params,0,fnf_handle);
4614 SSVAL(params,2,0); /* No changes */
4615 SSVAL(params,4,0); /* No EA errors */
4622 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4627 /****************************************************************************
4628 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4629 changes). Currently this does nothing.
4630 ****************************************************************************/
4632 static int call_trans2findnotifynext(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;
4638 DEBUG(3,("call_trans2findnotifynext\n"));
4640 /* Realloc the parameter and data sizes */
4641 params = SMB_REALLOC(*pparams,4);
4642 if(params == NULL) {
4643 return ERROR_NT(NT_STATUS_NO_MEMORY);
4647 SSVAL(params,0,0); /* No changes */
4648 SSVAL(params,2,0); /* No EA errors */
4650 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4655 /****************************************************************************
4656 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4657 ****************************************************************************/
4659 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4660 char **pparams, int total_params, char **ppdata, int total_data,
4661 unsigned int max_data_bytes)
4663 char *params = *pparams;
4666 int max_referral_level;
4668 DEBUG(10,("call_trans2getdfsreferral\n"));
4670 if (total_params < 2) {
4671 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4674 max_referral_level = SVAL(params,0);
4676 if(!lp_host_msdfs())
4677 return ERROR_DOS(ERRDOS,ERRbadfunc);
4679 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4680 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4681 return UNIXERROR(ERRDOS,ERRbadfile);
4683 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4684 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4689 #define LMCAT_SPL 0x53
4690 #define LMFUNC_GETJOBID 0x60
4692 /****************************************************************************
4693 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4694 ****************************************************************************/
4696 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4697 char **pparams, int total_params, char **ppdata, int total_data,
4698 unsigned int max_data_bytes)
4700 char *pdata = *ppdata;
4701 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4703 /* check for an invalid fid before proceeding */
4706 return(ERROR_DOS(ERRDOS,ERRbadfid));
4708 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4709 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4710 pdata = SMB_REALLOC(*ppdata, 32);
4712 return ERROR_NT(NT_STATUS_NO_MEMORY);
4716 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4717 CAN ACCEPT THIS IN UNICODE. JRA. */
4719 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4720 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4721 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4722 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4725 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4726 return ERROR_DOS(ERRSRV,ERRerror);
4730 /****************************************************************************
4731 Reply to a SMBfindclose (stop trans2 directory search).
4732 ****************************************************************************/
4734 int reply_findclose(connection_struct *conn,
4735 char *inbuf,char *outbuf,int length,int bufsize)
4738 int dptr_num=SVALS(inbuf,smb_vwv0);
4739 START_PROFILE(SMBfindclose);
4741 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4743 dptr_close(&dptr_num);
4745 outsize = set_message(outbuf,0,0,True);
4747 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4749 END_PROFILE(SMBfindclose);
4753 /****************************************************************************
4754 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4755 ****************************************************************************/
4757 int reply_findnclose(connection_struct *conn,
4758 char *inbuf,char *outbuf,int length,int bufsize)
4762 START_PROFILE(SMBfindnclose);
4764 dptr_num = SVAL(inbuf,smb_vwv0);
4766 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4768 /* We never give out valid handles for a
4769 findnotifyfirst - so any dptr_num is ok here.
4772 outsize = set_message(outbuf,0,0,True);
4774 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4776 END_PROFILE(SMBfindnclose);
4780 /****************************************************************************
4781 Reply to a SMBtranss2 - just ignore it!
4782 ****************************************************************************/
4784 int reply_transs2(connection_struct *conn,
4785 char *inbuf,char *outbuf,int length,int bufsize)
4787 START_PROFILE(SMBtranss2);
4788 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4789 END_PROFILE(SMBtranss2);
4793 /****************************************************************************
4794 Reply to a SMBtrans2.
4795 ****************************************************************************/
4797 int reply_trans2(connection_struct *conn,
4798 char *inbuf,char *outbuf,int length,int bufsize)
4801 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4802 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4803 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4805 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4806 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4807 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4808 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4809 int32 timeout = IVALS(inbuf,smb_timeout);
4811 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4812 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4813 char *params = NULL, *data = NULL;
4814 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4815 START_PROFILE(SMBtrans2);
4817 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4818 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4819 END_PROFILE(SMBtrans2);
4820 return ERROR_DOS(ERRSRV,ERRaccess);
4823 outsize = set_message(outbuf,0,0,True);
4825 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4826 is so as a sanity check */
4829 * Need to have rc=0 for ioctl to get job id for OS/2.
4830 * Network printing will fail if function is not successful.
4831 * Similar function in reply.c will be used if protocol
4832 * is LANMAN1.0 instead of LM1.2X002.
4833 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4834 * outbuf doesn't have to be set(only job id is used).
4836 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4837 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4838 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4839 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4841 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4842 DEBUG(2,("Transaction is %d\n",tran_call));
4843 END_PROFILE(SMBtrans2);
4844 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4848 /* Allocate the space for the maximum needed parameters and data */
4849 if (total_params > 0)
4850 params = (char *)SMB_MALLOC(total_params);
4852 data = (char *)SMB_MALLOC(total_data);
4854 if ((total_params && !params) || (total_data && !data)) {
4855 DEBUG(2,("Out of memory in reply_trans2\n"));
4858 END_PROFILE(SMBtrans2);
4859 return ERROR_NT(NT_STATUS_NO_MEMORY);
4862 /* Copy the param and data bytes sent with this request into
4863 the params buffer */
4864 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4865 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4867 if (num_params > total_params || num_data > total_data)
4868 exit_server("invalid params in reply_trans2");
4871 unsigned int psoff = SVAL(inbuf, smb_psoff);
4872 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4874 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4875 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4877 memcpy( params, smb_base(inbuf) + psoff, num_params);
4880 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4881 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4883 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4884 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4886 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4889 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4891 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4892 /* We need to send an interim response then receive the rest
4893 of the parameter/data bytes */
4894 outsize = set_message(outbuf,0,0,True);
4895 srv_signing_trans_stop();
4897 if (!send_smb(smbd_server_fd(),outbuf))
4898 exit_server("reply_trans2: send_smb failed.");
4900 while (num_data_sofar < total_data ||
4901 num_params_sofar < total_params) {
4903 unsigned int param_disp;
4904 unsigned int param_off;
4905 unsigned int data_disp;
4906 unsigned int data_off;
4908 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4910 /* We need to re-calcuate the new length after we've read the secondary packet. */
4911 length = smb_len(inbuf) + 4;
4914 * The sequence number for the trans reply is always
4915 * based on the last secondary received.
4918 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4921 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4922 outsize = set_message(outbuf,0,0,True);
4924 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4926 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4927 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4931 /* Revise total_params and total_data in case
4932 they have changed downwards */
4933 if (SVAL(inbuf, smb_tpscnt) < total_params)
4934 total_params = SVAL(inbuf, smb_tpscnt);
4935 if (SVAL(inbuf, smb_tdscnt) < total_data)
4936 total_data = SVAL(inbuf, smb_tdscnt);
4938 num_params = SVAL(inbuf,smb_spscnt);
4939 param_off = SVAL(inbuf, smb_spsoff);
4940 param_disp = SVAL(inbuf, smb_spsdisp);
4941 num_params_sofar += num_params;
4943 num_data = SVAL(inbuf, smb_sdscnt);
4944 data_off = SVAL(inbuf, smb_sdsoff);
4945 data_disp = SVAL(inbuf, smb_sdsdisp);
4946 num_data_sofar += num_data;
4948 if (num_params_sofar > total_params || num_data_sofar > total_data)
4952 if (param_disp + num_params > total_params)
4954 if ((param_disp + num_params < param_disp) ||
4955 (param_disp + num_params < num_params))
4957 if (param_disp > total_params)
4959 if ((smb_base(inbuf) + param_off + num_params > inbuf + length) ||
4960 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4962 if (params + param_disp < params)
4965 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
4968 if (data_disp + num_data > total_data)
4970 if ((data_disp + num_data < data_disp) ||
4971 (data_disp + num_data < num_data))
4973 if (data_disp > total_data)
4975 if ((smb_base(inbuf) + data_off + num_data > inbuf + length) ||
4976 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4978 if (data + data_disp < data)
4981 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4986 if (Protocol >= PROTOCOL_NT1) {
4987 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4990 /* Now we must call the relevant TRANS2 function */
4992 case TRANSACT2_OPEN:
4993 START_PROFILE_NESTED(Trans2_open);
4994 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4995 ¶ms, total_params, &data, total_data, max_data_bytes);
4996 END_PROFILE_NESTED(Trans2_open);
4999 case TRANSACT2_FINDFIRST:
5000 START_PROFILE_NESTED(Trans2_findfirst);
5001 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
5002 ¶ms, total_params, &data, total_data, max_data_bytes);
5003 END_PROFILE_NESTED(Trans2_findfirst);
5006 case TRANSACT2_FINDNEXT:
5007 START_PROFILE_NESTED(Trans2_findnext);
5008 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
5009 ¶ms, total_params, &data, total_data, max_data_bytes);
5010 END_PROFILE_NESTED(Trans2_findnext);
5013 case TRANSACT2_QFSINFO:
5014 START_PROFILE_NESTED(Trans2_qfsinfo);
5015 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
5016 ¶ms, total_params, &data, total_data, max_data_bytes);
5017 END_PROFILE_NESTED(Trans2_qfsinfo);
5020 case TRANSACT2_SETFSINFO:
5021 START_PROFILE_NESTED(Trans2_setfsinfo);
5022 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
5023 ¶ms, total_params, &data, total_data, max_data_bytes);
5024 END_PROFILE_NESTED(Trans2_setfsinfo);
5027 case TRANSACT2_QPATHINFO:
5028 case TRANSACT2_QFILEINFO:
5029 START_PROFILE_NESTED(Trans2_qpathinfo);
5030 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5031 ¶ms, total_params, &data, total_data, max_data_bytes);
5032 END_PROFILE_NESTED(Trans2_qpathinfo);
5034 case TRANSACT2_SETPATHINFO:
5035 case TRANSACT2_SETFILEINFO:
5036 START_PROFILE_NESTED(Trans2_setpathinfo);
5037 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5038 ¶ms, total_params, &data, total_data, max_data_bytes);
5039 END_PROFILE_NESTED(Trans2_setpathinfo);
5042 case TRANSACT2_FINDNOTIFYFIRST:
5043 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5044 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
5045 ¶ms, total_params, &data, total_data, max_data_bytes);
5046 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5049 case TRANSACT2_FINDNOTIFYNEXT:
5050 START_PROFILE_NESTED(Trans2_findnotifynext);
5051 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
5052 ¶ms, total_params, &data, total_data, max_data_bytes);
5053 END_PROFILE_NESTED(Trans2_findnotifynext);
5055 case TRANSACT2_MKDIR:
5056 START_PROFILE_NESTED(Trans2_mkdir);
5057 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
5058 ¶ms, total_params, &data, total_data, max_data_bytes);
5059 END_PROFILE_NESTED(Trans2_mkdir);
5062 case TRANSACT2_GET_DFS_REFERRAL:
5063 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5064 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
5065 ¶ms, total_params, &data, total_data, max_data_bytes);
5066 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5068 case TRANSACT2_IOCTL:
5069 START_PROFILE_NESTED(Trans2_ioctl);
5070 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
5071 ¶ms, total_params, &data, total_data, max_data_bytes);
5072 END_PROFILE_NESTED(Trans2_ioctl);
5075 /* Error in request */
5076 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
5079 END_PROFILE(SMBtrans2);
5080 srv_signing_trans_stop();
5081 return ERROR_DOS(ERRSRV,ERRerror);
5084 /* As we do not know how many data packets will need to be
5085 returned here the various call_trans2xxxx calls
5086 must send their own. Thus a call_trans2xxx routine only
5087 returns a value other than -1 when it wants to send
5091 srv_signing_trans_stop();
5095 END_PROFILE(SMBtrans2);
5096 return outsize; /* If a correct response was needed the
5097 call_trans2xxx calls have already sent
5098 it. If outsize != -1 then it is returning */
5102 srv_signing_trans_stop();
5105 END_PROFILE(SMBtrans2);
5106 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);