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,ERROR_CLOSE);
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,ERROR_CLOSE);
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));
1150 file_size = get_file_size(sbuf);
1151 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1152 mdate = sbuf.st_mtime;
1153 adate = sbuf.st_atime;
1154 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1156 if (lp_dos_filetime_resolution(SNUM(conn))) {
1163 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1169 mangle_map(fname,False,True,SNUM(conn));
1174 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1176 switch (info_level) {
1177 case SMB_FIND_INFO_STANDARD:
1178 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1179 if(requires_resume_key) {
1183 srv_put_dos_date2(p,0,cdate);
1184 srv_put_dos_date2(p,4,adate);
1185 srv_put_dos_date2(p,8,mdate);
1186 SIVAL(p,12,(uint32)file_size);
1187 SIVAL(p,16,(uint32)allocation_size);
1191 p += align_string(outbuf, p, 0);
1192 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1193 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1195 SCVAL(nameptr, -1, len - 2);
1197 SCVAL(nameptr, -1, 0);
1201 SCVAL(nameptr, -1, len - 1);
1203 SCVAL(nameptr, -1, 0);
1209 case SMB_FIND_EA_SIZE:
1210 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1211 if(requires_resume_key) {
1215 srv_put_dos_date2(p,0,cdate);
1216 srv_put_dos_date2(p,4,adate);
1217 srv_put_dos_date2(p,8,mdate);
1218 SIVAL(p,12,(uint32)file_size);
1219 SIVAL(p,16,(uint32)allocation_size);
1222 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1223 SIVAL(p,22,ea_size); /* Extended attributes */
1227 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1228 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1241 SCVAL(nameptr,0,len);
1243 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1246 case SMB_FIND_EA_LIST:
1248 struct ea_list *file_list = NULL;
1251 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1255 if(requires_resume_key) {
1259 srv_put_dos_date2(p,0,cdate);
1260 srv_put_dos_date2(p,4,adate);
1261 srv_put_dos_date2(p,8,mdate);
1262 SIVAL(p,12,(uint32)file_size);
1263 SIVAL(p,16,(uint32)allocation_size);
1265 p += 22; /* p now points to the EA area. */
1267 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1268 name_list = ea_list_union(name_list, file_list, &ea_len);
1270 /* We need to determine if this entry will fit in the space available. */
1271 /* Max string size is 255 bytes. */
1272 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1273 /* Move the dirptr back to prev_dirpos */
1274 dptr_SeekDir(conn->dirptr, prev_dirpos);
1275 *out_of_space = True;
1276 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1277 return False; /* Not finished - just out of space */
1280 /* Push the ea_data followed by the name. */
1281 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1283 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1284 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1297 SCVAL(nameptr,0,len);
1299 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1303 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1304 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1305 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1307 SIVAL(p,0,reskey); p += 4;
1308 put_long_date(p,cdate); p += 8;
1309 put_long_date(p,adate); p += 8;
1310 put_long_date(p,mdate); p += 8;
1311 put_long_date(p,mdate); p += 8;
1312 SOFF_T(p,0,file_size); p += 8;
1313 SOFF_T(p,0,allocation_size); p += 8;
1314 SIVAL(p,0,nt_extmode); p += 4;
1315 q = p; p += 4; /* q is placeholder for name length. */
1317 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1318 SIVAL(p,0,ea_size); /* Extended attributes */
1321 /* Clear the short name buffer. This is
1322 * IMPORTANT as not doing so will trigger
1323 * a Win2k client bug. JRA.
1325 if (!was_8_3 && check_mangled_names) {
1326 pstring mangled_name;
1327 pstrcpy(mangled_name, fname);
1328 mangle_map(mangled_name,True,True,SNUM(conn));
1329 mangled_name[12] = 0;
1330 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1332 memset(p + 2 + len,'\0',24 - len);
1339 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1342 SIVAL(p,0,0); /* Ensure any padding is null. */
1343 len = PTR_DIFF(p, pdata);
1344 len = (len + 3) & ~3;
1349 case SMB_FIND_FILE_DIRECTORY_INFO:
1350 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1352 SIVAL(p,0,reskey); p += 4;
1353 put_long_date(p,cdate); p += 8;
1354 put_long_date(p,adate); p += 8;
1355 put_long_date(p,mdate); p += 8;
1356 put_long_date(p,mdate); p += 8;
1357 SOFF_T(p,0,file_size); p += 8;
1358 SOFF_T(p,0,allocation_size); p += 8;
1359 SIVAL(p,0,nt_extmode); p += 4;
1360 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1363 SIVAL(p,0,0); /* Ensure any padding is null. */
1364 len = PTR_DIFF(p, pdata);
1365 len = (len + 3) & ~3;
1370 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1371 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1373 SIVAL(p,0,reskey); p += 4;
1374 put_long_date(p,cdate); p += 8;
1375 put_long_date(p,adate); p += 8;
1376 put_long_date(p,mdate); p += 8;
1377 put_long_date(p,mdate); p += 8;
1378 SOFF_T(p,0,file_size); p += 8;
1379 SOFF_T(p,0,allocation_size); p += 8;
1380 SIVAL(p,0,nt_extmode); p += 4;
1381 q = p; p += 4; /* q is placeholder for name length. */
1383 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1384 SIVAL(p,0,ea_size); /* Extended attributes */
1387 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1391 SIVAL(p,0,0); /* Ensure any padding is null. */
1392 len = PTR_DIFF(p, pdata);
1393 len = (len + 3) & ~3;
1398 case SMB_FIND_FILE_NAMES_INFO:
1399 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1401 SIVAL(p,0,reskey); p += 4;
1403 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1404 acl on a dir (tridge) */
1405 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1408 SIVAL(p,0,0); /* Ensure any padding is null. */
1409 len = PTR_DIFF(p, pdata);
1410 len = (len + 3) & ~3;
1415 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1416 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1418 SIVAL(p,0,reskey); p += 4;
1419 put_long_date(p,cdate); p += 8;
1420 put_long_date(p,adate); p += 8;
1421 put_long_date(p,mdate); p += 8;
1422 put_long_date(p,mdate); p += 8;
1423 SOFF_T(p,0,file_size); p += 8;
1424 SOFF_T(p,0,allocation_size); p += 8;
1425 SIVAL(p,0,nt_extmode); p += 4;
1426 q = p; p += 4; /* q is placeholder for name length. */
1428 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1429 SIVAL(p,0,ea_size); /* Extended attributes */
1432 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1433 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1434 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1435 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1438 SIVAL(p,0,0); /* Ensure any padding is null. */
1439 len = PTR_DIFF(p, pdata);
1440 len = (len + 3) & ~3;
1445 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1446 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1447 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1449 SIVAL(p,0,reskey); p += 4;
1450 put_long_date(p,cdate); p += 8;
1451 put_long_date(p,adate); p += 8;
1452 put_long_date(p,mdate); p += 8;
1453 put_long_date(p,mdate); p += 8;
1454 SOFF_T(p,0,file_size); p += 8;
1455 SOFF_T(p,0,allocation_size); p += 8;
1456 SIVAL(p,0,nt_extmode); p += 4;
1457 q = p; p += 4; /* q is placeholder for name length */
1459 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1460 SIVAL(p,0,ea_size); /* Extended attributes */
1463 /* Clear the short name buffer. This is
1464 * IMPORTANT as not doing so will trigger
1465 * a Win2k client bug. JRA.
1467 if (!was_8_3 && check_mangled_names) {
1468 pstring mangled_name;
1469 pstrcpy(mangled_name, fname);
1470 mangle_map(mangled_name,True,True,SNUM(conn));
1471 mangled_name[12] = 0;
1472 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1475 memset(p + 2 + len,'\0',24 - len);
1482 SSVAL(p,0,0); p += 2; /* Reserved ? */
1483 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1484 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1485 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1488 SIVAL(p,0,0); /* Ensure any padding is null. */
1489 len = PTR_DIFF(p, pdata);
1490 len = (len + 3) & ~3;
1495 /* CIFS UNIX Extension. */
1497 case SMB_FIND_FILE_UNIX:
1498 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1500 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1502 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1503 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1506 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1509 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1510 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1511 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1514 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1518 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1522 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1525 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1529 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1533 SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1536 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1540 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1544 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1546 SIVAL(p,0,0); /* Ensure any padding is null. */
1548 len = PTR_DIFF(p, pdata);
1549 len = (len + 3) & ~3;
1550 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1552 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1561 if (PTR_DIFF(p,pdata) > space_remaining) {
1562 /* Move the dirptr back to prev_dirpos */
1563 dptr_SeekDir(conn->dirptr, prev_dirpos);
1564 *out_of_space = True;
1565 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1566 return False; /* Not finished - just out of space */
1569 /* Setup the last entry pointer, as an offset from base_data */
1570 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1571 /* Advance the data pointer to the next slot */
1577 /****************************************************************************
1578 Reply to a TRANS2_FINDFIRST.
1579 ****************************************************************************/
1581 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1582 char **pparams, int total_params, char **ppdata, int total_data,
1583 unsigned int max_data_bytes)
1585 /* We must be careful here that we don't return more than the
1586 allowed number of data bytes. If this means returning fewer than
1587 maxentries then so be it. We assume that the redirector has
1588 enough room for the fixed number of parameter bytes it has
1590 char *params = *pparams;
1591 char *pdata = *ppdata;
1592 uint32 dirtype = SVAL(params,0);
1593 int maxentries = SVAL(params,2);
1594 uint16 findfirst_flags = SVAL(params,4);
1595 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1596 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1597 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1598 int info_level = SVAL(params,6);
1602 int last_entry_off=0;
1606 BOOL finished = False;
1607 BOOL dont_descend = False;
1608 BOOL out_of_space = False;
1609 int space_remaining;
1610 BOOL bad_path = False;
1611 BOOL mask_contains_wcard = False;
1612 SMB_STRUCT_STAT sbuf;
1613 TALLOC_CTX *ea_ctx = NULL;
1614 struct ea_list *ea_list = NULL;
1615 NTSTATUS ntstatus = NT_STATUS_OK;
1617 if (total_params < 12) {
1618 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1621 *directory = *mask = 0;
1623 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1624 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1625 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1626 info_level, max_data_bytes));
1629 /* W2K3 seems to treat zero as 1. */
1633 switch (info_level) {
1634 case SMB_FIND_INFO_STANDARD:
1635 case SMB_FIND_EA_SIZE:
1636 case SMB_FIND_EA_LIST:
1637 case SMB_FIND_FILE_DIRECTORY_INFO:
1638 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1639 case SMB_FIND_FILE_NAMES_INFO:
1640 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1641 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1642 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1644 case SMB_FIND_FILE_UNIX:
1645 if (!lp_unix_extensions())
1646 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1649 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1652 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1653 if (!NT_STATUS_IS_OK(ntstatus)) {
1654 return ERROR_NT(ntstatus);
1657 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1659 unix_convert(directory,conn,0,&bad_path,&sbuf);
1661 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1663 if(!check_name(directory,conn)) {
1664 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1667 p = strrchr_m(directory,'/');
1669 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1670 if((directory[0] == '.') && (directory[1] == '\0')) {
1672 mask_contains_wcard = True;
1674 pstrcpy(mask,directory);
1676 pstrcpy(directory,"./");
1682 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1684 if (info_level == SMB_FIND_EA_LIST) {
1687 if (total_data < 4) {
1688 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1691 ea_size = IVAL(pdata,0);
1692 if (ea_size != total_data) {
1693 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1694 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1695 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1698 if (!lp_ea_support(SNUM(conn))) {
1699 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1702 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1703 return ERROR_NT(NT_STATUS_NO_MEMORY);
1706 /* Pull out the list of names. */
1707 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1709 talloc_destroy(ea_ctx);
1710 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1714 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1715 if( pdata == NULL ) {
1716 talloc_destroy(ea_ctx);
1717 return ERROR_NT(NT_STATUS_NO_MEMORY);
1722 /* Realloc the params space */
1723 params = SMB_REALLOC(*pparams, 10);
1724 if (params == NULL) {
1725 talloc_destroy(ea_ctx);
1726 return ERROR_NT(NT_STATUS_NO_MEMORY);
1730 /* Save the wildcard match and attribs we are using on this directory -
1731 needed as lanman2 assumes these are being saved between calls */
1733 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1735 talloc_destroy(ea_ctx);
1736 return(UNIXERROR(ERRDOS,ERRbadfile));
1739 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1741 /* We don't need to check for VOL here as this is returned by
1742 a different TRANS2 call. */
1744 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1745 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1746 dont_descend = True;
1749 space_remaining = max_data_bytes;
1750 out_of_space = False;
1752 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1753 BOOL got_exact_match = False;
1755 /* this is a heuristic to avoid seeking the dirptr except when
1756 absolutely necessary. It allows for a filename of about 40 chars */
1757 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1758 out_of_space = True;
1761 finished = !get_lanman2_dir_entry(conn,
1763 mask,dirtype,info_level,
1764 requires_resume_key,dont_descend,
1765 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1766 &last_entry_off, ea_list, ea_ctx);
1769 if (finished && out_of_space)
1772 if (!finished && !out_of_space)
1776 * As an optimisation if we know we aren't looking
1777 * for a wildcard name (ie. the name matches the wildcard exactly)
1778 * then we can finish on any (first) match.
1779 * This speeds up large directory searches. JRA.
1785 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1788 talloc_destroy(ea_ctx);
1790 /* Check if we can close the dirptr */
1791 if(close_after_first || (finished && close_if_end)) {
1792 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1793 dptr_close(&dptr_num);
1797 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1798 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1799 * the protocol level is less than NT1. Tested with smbclient. JRA.
1800 * This should fix the OS/2 client bug #2335.
1803 if(numentries == 0) {
1804 dptr_close(&dptr_num);
1805 if (Protocol < PROTOCOL_NT1) {
1806 return ERROR_DOS(ERRDOS,ERRnofiles);
1808 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1812 /* At this point pdata points to numentries directory entries. */
1814 /* Set up the return parameter block */
1815 SSVAL(params,0,dptr_num);
1816 SSVAL(params,2,numentries);
1817 SSVAL(params,4,finished);
1818 SSVAL(params,6,0); /* Never an EA error */
1819 SSVAL(params,8,last_entry_off);
1821 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1823 if ((! *directory) && dptr_path(dptr_num))
1824 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1826 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1827 smb_fn_name(CVAL(inbuf,smb_com)),
1828 mask, directory, dirtype, numentries ) );
1831 * Force a name mangle here to ensure that the
1832 * mask as an 8.3 name is top of the mangled cache.
1833 * The reasons for this are subtle. Don't remove
1834 * this code unless you know what you are doing
1835 * (see PR#13758). JRA.
1838 if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn)))
1839 mangle_map(mask, True, True, SNUM(conn));
1844 /****************************************************************************
1845 Reply to a TRANS2_FINDNEXT.
1846 ****************************************************************************/
1848 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1849 char **pparams, int total_params, char **ppdata, int total_data,
1850 unsigned int max_data_bytes)
1852 /* We must be careful here that we don't return more than the
1853 allowed number of data bytes. If this means returning fewer than
1854 maxentries then so be it. We assume that the redirector has
1855 enough room for the fixed number of parameter bytes it has
1857 char *params = *pparams;
1858 char *pdata = *ppdata;
1859 int dptr_num = SVAL(params,0);
1860 int maxentries = SVAL(params,2);
1861 uint16 info_level = SVAL(params,4);
1862 uint32 resume_key = IVAL(params,6);
1863 uint16 findnext_flags = SVAL(params,10);
1864 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1865 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1866 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1867 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1868 BOOL mask_contains_wcard = False;
1869 pstring resume_name;
1875 int i, last_entry_off=0;
1876 BOOL finished = False;
1877 BOOL dont_descend = False;
1878 BOOL out_of_space = False;
1879 int space_remaining;
1880 TALLOC_CTX *ea_ctx = NULL;
1881 struct ea_list *ea_list = NULL;
1882 NTSTATUS ntstatus = NT_STATUS_OK;
1884 if (total_params < 12) {
1885 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1888 *mask = *directory = *resume_name = 0;
1890 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1891 if (!NT_STATUS_IS_OK(ntstatus)) {
1892 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1893 complain (it thinks we're asking for the directory above the shared
1894 path or an invalid name). Catch this as the resume name is only compared, never used in
1895 a file access. JRA. */
1896 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1897 pstrcpy(resume_name, "..");
1898 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1899 pstrcpy(resume_name, ".");
1901 return ERROR_NT(ntstatus);
1905 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1906 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1907 resume_key = %d resume name = %s continue=%d level = %d\n",
1908 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1909 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1912 /* W2K3 seems to treat zero as 1. */
1916 switch (info_level) {
1917 case SMB_FIND_INFO_STANDARD:
1918 case SMB_FIND_EA_SIZE:
1919 case SMB_FIND_EA_LIST:
1920 case SMB_FIND_FILE_DIRECTORY_INFO:
1921 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1922 case SMB_FIND_FILE_NAMES_INFO:
1923 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1924 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1925 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1927 case SMB_FIND_FILE_UNIX:
1928 if (!lp_unix_extensions())
1929 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1932 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1935 if (info_level == SMB_FIND_EA_LIST) {
1938 if (total_data < 4) {
1939 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1942 ea_size = IVAL(pdata,0);
1943 if (ea_size != total_data) {
1944 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1945 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1946 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1949 if (!lp_ea_support(SNUM(conn))) {
1950 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1953 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1954 return ERROR_NT(NT_STATUS_NO_MEMORY);
1957 /* Pull out the list of names. */
1958 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1960 talloc_destroy(ea_ctx);
1961 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1965 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1967 talloc_destroy(ea_ctx);
1968 return ERROR_NT(NT_STATUS_NO_MEMORY);
1973 /* Realloc the params space */
1974 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1975 if( params == NULL ) {
1976 talloc_destroy(ea_ctx);
1977 return ERROR_NT(NT_STATUS_NO_MEMORY);
1982 /* Check that the dptr is valid */
1983 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
1984 talloc_destroy(ea_ctx);
1985 return ERROR_DOS(ERRDOS,ERRnofiles);
1988 string_set(&conn->dirpath,dptr_path(dptr_num));
1990 /* Get the wildcard mask from the dptr */
1991 if((p = dptr_wcard(dptr_num))== NULL) {
1992 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1993 talloc_destroy(ea_ctx);
1994 return ERROR_DOS(ERRDOS,ERRnofiles);
1998 pstrcpy(directory,conn->dirpath);
2000 /* Get the attr mask from the dptr */
2001 dirtype = dptr_attr(dptr_num);
2003 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2004 dptr_num, mask, dirtype,
2006 dptr_TellDir(conn->dirptr)));
2008 /* We don't need to check for VOL here as this is returned by
2009 a different TRANS2 call. */
2011 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2012 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2013 dont_descend = True;
2016 space_remaining = max_data_bytes;
2017 out_of_space = False;
2020 * Seek to the correct position. We no longer use the resume key but
2021 * depend on the last file name instead.
2024 if(*resume_name && !continue_bit) {
2027 long current_pos = 0;
2029 * Remember, mangle_map is called by
2030 * get_lanman2_dir_entry(), so the resume name
2031 * could be mangled. Ensure we check the unmangled name.
2034 if (mangle_is_mangled(resume_name, SNUM(conn))) {
2035 mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn));
2039 * Fix for NT redirector problem triggered by resume key indexes
2040 * changing between directory scans. We now return a resume key of 0
2041 * and instead look for the filename to continue from (also given
2042 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2043 * findfirst/findnext (as is usual) then the directory pointer
2044 * should already be at the correct place.
2047 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2048 } /* end if resume_name && !continue_bit */
2050 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2051 BOOL got_exact_match = False;
2053 /* this is a heuristic to avoid seeking the dirptr except when
2054 absolutely necessary. It allows for a filename of about 40 chars */
2055 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2056 out_of_space = True;
2059 finished = !get_lanman2_dir_entry(conn,
2061 mask,dirtype,info_level,
2062 requires_resume_key,dont_descend,
2063 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2064 &last_entry_off, ea_list, ea_ctx);
2067 if (finished && out_of_space)
2070 if (!finished && !out_of_space)
2074 * As an optimisation if we know we aren't looking
2075 * for a wildcard name (ie. the name matches the wildcard exactly)
2076 * then we can finish on any (first) match.
2077 * This speeds up large directory searches. JRA.
2083 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2086 talloc_destroy(ea_ctx);
2088 /* Check if we can close the dirptr */
2089 if(close_after_request || (finished && close_if_end)) {
2090 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2091 dptr_close(&dptr_num); /* This frees up the saved mask */
2094 /* Set up the return parameter block */
2095 SSVAL(params,0,numentries);
2096 SSVAL(params,2,finished);
2097 SSVAL(params,4,0); /* Never an EA error */
2098 SSVAL(params,6,last_entry_off);
2100 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2102 if ((! *directory) && dptr_path(dptr_num))
2103 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2105 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2106 smb_fn_name(CVAL(inbuf,smb_com)),
2107 mask, directory, dirtype, numentries ) );
2112 /****************************************************************************
2113 Reply to a TRANS2_QFSINFO (query filesystem info).
2114 ****************************************************************************/
2116 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2117 char **pparams, int total_params, char **ppdata, int total_data,
2118 unsigned int max_data_bytes)
2120 char *pdata = *ppdata;
2121 char *params = *pparams;
2122 uint16 info_level = SVAL(params,0);
2125 char *vname = volume_label(SNUM(conn));
2126 int snum = SNUM(conn);
2127 char *fstype = lp_fstype(SNUM(conn));
2130 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2132 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2133 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2134 return ERROR_DOS(ERRSRV,ERRinvdevice);
2137 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2138 if ( pdata == NULL ) {
2139 return ERROR_NT(NT_STATUS_NO_MEMORY);
2143 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2145 switch (info_level) {
2146 case SMB_INFO_ALLOCATION:
2148 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2150 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2151 return(UNIXERROR(ERRHRD,ERRgeneral));
2154 block_size = lp_block_size(snum);
2155 if (bsize < block_size) {
2156 SMB_BIG_UINT factor = block_size/bsize;
2161 if (bsize > block_size) {
2162 SMB_BIG_UINT factor = bsize/block_size;
2167 bytes_per_sector = 512;
2168 sectors_per_unit = bsize/bytes_per_sector;
2170 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2171 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2172 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2174 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2175 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2176 SIVAL(pdata,l1_cUnit,dsize);
2177 SIVAL(pdata,l1_cUnitAvail,dfree);
2178 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2182 case SMB_INFO_VOLUME:
2183 /* Return volume name */
2185 * Add volume serial number - hash of a combination of
2186 * the called hostname and the service name.
2188 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2190 * Win2k3 and previous mess this up by sending a name length
2191 * one byte short. I believe only older clients (OS/2 Win9x) use
2192 * this call so try fixing this by adding a terminating null to
2193 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2195 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2196 SCVAL(pdata,l2_vol_cch,len);
2197 data_len = l2_vol_szVolLabel + len;
2198 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2199 (unsigned)st.st_ctime, len, vname));
2202 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2203 case SMB_FS_ATTRIBUTE_INFORMATION:
2206 #if defined(HAVE_SYS_QUOTAS)
2207 quota_flag = FILE_VOLUME_QUOTAS;
2210 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2211 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2212 quota_flag); /* FS ATTRIBUTES */
2214 SIVAL(pdata,4,255); /* Max filename component length */
2215 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2216 and will think we can't do long filenames */
2217 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2219 data_len = 12 + len;
2222 case SMB_QUERY_FS_LABEL_INFO:
2223 case SMB_FS_LABEL_INFORMATION:
2224 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2229 case SMB_QUERY_FS_VOLUME_INFO:
2230 case SMB_FS_VOLUME_INFORMATION:
2233 * Add volume serial number - hash of a combination of
2234 * the called hostname and the service name.
2236 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2237 (str_checksum(get_local_machine_name())<<16));
2239 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2240 SIVAL(pdata,12,len);
2242 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2243 (int)strlen(vname),vname, lp_servicename(snum)));
2246 case SMB_QUERY_FS_SIZE_INFO:
2247 case SMB_FS_SIZE_INFORMATION:
2249 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2251 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2252 return(UNIXERROR(ERRHRD,ERRgeneral));
2254 block_size = lp_block_size(snum);
2255 if (bsize < block_size) {
2256 SMB_BIG_UINT factor = block_size/bsize;
2261 if (bsize > block_size) {
2262 SMB_BIG_UINT factor = bsize/block_size;
2267 bytes_per_sector = 512;
2268 sectors_per_unit = bsize/bytes_per_sector;
2269 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2270 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2271 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2272 SBIG_UINT(pdata,0,dsize);
2273 SBIG_UINT(pdata,8,dfree);
2274 SIVAL(pdata,16,sectors_per_unit);
2275 SIVAL(pdata,20,bytes_per_sector);
2279 case SMB_FS_FULL_SIZE_INFORMATION:
2281 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2283 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2284 return(UNIXERROR(ERRHRD,ERRgeneral));
2286 block_size = lp_block_size(snum);
2287 if (bsize < block_size) {
2288 SMB_BIG_UINT factor = block_size/bsize;
2293 if (bsize > block_size) {
2294 SMB_BIG_UINT factor = bsize/block_size;
2299 bytes_per_sector = 512;
2300 sectors_per_unit = bsize/bytes_per_sector;
2301 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2302 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2303 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2304 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2305 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2306 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2307 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2308 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2312 case SMB_QUERY_FS_DEVICE_INFO:
2313 case SMB_FS_DEVICE_INFORMATION:
2315 SIVAL(pdata,0,0); /* dev type */
2316 SIVAL(pdata,4,0); /* characteristics */
2319 #ifdef HAVE_SYS_QUOTAS
2320 case SMB_FS_QUOTA_INFORMATION:
2322 * what we have to send --metze:
2324 * Unknown1: 24 NULL bytes
2325 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2326 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2327 * Quota Flags: 2 byte :
2328 * Unknown3: 6 NULL bytes
2332 * details for Quota Flags:
2334 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2335 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2336 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2337 * 0x0001 Enable Quotas: enable quota for this fs
2341 /* we need to fake up a fsp here,
2342 * because its not send in this call
2345 SMB_NTQUOTA_STRUCT quotas;
2348 ZERO_STRUCT(quotas);
2354 if (current_user.ut.uid != 0) {
2355 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2356 lp_servicename(SNUM(conn)),conn->user));
2357 return ERROR_DOS(ERRDOS,ERRnoaccess);
2360 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2361 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2362 return ERROR_DOS(ERRSRV,ERRerror);
2367 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2369 /* Unknown1 24 NULL bytes*/
2370 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2371 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2372 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2374 /* Default Soft Quota 8 bytes */
2375 SBIG_UINT(pdata,24,quotas.softlim);
2377 /* Default Hard Quota 8 bytes */
2378 SBIG_UINT(pdata,32,quotas.hardlim);
2380 /* Quota flag 2 bytes */
2381 SSVAL(pdata,40,quotas.qflags);
2383 /* Unknown3 6 NULL bytes */
2389 #endif /* HAVE_SYS_QUOTAS */
2390 case SMB_FS_OBJECTID_INFORMATION:
2395 * Query the version and capabilities of the CIFS UNIX extensions
2399 case SMB_QUERY_CIFS_UNIX_INFO:
2400 if (!lp_unix_extensions())
2401 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2403 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2404 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2405 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(CIFS_UNIX_POSIX_ACLS_CAP|
2406 CIFS_UNIX_POSIX_PATHNAMES_CAP))); /* We have POSIX ACLs and pathname capability. */
2409 case SMB_QUERY_POSIX_FS_INFO:
2412 vfs_statvfs_struct svfs;
2414 if (!lp_unix_extensions())
2415 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2417 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2421 SIVAL(pdata,0,svfs.OptimalTransferSize);
2422 SIVAL(pdata,4,svfs.BlockSize);
2423 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2424 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2425 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2426 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2427 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2428 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2429 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2431 } else if (rc == EOPNOTSUPP) {
2432 return ERROR_DOS(ERRDOS, ERRunknownlevel);
2433 #endif /* EOPNOTSUPP */
2435 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2436 return ERROR_DOS(ERRSRV,ERRerror);
2441 case SMB_MAC_QUERY_FS_INFO:
2443 * Thursby MAC extension... ONLY on NTFS filesystems
2444 * once we do streams then we don't need this
2446 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2448 SIVAL(pdata,84,0x100); /* Don't support mac... */
2453 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2457 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2459 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2464 /****************************************************************************
2465 Reply to a TRANS2_SETFSINFO (set filesystem info).
2466 ****************************************************************************/
2468 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2469 char **pparams, int total_params, char **ppdata, int total_data,
2470 unsigned int max_data_bytes)
2472 char *pdata = *ppdata;
2473 char *params = *pparams;
2477 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2480 if (total_params < 4) {
2481 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2483 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2486 info_level = SVAL(params,2);
2488 switch(info_level) {
2489 case SMB_SET_CIFS_UNIX_INFO:
2491 uint16 client_unix_major;
2492 uint16 client_unix_minor;
2493 uint32 client_unix_cap_low;
2494 uint32 client_unix_cap_high;
2496 if (!lp_unix_extensions()) {
2497 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2500 /* There should be 12 bytes of capabilities set. */
2501 if (total_data < 8) {
2502 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2504 client_unix_major = SVAL(pdata,0);
2505 client_unix_minor = SVAL(pdata,2);
2506 client_unix_cap_low = IVAL(pdata,4);
2507 client_unix_cap_high = IVAL(pdata,8);
2508 /* Just print these values for now. */
2509 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2510 cap_low = 0x%x, cap_high = 0x%x\n",
2511 (unsigned int)client_unix_major,
2512 (unsigned int)client_unix_minor,
2513 (unsigned int)client_unix_cap_low,
2514 (unsigned int)client_unix_cap_high ));
2516 /* Here is where we must switch to posix pathname processing... */
2517 lp_set_posix_pathnames();
2518 mangle_change_to_posix();
2521 case SMB_FS_QUOTA_INFORMATION:
2523 files_struct *fsp = NULL;
2524 SMB_NTQUOTA_STRUCT quotas;
2526 ZERO_STRUCT(quotas);
2529 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2530 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2531 lp_servicename(SNUM(conn)),conn->user));
2532 return ERROR_DOS(ERRSRV,ERRaccess);
2535 /* note: normaly there're 48 bytes,
2536 * but we didn't use the last 6 bytes for now
2539 fsp = file_fsp(params,0);
2540 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2541 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2542 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2545 if (total_data < 42) {
2546 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2548 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2551 /* unknown_1 24 NULL bytes in pdata*/
2553 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2554 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2555 #ifdef LARGE_SMB_OFF_T
2556 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2557 #else /* LARGE_SMB_OFF_T */
2558 if ((IVAL(pdata,28) != 0)&&
2559 ((quotas.softlim != 0xFFFFFFFF)||
2560 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2561 /* more than 32 bits? */
2562 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2564 #endif /* LARGE_SMB_OFF_T */
2566 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2567 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2568 #ifdef LARGE_SMB_OFF_T
2569 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2570 #else /* LARGE_SMB_OFF_T */
2571 if ((IVAL(pdata,36) != 0)&&
2572 ((quotas.hardlim != 0xFFFFFFFF)||
2573 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2574 /* more than 32 bits? */
2575 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2577 #endif /* LARGE_SMB_OFF_T */
2579 /* quota_flags 2 bytes **/
2580 quotas.qflags = SVAL(pdata,40);
2582 /* unknown_2 6 NULL bytes follow*/
2584 /* now set the quotas */
2585 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2586 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2587 return ERROR_DOS(ERRSRV,ERRerror);
2593 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2595 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2600 * sending this reply works fine,
2601 * but I'm not sure it's the same
2602 * like windows do...
2605 outsize = set_message(outbuf,10,0,True);
2610 /****************************************************************************
2611 Utility function to set bad path error.
2612 ****************************************************************************/
2614 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2616 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2617 err, (int)bad_path ));
2621 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2623 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2626 return UNIXERROR(def_class,def_code);
2629 #if defined(HAVE_POSIX_ACLS)
2630 /****************************************************************************
2631 Utility function to count the number of entries in a POSIX acl.
2632 ****************************************************************************/
2634 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2636 unsigned int ace_count = 0;
2637 int entry_id = SMB_ACL_FIRST_ENTRY;
2638 SMB_ACL_ENTRY_T entry;
2640 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2642 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2643 entry_id = SMB_ACL_NEXT_ENTRY;
2650 /****************************************************************************
2651 Utility function to marshall a POSIX acl into wire format.
2652 ****************************************************************************/
2654 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2656 int entry_id = SMB_ACL_FIRST_ENTRY;
2657 SMB_ACL_ENTRY_T entry;
2659 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2660 SMB_ACL_TAG_T tagtype;
2661 SMB_ACL_PERMSET_T permset;
2662 unsigned char perms = 0;
2663 unsigned int own_grp;
2666 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2667 entry_id = SMB_ACL_NEXT_ENTRY;
2670 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2671 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2675 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2676 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2680 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2681 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2682 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2684 SCVAL(pdata,1,perms);
2687 case SMB_ACL_USER_OBJ:
2688 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2689 own_grp = (unsigned int)pst->st_uid;
2690 SIVAL(pdata,2,own_grp);
2695 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2697 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2699 own_grp = (unsigned int)*puid;
2700 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2701 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2702 SIVAL(pdata,2,own_grp);
2706 case SMB_ACL_GROUP_OBJ:
2707 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2708 own_grp = (unsigned int)pst->st_gid;
2709 SIVAL(pdata,2,own_grp);
2714 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2716 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2718 own_grp = (unsigned int)*pgid;
2719 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2720 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2721 SIVAL(pdata,2,own_grp);
2726 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2727 SIVAL(pdata,2,0xFFFFFFFF);
2728 SIVAL(pdata,6,0xFFFFFFFF);
2731 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2732 SIVAL(pdata,2,0xFFFFFFFF);
2733 SIVAL(pdata,6,0xFFFFFFFF);
2736 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2739 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2746 /****************************************************************************
2747 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2748 file name or file id).
2749 ****************************************************************************/
2751 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2752 unsigned int tran_call,
2753 char **pparams, int total_params, char **ppdata, int total_data,
2754 unsigned int max_data_bytes)
2756 char *params = *pparams;
2757 char *pdata = *ppdata;
2761 SMB_OFF_T file_size=0;
2762 SMB_BIG_UINT allocation_size=0;
2763 unsigned int data_size = 0;
2764 unsigned int param_size = 2;
2765 SMB_STRUCT_STAT sbuf;
2766 pstring fname, dos_fname;
2771 BOOL bad_path = False;
2772 BOOL delete_pending = False;
2775 files_struct *fsp = NULL;
2776 TALLOC_CTX *ea_ctx = NULL;
2777 struct ea_list *ea_list = NULL;
2778 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2781 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2785 if (tran_call == TRANSACT2_QFILEINFO) {
2786 if (total_params < 4) {
2787 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2790 fsp = file_fsp(params,0);
2791 info_level = SVAL(params,2);
2793 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2795 if(fsp && (fsp->fake_file_handle)) {
2797 * This is actually for the QUOTA_FAKE_FILE --metze
2800 pstrcpy(fname, fsp->fsp_name);
2801 /* We know this name is ok, it's already passed the checks. */
2803 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2805 * This is actually a QFILEINFO on a directory
2806 * handle (returned from an NT SMB). NT5.0 seems
2807 * to do this call. JRA.
2809 /* We know this name is ok, it's already passed the checks. */
2810 pstrcpy(fname, fsp->fsp_name);
2812 if (INFO_LEVEL_IS_UNIX(info_level)) {
2813 /* Always do lstat for UNIX calls. */
2814 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2815 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2816 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2818 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2819 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2820 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2823 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2826 * Original code - this is an open file.
2828 CHECK_FSP(fsp,conn);
2830 pstrcpy(fname, fsp->fsp_name);
2831 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2832 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2833 return(UNIXERROR(ERRDOS,ERRbadfid));
2835 pos = fsp->fh->position_information;
2836 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2837 access_mask = fsp->access_mask;
2840 NTSTATUS status = NT_STATUS_OK;
2843 if (total_params < 6) {
2844 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2847 info_level = SVAL(params,0);
2849 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2851 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
2852 if (!NT_STATUS_IS_OK(status)) {
2853 return ERROR_NT(status);
2856 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2858 unix_convert(fname,conn,0,&bad_path,&sbuf);
2860 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2862 if (!check_name(fname,conn)) {
2863 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2864 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2867 if (INFO_LEVEL_IS_UNIX(info_level)) {
2868 /* Always do lstat for UNIX calls. */
2869 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2870 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2871 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2873 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2874 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2875 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2878 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2879 if (delete_pending) {
2880 return ERROR_NT(NT_STATUS_DELETE_PENDING);
2884 nlink = sbuf.st_nlink;
2886 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2887 /* NTFS does not seem to count ".." */
2891 if ((nlink > 0) && delete_pending) {
2895 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2896 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2898 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2899 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2901 p = strrchr_m(fname,'/');
2907 mode = dos_mode(conn,fname,&sbuf);
2909 mode = FILE_ATTRIBUTE_NORMAL;
2911 fullpathname = fname;
2913 file_size = get_file_size(sbuf);
2915 /* Pull any EA list from the data portion. */
2916 if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2919 if (total_data < 4) {
2920 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2922 ea_size = IVAL(pdata,0);
2924 if (total_data > 0 && ea_size != total_data) {
2925 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2926 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2927 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2930 if (!lp_ea_support(SNUM(conn))) {
2931 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2934 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2935 return ERROR_NT(NT_STATUS_NO_MEMORY);
2938 /* Pull out the list of names. */
2939 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2941 talloc_destroy(ea_ctx);
2942 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2946 params = SMB_REALLOC(*pparams,2);
2947 if (params == NULL) {
2948 talloc_destroy(ea_ctx);
2949 return ERROR_NT(NT_STATUS_NO_MEMORY);
2953 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2954 pdata = SMB_REALLOC(*ppdata, data_size);
2955 if ( pdata == NULL ) {
2956 talloc_destroy(ea_ctx);
2957 return ERROR_NT(NT_STATUS_NO_MEMORY);
2961 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2963 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2966 if (fsp->pending_modtime) {
2967 /* the pending modtime overrides the current modtime */
2968 sbuf.st_mtime = fsp->pending_modtime;
2971 /* Do we have this path open ? */
2972 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2973 if (fsp1 && fsp1->pending_modtime) {
2974 /* the pending modtime overrides the current modtime */
2975 sbuf.st_mtime = fsp1->pending_modtime;
2977 if (fsp1 && fsp1->initial_allocation_size) {
2978 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
2982 if (lp_dos_filetime_resolution(SNUM(conn))) {
2984 sbuf.st_atime &= ~1;
2985 sbuf.st_ctime &= ~1;
2986 sbuf.st_mtime &= ~1;
2989 /* NT expects the name to be in an exact form of the *full*
2990 filename. See the trans2 torture test */
2991 if (strequal(base_name,".")) {
2992 pstrcpy(dos_fname, "\\");
2994 pstr_sprintf(dos_fname, "\\%s", fname);
2995 string_replace(dos_fname, '/', '\\');
2998 switch (info_level) {
2999 case SMB_INFO_STANDARD:
3000 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3002 srv_put_dos_date2(pdata,l1_fdateCreation,c_time);
3003 srv_put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
3004 srv_put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
3005 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3006 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3007 SSVAL(pdata,l1_attrFile,mode);
3010 case SMB_INFO_QUERY_EA_SIZE:
3012 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3013 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3015 srv_put_dos_date2(pdata,0,c_time);
3016 srv_put_dos_date2(pdata,4,sbuf.st_atime);
3017 srv_put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */
3018 SIVAL(pdata,12,(uint32)file_size);
3019 SIVAL(pdata,16,(uint32)allocation_size);
3020 SSVAL(pdata,20,mode);
3021 SIVAL(pdata,22,ea_size);
3025 case SMB_INFO_IS_NAME_VALID:
3026 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3027 if (tran_call == TRANSACT2_QFILEINFO) {
3028 /* os/2 needs this ? really ?*/
3029 return ERROR_DOS(ERRDOS,ERRbadfunc);
3035 case SMB_INFO_QUERY_EAS_FROM_LIST:
3037 size_t total_ea_len = 0;
3038 struct ea_list *ea_file_list = NULL;
3040 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3042 ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3043 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3045 if (!ea_list || (total_ea_len > data_size)) {
3046 talloc_destroy(ea_ctx);
3048 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3052 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3053 talloc_destroy(ea_ctx);
3057 case SMB_INFO_QUERY_ALL_EAS:
3059 /* We have data_size bytes to put EA's into. */
3060 size_t total_ea_len = 0;
3062 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3064 ea_ctx = talloc_init("ea_ctx");
3066 return ERROR_NT(NT_STATUS_NO_MEMORY);
3069 ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3070 if (!ea_list || (total_ea_len > data_size)) {
3071 talloc_destroy(ea_ctx);
3073 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3077 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3078 talloc_destroy(ea_ctx);
3082 case SMB_FILE_BASIC_INFORMATION:
3083 case SMB_QUERY_FILE_BASIC_INFO:
3085 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3086 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3087 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3089 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3093 put_long_date(pdata,c_time);
3094 put_long_date(pdata+8,sbuf.st_atime);
3095 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3096 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3097 SIVAL(pdata,32,mode);
3099 DEBUG(5,("SMB_QFBI - "));
3101 time_t create_time = c_time;
3102 DEBUG(5,("create: %s ", ctime(&create_time)));
3104 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3105 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3106 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3107 DEBUG(5,("mode: %x\n", mode));
3110 case SMB_FILE_STANDARD_INFORMATION:
3111 case SMB_QUERY_FILE_STANDARD_INFO:
3113 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3115 SOFF_T(pdata,0,allocation_size);
3116 SOFF_T(pdata,8,file_size);
3117 SIVAL(pdata,16,nlink);
3118 SCVAL(pdata,20,delete_pending?1:0);
3119 SCVAL(pdata,21,(mode&aDIR)?1:0);
3120 SSVAL(pdata,22,0); /* Padding. */
3123 case SMB_FILE_EA_INFORMATION:
3124 case SMB_QUERY_FILE_EA_INFO:
3126 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3127 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3129 SIVAL(pdata,0,ea_size);
3133 /* Get the 8.3 name - used if NT SMB was negotiated. */
3134 case SMB_QUERY_FILE_ALT_NAME_INFO:
3135 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3139 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3140 pstrcpy(short_name,base_name);
3141 /* Mangle if not already 8.3 */
3142 if(!mangle_is_8_3(short_name, True, SNUM(conn))) {
3143 mangle_map(short_name,True,True,SNUM(conn));
3145 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3146 data_size = 4 + len;
3151 case SMB_QUERY_FILE_NAME_INFO:
3153 this must be *exactly* right for ACLs on mapped drives to work
3155 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3156 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3157 data_size = 4 + len;
3161 case SMB_FILE_ALLOCATION_INFORMATION:
3162 case SMB_QUERY_FILE_ALLOCATION_INFO:
3163 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3165 SOFF_T(pdata,0,allocation_size);
3168 case SMB_FILE_END_OF_FILE_INFORMATION:
3169 case SMB_QUERY_FILE_END_OF_FILEINFO:
3170 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3172 SOFF_T(pdata,0,file_size);
3175 case SMB_QUERY_FILE_ALL_INFO:
3176 case SMB_FILE_ALL_INFORMATION:
3178 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3179 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3180 put_long_date(pdata,c_time);
3181 put_long_date(pdata+8,sbuf.st_atime);
3182 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3183 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3184 SIVAL(pdata,32,mode);
3185 SIVAL(pdata,36,0); /* padding. */
3187 SOFF_T(pdata,0,allocation_size);
3188 SOFF_T(pdata,8,file_size);
3189 SIVAL(pdata,16,nlink);
3190 SCVAL(pdata,20,delete_pending);
3191 SCVAL(pdata,21,(mode&aDIR)?1:0);
3194 SIVAL(pdata,0,ea_size);
3195 pdata += 4; /* EA info */
3196 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3199 data_size = PTR_DIFF(pdata,(*ppdata));
3202 case SMB_FILE_INTERNAL_INFORMATION:
3203 /* This should be an index number - looks like
3206 I think this causes us to fail the IFSKIT
3207 BasicFileInformationTest. -tpot */
3209 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3210 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3211 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3215 case SMB_FILE_ACCESS_INFORMATION:
3216 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3217 SIVAL(pdata,0,access_mask);
3221 case SMB_FILE_NAME_INFORMATION:
3222 /* Pathname with leading '\'. */
3225 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
3226 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3227 SIVAL(pdata,0,byte_len);
3228 data_size = 4 + byte_len;
3232 case SMB_FILE_DISPOSITION_INFORMATION:
3233 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3235 SCVAL(pdata,0,delete_pending);
3238 case SMB_FILE_POSITION_INFORMATION:
3239 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3241 SOFF_T(pdata,0,pos);
3244 case SMB_FILE_MODE_INFORMATION:
3245 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3246 SIVAL(pdata,0,mode);
3250 case SMB_FILE_ALIGNMENT_INFORMATION:
3251 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3252 SIVAL(pdata,0,0); /* No alignment needed. */
3258 * NT4 server just returns "invalid query" to this - if we try to answer
3259 * it then NTws gets a BSOD! (tridge).
3260 * W2K seems to want this. JRA.
3262 case SMB_QUERY_FILE_STREAM_INFO:
3264 case SMB_FILE_STREAM_INFORMATION:
3265 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3269 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
3270 SIVAL(pdata,0,0); /* ??? */
3271 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3272 SOFF_T(pdata,8,file_size);
3273 SIVAL(pdata,16,allocation_size);
3274 SIVAL(pdata,20,0); /* ??? */
3275 data_size = 24 + byte_len;
3279 case SMB_QUERY_COMPRESSION_INFO:
3280 case SMB_FILE_COMPRESSION_INFORMATION:
3281 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3282 SOFF_T(pdata,0,file_size);
3283 SIVAL(pdata,8,0); /* ??? */
3284 SIVAL(pdata,12,0); /* ??? */
3288 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3289 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3290 put_long_date(pdata,c_time);
3291 put_long_date(pdata+8,sbuf.st_atime);
3292 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3293 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3294 SIVAL(pdata,32,allocation_size);
3295 SOFF_T(pdata,40,file_size);
3296 SIVAL(pdata,48,mode);
3297 SIVAL(pdata,52,0); /* ??? */
3301 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3302 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3303 SIVAL(pdata,0,mode);
3309 * CIFS UNIX Extensions.
3312 case SMB_QUERY_FILE_UNIX_BASIC:
3314 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3315 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3317 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3320 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3323 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3324 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3325 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3328 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3332 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3336 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3339 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3343 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3347 SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3350 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3354 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3357 data_size = PTR_DIFF(pdata,(*ppdata));
3361 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3363 for (i=0; i<100; i++)
3364 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3370 case SMB_QUERY_FILE_UNIX_LINK:
3374 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3376 if(!S_ISLNK(sbuf.st_mode))
3377 return(UNIXERROR(ERRSRV,ERRbadlink));
3379 return(UNIXERROR(ERRDOS,ERRbadlink));
3381 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3383 return(UNIXERROR(ERRDOS,ERRnoaccess));
3385 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3387 data_size = PTR_DIFF(pdata,(*ppdata));
3392 #if defined(HAVE_POSIX_ACLS)
3393 case SMB_QUERY_POSIX_ACL:
3395 SMB_ACL_T file_acl = NULL;
3396 SMB_ACL_T def_acl = NULL;
3397 uint16 num_file_acls = 0;
3398 uint16 num_def_acls = 0;
3400 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3401 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3403 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3406 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3407 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3409 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3412 if (S_ISDIR(sbuf.st_mode)) {
3413 if (fsp && fsp->is_directory) {
3414 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3416 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3418 def_acl = free_empty_sys_acl(conn, def_acl);
3421 num_file_acls = count_acl_entries(conn, file_acl);
3422 num_def_acls = count_acl_entries(conn, def_acl);
3424 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3425 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3427 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3428 SMB_POSIX_ACL_HEADER_SIZE) ));
3430 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3433 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3435 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3438 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3439 SSVAL(pdata,2,num_file_acls);
3440 SSVAL(pdata,4,num_def_acls);
3441 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3443 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3446 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3448 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3450 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3452 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3455 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3457 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3461 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3464 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3466 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3472 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3475 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3480 /****************************************************************************
3481 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3483 ****************************************************************************/
3485 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3487 BOOL bad_path_oldname = False;
3488 BOOL bad_path_newname = False;
3489 SMB_STRUCT_STAT sbuf1, sbuf2;
3490 pstring last_component_oldname;
3491 pstring last_component_newname;
3492 NTSTATUS status = NT_STATUS_OK;
3498 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3499 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3502 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3503 if (bad_path_oldname) {
3504 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3507 /* Quick check for "." and ".." */
3508 if (last_component_oldname[0] == '.') {
3509 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3510 return NT_STATUS_OBJECT_NAME_INVALID;
3514 /* source must already exist. */
3515 if (!VALID_STAT(sbuf1)) {
3516 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3519 if (!check_name(oldname,conn)) {
3520 return NT_STATUS_ACCESS_DENIED;
3523 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3524 if (bad_path_newname) {
3525 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3528 /* Quick check for "." and ".." */
3529 if (last_component_newname[0] == '.') {
3530 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3531 return NT_STATUS_OBJECT_NAME_INVALID;
3535 /* Disallow if newname already exists. */
3536 if (VALID_STAT(sbuf2)) {
3537 return NT_STATUS_OBJECT_NAME_COLLISION;
3540 if (!check_name(newname,conn)) {
3541 return NT_STATUS_ACCESS_DENIED;
3544 /* No links from a directory. */
3545 if (S_ISDIR(sbuf1.st_mode)) {
3546 return NT_STATUS_FILE_IS_A_DIRECTORY;
3549 /* Ensure this is within the share. */
3550 if (!reduce_name(conn, oldname) != 0)
3551 return NT_STATUS_ACCESS_DENIED;
3553 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3555 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3556 status = map_nt_error_from_unix(errno);
3557 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3558 nt_errstr(status), newname, oldname));
3564 /****************************************************************************
3565 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3566 ****************************************************************************/
3568 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3569 unsigned int tran_call,
3570 char **pparams, int total_params, char **ppdata, int total_data,
3571 unsigned int max_data_bytes)
3573 char *params = *pparams;
3574 char *pdata = *ppdata;
3579 SMB_STRUCT_STAT sbuf;
3582 BOOL bad_path = False;
3583 files_struct *fsp = NULL;
3584 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3585 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3586 mode_t unixmode = 0;
3587 NTSTATUS status = NT_STATUS_OK;
3590 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3595 if (tran_call == TRANSACT2_SETFILEINFO) {
3596 if (total_params < 4) {
3597 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3600 fsp = file_fsp(params,0);
3601 info_level = SVAL(params,2);
3603 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3605 * This is actually a SETFILEINFO on a directory
3606 * handle (returned from an NT SMB). NT5.0 seems
3607 * to do this call. JRA.
3609 pstrcpy(fname, fsp->fsp_name);
3610 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3611 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3612 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3614 } else if (fsp && fsp->print_file) {
3616 * Doing a DELETE_ON_CLOSE should cancel a print job.
3618 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3619 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
3621 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3624 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3627 return (UNIXERROR(ERRDOS,ERRbadpath));
3630 * Original code - this is an open file.
3632 CHECK_FSP(fsp,conn);
3634 pstrcpy(fname, fsp->fsp_name);
3637 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3638 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3639 return(UNIXERROR(ERRDOS,ERRbadfid));
3644 if (total_params < 6) {
3645 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3648 info_level = SVAL(params,0);
3649 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
3650 if (!NT_STATUS_IS_OK(status)) {
3651 return ERROR_NT(status);
3653 unix_convert(fname,conn,0,&bad_path,&sbuf);
3655 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3659 * For CIFS UNIX extensions the target name may not exist.
3662 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3663 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3664 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3667 if(!check_name(fname, conn)) {
3668 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3673 if (!CAN_WRITE(conn))
3674 return ERROR_DOS(ERRSRV,ERRaccess);
3676 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3677 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3679 if (VALID_STAT(sbuf))
3680 unixmode = sbuf.st_mode;
3682 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3683 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3685 /* Realloc the parameter size */
3686 params = SMB_REALLOC(*pparams,2);
3687 if(params == NULL) {
3688 return ERROR_NT(NT_STATUS_NO_MEMORY);
3694 if (fsp && fsp->pending_modtime) {
3695 /* the pending modtime overrides the current modtime */
3696 sbuf.st_mtime = fsp->pending_modtime;
3699 size = get_file_size(sbuf);
3700 tvs.modtime = sbuf.st_mtime;
3701 tvs.actime = sbuf.st_atime;
3702 dosmode = dos_mode(conn,fname,&sbuf);
3703 unixmode = sbuf.st_mode;
3705 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3706 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3708 switch (info_level) {
3709 case SMB_INFO_STANDARD:
3711 if (total_data < 12) {
3712 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3716 tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
3718 tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
3722 case SMB_INFO_SET_EA:
3724 struct ea_list *ea_list = NULL;
3725 TALLOC_CTX *ctx = NULL;
3727 if (total_data < 10) {
3729 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3730 length. They seem to have no effect. Bug #3212. JRA */
3732 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3733 /* We're done. We only get EA info in this call. */
3735 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3739 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3742 if (IVAL(pdata,0) > total_data) {
3743 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3744 IVAL(pdata,0), (unsigned int)total_data));
3745 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3748 ctx = talloc_init("SMB_INFO_SET_EA");
3750 return ERROR_NT(NT_STATUS_NO_MEMORY);
3752 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3754 talloc_destroy(ctx);
3755 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3757 status = set_ea(conn, fsp, fname, ea_list);
3758 talloc_destroy(ctx);
3760 if (!NT_STATUS_IS_OK(status)) {
3761 return ERROR_NT(status);
3764 /* We're done. We only get EA info in this call. */
3766 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3771 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3772 /* XXXX um, i don't think this is right.
3773 it's also not in the cifs6.txt spec.
3775 case SMB_INFO_QUERY_EAS_FROM_LIST:
3776 if (total_data < 28)
3777 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3779 tvs.actime = make_unix_date2(pdata+8);
3780 tvs.modtime = make_unix_date2(pdata+12);
3781 size = IVAL(pdata,16);
3782 dosmode = IVAL(pdata,24);
3785 /* XXXX nor this. not in cifs6.txt, either. */
3786 case SMB_INFO_QUERY_ALL_EAS:
3787 if (total_data < 28)
3788 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3790 tvs.actime = make_unix_date2(pdata+8);
3791 tvs.modtime = make_unix_date2(pdata+12);
3792 size = IVAL(pdata,16);
3793 dosmode = IVAL(pdata,24);
3797 case SMB_SET_FILE_BASIC_INFO:
3798 case SMB_FILE_BASIC_INFORMATION:
3800 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3802 time_t changed_time;
3804 if (total_data < 36) {
3805 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3808 /* Ignore create time at offset pdata. */
3811 tvs.actime = interpret_long_date(pdata+8);
3813 write_time = interpret_long_date(pdata+16);
3814 changed_time = interpret_long_date(pdata+24);
3816 tvs.modtime = MIN(write_time, changed_time);
3818 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3819 tvs.modtime = write_time;
3821 /* Prefer a defined time to an undefined one. */
3822 if (null_mtime(tvs.modtime)) {
3823 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3827 dosmode = IVAL(pdata,32);
3831 case SMB_FILE_ALLOCATION_INFORMATION:
3832 case SMB_SET_FILE_ALLOCATION_INFO:
3835 SMB_BIG_UINT allocation_size;
3837 if (total_data < 8) {
3838 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3841 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3842 #ifdef LARGE_SMB_OFF_T
3843 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3844 #else /* LARGE_SMB_OFF_T */
3845 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3846 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3847 #endif /* LARGE_SMB_OFF_T */
3848 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3849 fname, (double)allocation_size ));
3851 if (allocation_size) {
3852 allocation_size = smb_roundup(conn, allocation_size);
3855 if(allocation_size != get_file_size(sbuf)) {
3856 SMB_STRUCT_STAT new_sbuf;
3858 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3859 fname, (double)allocation_size ));
3862 files_struct *new_fsp = NULL;
3864 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
3866 FILE_SHARE_READ|FILE_SHARE_WRITE,
3869 FILE_ATTRIBUTE_NORMAL,
3873 if (new_fsp == NULL) {
3874 return(UNIXERROR(ERRDOS,ERRbadpath));
3876 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3877 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
3878 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3879 new_fsp->fnum, strerror(errno)));
3882 close_file(new_fsp,NORMAL_CLOSE);
3884 ret = vfs_allocate_file_space(fsp, allocation_size);
3885 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3886 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3887 fsp->fnum, strerror(errno)));
3892 return ERROR_NT(NT_STATUS_DISK_FULL);
3894 /* Allocate can truncate size... */
3895 size = get_file_size(new_sbuf);
3901 case SMB_FILE_END_OF_FILE_INFORMATION:
3902 case SMB_SET_FILE_END_OF_FILE_INFO:
3904 if (total_data < 8) {
3905 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3908 size = IVAL(pdata,0);
3909 #ifdef LARGE_SMB_OFF_T
3910 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3911 #else /* LARGE_SMB_OFF_T */
3912 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3913 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3914 #endif /* LARGE_SMB_OFF_T */
3915 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3919 case SMB_FILE_DISPOSITION_INFORMATION:
3920 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3922 BOOL delete_on_close;
3924 if (total_data < 1) {
3925 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3928 delete_on_close = (CVAL(pdata,0) ? True : False);
3930 /* Just ignore this set on a path. */
3931 if (tran_call != TRANSACT2_SETFILEINFO)
3935 return(UNIXERROR(ERRDOS,ERRbadfid));
3937 status = can_set_delete_on_close(fsp, delete_on_close,
3940 if (!NT_STATUS_IS_OK(status)) {
3941 return ERROR_NT(status);
3944 /* The set is across all open files on this dev/inode pair. */
3945 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
3946 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3950 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3954 case SMB_FILE_POSITION_INFORMATION:
3956 SMB_BIG_UINT position_information;
3958 if (total_data < 8) {
3959 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3962 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3963 #ifdef LARGE_SMB_OFF_T
3964 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3965 #else /* LARGE_SMB_OFF_T */
3966 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3967 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3968 #endif /* LARGE_SMB_OFF_T */
3969 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3970 fname, (double)position_information ));
3972 fsp->fh->position_information = position_information;
3975 /* We're done. We only get position info in this call. */
3977 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3981 /* From tridge Samba4 :
3982 * MODE_INFORMATION in setfileinfo (I have no
3983 * idea what "mode information" on a file is - it takes a value of 0,
3984 * 2, 4 or 6. What could it be?).
3987 case SMB_FILE_MODE_INFORMATION:
3991 if (total_data < 4) {
3992 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3994 mode = IVAL(pdata,0);
3995 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
3996 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3999 /* We're done. We only get mode info in this call. */
4001 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4006 * CIFS UNIX extensions.
4009 case SMB_SET_FILE_UNIX_BASIC:
4011 uint32 raw_unixmode;
4013 if (total_data < 100) {
4014 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4017 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4018 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4019 size=IVAL(pdata,0); /* first 8 Bytes are size */
4020 #ifdef LARGE_SMB_OFF_T
4021 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4022 #else /* LARGE_SMB_OFF_T */
4023 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
4024 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4025 #endif /* LARGE_SMB_OFF_T */
4027 pdata+=24; /* ctime & st_blocks are not changed */
4028 tvs.actime = interpret_long_date(pdata); /* access_time */
4029 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
4031 set_owner = (uid_t)IVAL(pdata,0);
4033 set_grp = (gid_t)IVAL(pdata,0);
4035 raw_unixmode = IVAL(pdata,28);
4036 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4037 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4039 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4040 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4041 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4043 if (!VALID_STAT(sbuf)) {
4046 * The only valid use of this is to create character and block
4047 * devices, and named pipes. This is deprecated (IMHO) and
4048 * a new info level should be used for mknod. JRA.
4051 uint32 file_type = IVAL(pdata,0);
4052 #if defined(HAVE_MAKEDEV)
4053 uint32 dev_major = IVAL(pdata,4);
4054 uint32 dev_minor = IVAL(pdata,12);
4057 uid_t myuid = geteuid();
4058 gid_t mygid = getegid();
4059 SMB_DEV_T dev = (SMB_DEV_T)0;
4061 if (tran_call == TRANSACT2_SETFILEINFO)
4062 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4064 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4065 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4068 #if defined(HAVE_MAKEDEV)
4069 dev = makedev(dev_major, dev_minor);
4072 /* We can only create as the owner/group we are. */
4074 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4075 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4076 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4077 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4079 switch (file_type) {
4080 #if defined(S_IFIFO)
4081 case UNIX_TYPE_FIFO:
4082 unixmode |= S_IFIFO;
4085 #if defined(S_IFSOCK)
4086 case UNIX_TYPE_SOCKET:
4087 unixmode |= S_IFSOCK;
4090 #if defined(S_IFCHR)
4091 case UNIX_TYPE_CHARDEV:
4092 unixmode |= S_IFCHR;
4095 #if defined(S_IFBLK)
4096 case UNIX_TYPE_BLKDEV:
4097 unixmode |= S_IFBLK;
4101 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4104 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4105 0%o for file %s\n", (double)dev, unixmode, fname ));
4107 /* Ok - do the mknod. */
4108 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4109 return(UNIXERROR(ERRDOS,ERRnoaccess));
4111 inherit_access_acl(conn, fname, unixmode);
4114 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4119 * Deal with the UNIX specific mode set.
4122 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4123 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4124 (unsigned int)unixmode, fname ));
4125 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4126 return(UNIXERROR(ERRDOS,ERRnoaccess));
4130 * Deal with the UNIX specific uid set.
4133 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4134 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4135 (unsigned int)set_owner, fname ));
4136 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4137 return(UNIXERROR(ERRDOS,ERRnoaccess));
4141 * Deal with the UNIX specific gid set.
4144 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4145 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4146 (unsigned int)set_owner, fname ));
4147 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4148 return(UNIXERROR(ERRDOS,ERRnoaccess));
4153 case SMB_SET_FILE_UNIX_LINK:
4155 pstring link_target;
4156 char *newname = fname;
4158 /* Set a symbolic link. */
4159 /* Don't allow this if follow links is false. */
4161 if (!lp_symlinks(SNUM(conn)))
4162 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4164 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4166 /* !widelinks forces the target path to be within the share. */
4167 /* This means we can interpret the target as a pathname. */
4168 if (!lp_widelinks(SNUM(conn))) {
4170 char *last_dirp = NULL;
4172 unix_format(link_target);
4173 if (*link_target == '/') {
4174 /* No absolute paths allowed. */
4175 return(UNIXERROR(ERRDOS,ERRnoaccess));
4177 pstrcpy(rel_name, newname);
4178 last_dirp = strrchr_m(rel_name, '/');
4180 last_dirp[1] = '\0';
4182 pstrcpy(rel_name, "./");
4184 pstrcat(rel_name, link_target);
4186 if (!check_name(rel_name, conn)) {
4187 return(UNIXERROR(ERRDOS,ERRnoaccess));
4191 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4192 fname, link_target ));
4194 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4195 return(UNIXERROR(ERRDOS,ERRnoaccess));
4197 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4201 case SMB_SET_FILE_UNIX_HLINK:
4204 char *newname = fname;
4206 /* Set a hard link. */
4207 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
4208 if (!NT_STATUS_IS_OK(status)) {
4209 return ERROR_NT(status);
4212 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4215 status = hardlink_internals(conn, oldname, newname);
4216 if (!NT_STATUS_IS_OK(status)) {
4217 return ERROR_NT(status);
4221 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4225 case SMB_FILE_RENAME_INFORMATION:
4234 if (total_data < 12) {
4235 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4238 overwrite = (CVAL(pdata,0) ? True : False);
4239 root_fid = IVAL(pdata,4);
4240 len = IVAL(pdata,8);
4241 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
4242 if (!NT_STATUS_IS_OK(status)) {
4243 return ERROR_NT(status);
4246 /* Check the new name has no '/' characters. */
4247 if (strchr_m(newname, '/'))
4248 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4250 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4252 /* Create the base directory. */
4253 pstrcpy(base_name, fname);
4254 p = strrchr_m(base_name, '/');
4257 /* Append the new name. */
4258 pstrcat(base_name, "/");
4259 pstrcat(base_name, newname);
4262 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4263 fsp->fnum, fsp->fsp_name, base_name ));
4264 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4266 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4268 status = rename_internals(conn, fname, base_name, 0, overwrite, False);
4270 if (!NT_STATUS_IS_OK(status)) {
4271 return ERROR_NT(status);
4273 process_pending_change_notify_queue((time_t)0);
4275 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4279 #if defined(HAVE_POSIX_ACLS)
4280 case SMB_SET_POSIX_ACL:
4282 uint16 posix_acl_version;
4283 uint16 num_file_acls;
4284 uint16 num_def_acls;
4285 BOOL valid_file_acls = True;
4286 BOOL valid_def_acls = True;
4288 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4289 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4291 posix_acl_version = SVAL(pdata,0);
4292 num_file_acls = SVAL(pdata,2);
4293 num_def_acls = SVAL(pdata,4);
4295 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4296 valid_file_acls = False;
4300 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4301 valid_def_acls = False;
4305 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4306 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4309 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4310 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4311 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4314 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4315 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4316 return(UNIXERROR(ERRDOS,ERRnoaccess));
4319 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4320 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4321 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4322 return(UNIXERROR(ERRDOS,ERRnoaccess));
4326 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4332 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4335 /* get some defaults (no modifications) if any info is zero or -1. */
4336 if (null_mtime(tvs.actime)) {
4337 tvs.actime = sbuf.st_atime;
4340 if (null_mtime(tvs.modtime)) {
4341 tvs.modtime = sbuf.st_mtime;
4344 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4345 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4346 DEBUG(6,("size: %.0f ", (double)size));
4349 if (S_ISDIR(sbuf.st_mode))
4355 DEBUG(6,("dosmode: %x\n" , dosmode));
4357 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4358 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4359 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4360 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4363 * Only do this test if we are not explicitly
4364 * changing the size of a file.
4367 size = get_file_size(sbuf);
4371 * Try and set the times, size and mode of this file -
4372 * if they are different from the current values
4375 /* check the mode isn't different, before changing it */
4376 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4378 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4380 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4381 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4382 return(UNIXERROR(ERRDOS,ERRnoaccess));
4387 if (size != get_file_size(sbuf)) {
4391 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4392 fname, (double)size ));
4395 files_struct *new_fsp = NULL;
4397 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
4399 FILE_SHARE_READ|FILE_SHARE_WRITE,
4402 FILE_ATTRIBUTE_NORMAL,
4406 if (new_fsp == NULL) {
4407 return(UNIXERROR(ERRDOS,ERRbadpath));
4409 ret = vfs_set_filelen(new_fsp, size);
4410 close_file(new_fsp,NORMAL_CLOSE);
4412 ret = vfs_set_filelen(fsp, size);
4416 return (UNIXERROR(ERRHRD,ERRdiskfull));
4421 * Finally the times.
4423 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4426 * This was a setfileinfo on an open file.
4427 * NT does this a lot. We also need to
4428 * set the time here, as it can be read by
4429 * FindFirst/FindNext and with the patch for bug #2045
4430 * in smbd/fileio.c it ensures that this timestamp is
4431 * kept sticky even after a write. We save the request
4432 * away and will set it on file close and after a write. JRA.
4435 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4436 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4437 fsp_set_pending_modtime(fsp, tvs.modtime);
4441 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4443 if(file_utime(conn, fname, &tvs)!=0) {
4444 return(UNIXERROR(ERRDOS,ERRnoaccess));
4449 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4454 /****************************************************************************
4455 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4456 ****************************************************************************/
4458 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4459 char **pparams, int total_params, char **ppdata, int total_data,
4460 unsigned int max_data_bytes)
4462 char *params = *pparams;
4463 char *pdata = *ppdata;
4466 SMB_STRUCT_STAT sbuf;
4467 BOOL bad_path = False;
4468 NTSTATUS status = NT_STATUS_OK;
4469 TALLOC_CTX *ctx = NULL;
4470 struct ea_list *ea_list = NULL;
4472 if (!CAN_WRITE(conn))
4473 return ERROR_DOS(ERRSRV,ERRaccess);
4475 if (total_params < 4) {
4476 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4479 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status);
4480 if (!NT_STATUS_IS_OK(status)) {
4481 return ERROR_NT(status);
4484 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4486 unix_convert(directory,conn,0,&bad_path,&sbuf);
4488 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4491 /* Any data in this call is an EA list. */
4492 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
4493 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4497 * OS/2 workplace shell seems to send SET_EA requests of "null"
4498 * length (4 bytes containing IVAL 4).
4499 * They seem to have no effect. Bug #3212. JRA.
4502 if (total_data != 4) {
4503 if (total_data < 10) {
4504 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4507 if (IVAL(pdata,0) > total_data) {
4508 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4509 IVAL(pdata,0), (unsigned int)total_data));
4510 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4513 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4515 return ERROR_NT(NT_STATUS_NO_MEMORY);
4517 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4519 talloc_destroy(ctx);
4520 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4522 } else if (IVAL(pdata,0) != 4) {
4523 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4526 if (check_name(directory,conn)) {
4527 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4531 talloc_destroy(ctx);
4532 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4533 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4536 /* Try and set any given EA. */
4538 status = set_ea(conn, NULL, directory, ea_list);
4539 talloc_destroy(ctx);
4540 if (!NT_STATUS_IS_OK(status)) {
4541 return ERROR_NT(status);
4545 /* Realloc the parameter and data sizes */
4546 params = SMB_REALLOC(*pparams,2);
4547 if(params == NULL) {
4548 return ERROR_NT(NT_STATUS_NO_MEMORY);
4554 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4559 /****************************************************************************
4560 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4561 We don't actually do this - we just send a null response.
4562 ****************************************************************************/
4564 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4565 char **pparams, int total_params, char **ppdata, int total_data,
4566 unsigned int max_data_bytes)
4568 static uint16 fnf_handle = 257;
4569 char *params = *pparams;
4572 if (total_params < 6) {
4573 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4576 info_level = SVAL(params,4);
4577 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4579 switch (info_level) {
4584 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4587 /* Realloc the parameter and data sizes */
4588 params = SMB_REALLOC(*pparams,6);
4589 if(params == NULL) {
4590 return ERROR_NT(NT_STATUS_NO_MEMORY);
4594 SSVAL(params,0,fnf_handle);
4595 SSVAL(params,2,0); /* No changes */
4596 SSVAL(params,4,0); /* No EA errors */
4603 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4608 /****************************************************************************
4609 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4610 changes). Currently this does nothing.
4611 ****************************************************************************/
4613 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4614 char **pparams, int total_params, char **ppdata, int total_data,
4615 unsigned int max_data_bytes)
4617 char *params = *pparams;
4619 DEBUG(3,("call_trans2findnotifynext\n"));
4621 /* Realloc the parameter and data sizes */
4622 params = SMB_REALLOC(*pparams,4);
4623 if(params == NULL) {
4624 return ERROR_NT(NT_STATUS_NO_MEMORY);
4628 SSVAL(params,0,0); /* No changes */
4629 SSVAL(params,2,0); /* No EA errors */
4631 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4636 /****************************************************************************
4637 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4638 ****************************************************************************/
4640 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4641 char **pparams, int total_params, char **ppdata, int total_data,
4642 unsigned int max_data_bytes)
4644 char *params = *pparams;
4647 int max_referral_level;
4649 DEBUG(10,("call_trans2getdfsreferral\n"));
4651 if (total_params < 2) {
4652 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4655 max_referral_level = SVAL(params,0);
4657 if(!lp_host_msdfs())
4658 return ERROR_DOS(ERRDOS,ERRbadfunc);
4660 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4661 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4662 return UNIXERROR(ERRDOS,ERRbadfile);
4664 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4665 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4670 #define LMCAT_SPL 0x53
4671 #define LMFUNC_GETJOBID 0x60
4673 /****************************************************************************
4674 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4675 ****************************************************************************/
4677 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4678 char **pparams, int total_params, char **ppdata, int total_data,
4679 unsigned int max_data_bytes)
4681 char *pdata = *ppdata;
4682 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4684 /* check for an invalid fid before proceeding */
4687 return(ERROR_DOS(ERRDOS,ERRbadfid));
4689 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4690 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4691 pdata = SMB_REALLOC(*ppdata, 32);
4693 return ERROR_NT(NT_STATUS_NO_MEMORY);
4697 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4698 CAN ACCEPT THIS IN UNICODE. JRA. */
4700 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4701 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4702 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4703 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4706 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4707 return ERROR_DOS(ERRSRV,ERRerror);
4711 /****************************************************************************
4712 Reply to a SMBfindclose (stop trans2 directory search).
4713 ****************************************************************************/
4715 int reply_findclose(connection_struct *conn,
4716 char *inbuf,char *outbuf,int length,int bufsize)
4719 int dptr_num=SVALS(inbuf,smb_vwv0);
4720 START_PROFILE(SMBfindclose);
4722 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4724 dptr_close(&dptr_num);
4726 outsize = set_message(outbuf,0,0,True);
4728 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4730 END_PROFILE(SMBfindclose);
4734 /****************************************************************************
4735 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4736 ****************************************************************************/
4738 int reply_findnclose(connection_struct *conn,
4739 char *inbuf,char *outbuf,int length,int bufsize)
4743 START_PROFILE(SMBfindnclose);
4745 dptr_num = SVAL(inbuf,smb_vwv0);
4747 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4749 /* We never give out valid handles for a
4750 findnotifyfirst - so any dptr_num is ok here.
4753 outsize = set_message(outbuf,0,0,True);
4755 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4757 END_PROFILE(SMBfindnclose);
4761 /****************************************************************************
4762 Reply to a SMBtranss2 - just ignore it!
4763 ****************************************************************************/
4765 int reply_transs2(connection_struct *conn,
4766 char *inbuf,char *outbuf,int length,int bufsize)
4768 START_PROFILE(SMBtranss2);
4769 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4770 END_PROFILE(SMBtranss2);
4774 /****************************************************************************
4775 Reply to a SMBtrans2.
4776 ****************************************************************************/
4778 int reply_trans2(connection_struct *conn,
4779 char *inbuf,char *outbuf,int length,int bufsize)
4782 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4783 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4784 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4786 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4787 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4788 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4789 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4790 int32 timeout = IVALS(inbuf,smb_timeout);
4792 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4793 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4794 char *params = NULL, *data = NULL;
4795 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4796 START_PROFILE(SMBtrans2);
4798 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4799 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4800 END_PROFILE(SMBtrans2);
4801 return ERROR_DOS(ERRSRV,ERRaccess);
4804 outsize = set_message(outbuf,0,0,True);
4806 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4807 is so as a sanity check */
4810 * Need to have rc=0 for ioctl to get job id for OS/2.
4811 * Network printing will fail if function is not successful.
4812 * Similar function in reply.c will be used if protocol
4813 * is LANMAN1.0 instead of LM1.2X002.
4814 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4815 * outbuf doesn't have to be set(only job id is used).
4817 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4818 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4819 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4820 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4822 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4823 DEBUG(2,("Transaction is %d\n",tran_call));
4824 END_PROFILE(SMBtrans2);
4825 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4829 /* Allocate the space for the maximum needed parameters and data */
4830 if (total_params > 0)
4831 params = (char *)SMB_MALLOC(total_params);
4833 data = (char *)SMB_MALLOC(total_data);
4835 if ((total_params && !params) || (total_data && !data)) {
4836 DEBUG(2,("Out of memory in reply_trans2\n"));
4839 END_PROFILE(SMBtrans2);
4840 return ERROR_NT(NT_STATUS_NO_MEMORY);
4843 /* Copy the param and data bytes sent with this request into
4844 the params buffer */
4845 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4846 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4848 if (num_params > total_params || num_data > total_data)
4849 exit_server("invalid params in reply_trans2");
4852 unsigned int psoff = SVAL(inbuf, smb_psoff);
4853 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4855 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4856 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4858 memcpy( params, smb_base(inbuf) + psoff, num_params);
4861 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4862 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4864 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4865 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4867 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4870 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4872 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4873 /* We need to send an interim response then receive the rest
4874 of the parameter/data bytes */
4875 outsize = set_message(outbuf,0,0,True);
4876 srv_signing_trans_stop();
4878 if (!send_smb(smbd_server_fd(),outbuf))
4879 exit_server("reply_trans2: send_smb failed.");
4881 while (num_data_sofar < total_data ||
4882 num_params_sofar < total_params) {
4884 unsigned int param_disp;
4885 unsigned int param_off;
4886 unsigned int data_disp;
4887 unsigned int data_off;
4889 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4891 /* We need to re-calcuate the new length after we've read the secondary packet. */
4892 length = smb_len(inbuf) + 4;
4895 * The sequence number for the trans reply is always
4896 * based on the last secondary received.
4899 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4902 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4903 outsize = set_message(outbuf,0,0,True);
4905 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4907 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4908 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4912 /* Revise total_params and total_data in case
4913 they have changed downwards */
4914 if (SVAL(inbuf, smb_tpscnt) < total_params)
4915 total_params = SVAL(inbuf, smb_tpscnt);
4916 if (SVAL(inbuf, smb_tdscnt) < total_data)
4917 total_data = SVAL(inbuf, smb_tdscnt);
4919 num_params = SVAL(inbuf,smb_spscnt);
4920 param_off = SVAL(inbuf, smb_spsoff);
4921 param_disp = SVAL(inbuf, smb_spsdisp);
4922 num_params_sofar += num_params;
4924 num_data = SVAL(inbuf, smb_sdscnt);
4925 data_off = SVAL(inbuf, smb_sdsoff);
4926 data_disp = SVAL(inbuf, smb_sdsdisp);
4927 num_data_sofar += num_data;
4929 if (num_params_sofar > total_params || num_data_sofar > total_data)
4933 if (param_disp + num_params > total_params)
4935 if ((param_disp + num_params < param_disp) ||
4936 (param_disp + num_params < num_params))
4938 if (param_disp > total_params)
4940 if ((smb_base(inbuf) + param_off + num_params > inbuf + length) ||
4941 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4943 if (params + param_disp < params)
4946 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
4949 if (data_disp + num_data > total_data)
4951 if ((data_disp + num_data < data_disp) ||
4952 (data_disp + num_data < num_data))
4954 if (data_disp > total_data)
4956 if ((smb_base(inbuf) + data_off + num_data > inbuf + length) ||
4957 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4959 if (data + data_disp < data)
4962 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4967 if (Protocol >= PROTOCOL_NT1) {
4968 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4971 /* Now we must call the relevant TRANS2 function */
4973 case TRANSACT2_OPEN:
4974 START_PROFILE_NESTED(Trans2_open);
4975 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4976 ¶ms, total_params, &data, total_data, max_data_bytes);
4977 END_PROFILE_NESTED(Trans2_open);
4980 case TRANSACT2_FINDFIRST:
4981 START_PROFILE_NESTED(Trans2_findfirst);
4982 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4983 ¶ms, total_params, &data, total_data, max_data_bytes);
4984 END_PROFILE_NESTED(Trans2_findfirst);
4987 case TRANSACT2_FINDNEXT:
4988 START_PROFILE_NESTED(Trans2_findnext);
4989 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4990 ¶ms, total_params, &data, total_data, max_data_bytes);
4991 END_PROFILE_NESTED(Trans2_findnext);
4994 case TRANSACT2_QFSINFO:
4995 START_PROFILE_NESTED(Trans2_qfsinfo);
4996 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4997 ¶ms, total_params, &data, total_data, max_data_bytes);
4998 END_PROFILE_NESTED(Trans2_qfsinfo);
5001 case TRANSACT2_SETFSINFO:
5002 START_PROFILE_NESTED(Trans2_setfsinfo);
5003 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
5004 ¶ms, total_params, &data, total_data, max_data_bytes);
5005 END_PROFILE_NESTED(Trans2_setfsinfo);
5008 case TRANSACT2_QPATHINFO:
5009 case TRANSACT2_QFILEINFO:
5010 START_PROFILE_NESTED(Trans2_qpathinfo);
5011 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5012 ¶ms, total_params, &data, total_data, max_data_bytes);
5013 END_PROFILE_NESTED(Trans2_qpathinfo);
5015 case TRANSACT2_SETPATHINFO:
5016 case TRANSACT2_SETFILEINFO:
5017 START_PROFILE_NESTED(Trans2_setpathinfo);
5018 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5019 ¶ms, total_params, &data, total_data, max_data_bytes);
5020 END_PROFILE_NESTED(Trans2_setpathinfo);
5023 case TRANSACT2_FINDNOTIFYFIRST:
5024 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5025 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
5026 ¶ms, total_params, &data, total_data, max_data_bytes);
5027 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5030 case TRANSACT2_FINDNOTIFYNEXT:
5031 START_PROFILE_NESTED(Trans2_findnotifynext);
5032 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
5033 ¶ms, total_params, &data, total_data, max_data_bytes);
5034 END_PROFILE_NESTED(Trans2_findnotifynext);
5036 case TRANSACT2_MKDIR:
5037 START_PROFILE_NESTED(Trans2_mkdir);
5038 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
5039 ¶ms, total_params, &data, total_data, max_data_bytes);
5040 END_PROFILE_NESTED(Trans2_mkdir);
5043 case TRANSACT2_GET_DFS_REFERRAL:
5044 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5045 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
5046 ¶ms, total_params, &data, total_data, max_data_bytes);
5047 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5049 case TRANSACT2_IOCTL:
5050 START_PROFILE_NESTED(Trans2_ioctl);
5051 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
5052 ¶ms, total_params, &data, total_data, max_data_bytes);
5053 END_PROFILE_NESTED(Trans2_ioctl);
5056 /* Error in request */
5057 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
5060 END_PROFILE(SMBtrans2);
5061 srv_signing_trans_stop();
5062 return ERROR_DOS(ERRSRV,ERRerror);
5065 /* As we do not know how many data packets will need to be
5066 returned here the various call_trans2xxxx calls
5067 must send their own. Thus a call_trans2xxx routine only
5068 returns a value other than -1 when it wants to send
5072 srv_signing_trans_stop();
5076 END_PROFILE(SMBtrans2);
5077 return outsize; /* If a correct response was needed the
5078 call_trans2xxx calls have already sent
5079 it. If outsize != -1 then it is returning */
5083 srv_signing_trans_stop();
5086 END_PROFILE(SMBtrans2);
5087 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);