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 *pparams = SMB_REALLOC(*pparams, 30);
874 if(*pparams == 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));
1167 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1171 mangle_map(fname,False,True,SNUM(conn));
1176 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1178 switch (info_level) {
1179 case SMB_FIND_INFO_STANDARD:
1180 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1181 if(requires_resume_key) {
1185 srv_put_dos_date2(p,0,cdate);
1186 srv_put_dos_date2(p,4,adate);
1187 srv_put_dos_date2(p,8,mdate);
1188 SIVAL(p,12,(uint32)file_size);
1189 SIVAL(p,16,(uint32)allocation_size);
1193 p += align_string(outbuf, p, 0);
1194 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1195 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1197 SCVAL(nameptr, -1, len - 2);
1199 SCVAL(nameptr, -1, 0);
1203 SCVAL(nameptr, -1, len - 1);
1205 SCVAL(nameptr, -1, 0);
1211 case SMB_FIND_EA_SIZE:
1212 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1213 if(requires_resume_key) {
1217 srv_put_dos_date2(p,0,cdate);
1218 srv_put_dos_date2(p,4,adate);
1219 srv_put_dos_date2(p,8,mdate);
1220 SIVAL(p,12,(uint32)file_size);
1221 SIVAL(p,16,(uint32)allocation_size);
1224 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1225 SIVAL(p,22,ea_size); /* Extended attributes */
1229 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1230 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1243 SCVAL(nameptr,0,len);
1245 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1248 case SMB_FIND_EA_LIST:
1250 struct ea_list *file_list = NULL;
1253 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1257 if(requires_resume_key) {
1261 srv_put_dos_date2(p,0,cdate);
1262 srv_put_dos_date2(p,4,adate);
1263 srv_put_dos_date2(p,8,mdate);
1264 SIVAL(p,12,(uint32)file_size);
1265 SIVAL(p,16,(uint32)allocation_size);
1267 p += 22; /* p now points to the EA area. */
1269 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1270 name_list = ea_list_union(name_list, file_list, &ea_len);
1272 /* We need to determine if this entry will fit in the space available. */
1273 /* Max string size is 255 bytes. */
1274 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1275 /* Move the dirptr back to prev_dirpos */
1276 dptr_SeekDir(conn->dirptr, prev_dirpos);
1277 *out_of_space = True;
1278 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1279 return False; /* Not finished - just out of space */
1282 /* Push the ea_data followed by the name. */
1283 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1285 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1286 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1299 SCVAL(nameptr,0,len);
1301 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1305 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1306 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1307 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1309 SIVAL(p,0,reskey); p += 4;
1310 put_long_date(p,cdate); p += 8;
1311 put_long_date(p,adate); p += 8;
1312 put_long_date(p,mdate); p += 8;
1313 put_long_date(p,mdate); p += 8;
1314 SOFF_T(p,0,file_size); p += 8;
1315 SOFF_T(p,0,allocation_size); p += 8;
1316 SIVAL(p,0,nt_extmode); p += 4;
1317 q = p; p += 4; /* q is placeholder for name length. */
1319 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1320 SIVAL(p,0,ea_size); /* Extended attributes */
1323 /* Clear the short name buffer. This is
1324 * IMPORTANT as not doing so will trigger
1325 * a Win2k client bug. JRA.
1327 if (!was_8_3 && check_mangled_names) {
1328 pstring mangled_name;
1329 pstrcpy(mangled_name, fname);
1330 mangle_map(mangled_name,True,True,SNUM(conn));
1331 mangled_name[12] = 0;
1332 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1334 memset(p + 2 + len,'\0',24 - len);
1341 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1344 SIVAL(p,0,0); /* Ensure any padding is null. */
1345 len = PTR_DIFF(p, pdata);
1346 len = (len + 3) & ~3;
1351 case SMB_FIND_FILE_DIRECTORY_INFO:
1352 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1354 SIVAL(p,0,reskey); p += 4;
1355 put_long_date(p,cdate); p += 8;
1356 put_long_date(p,adate); p += 8;
1357 put_long_date(p,mdate); p += 8;
1358 put_long_date(p,mdate); p += 8;
1359 SOFF_T(p,0,file_size); p += 8;
1360 SOFF_T(p,0,allocation_size); p += 8;
1361 SIVAL(p,0,nt_extmode); p += 4;
1362 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1365 SIVAL(p,0,0); /* Ensure any padding is null. */
1366 len = PTR_DIFF(p, pdata);
1367 len = (len + 3) & ~3;
1372 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1373 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1375 SIVAL(p,0,reskey); p += 4;
1376 put_long_date(p,cdate); p += 8;
1377 put_long_date(p,adate); p += 8;
1378 put_long_date(p,mdate); p += 8;
1379 put_long_date(p,mdate); p += 8;
1380 SOFF_T(p,0,file_size); p += 8;
1381 SOFF_T(p,0,allocation_size); p += 8;
1382 SIVAL(p,0,nt_extmode); p += 4;
1383 q = p; p += 4; /* q is placeholder for name length. */
1385 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1386 SIVAL(p,0,ea_size); /* Extended attributes */
1389 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1393 SIVAL(p,0,0); /* Ensure any padding is null. */
1394 len = PTR_DIFF(p, pdata);
1395 len = (len + 3) & ~3;
1400 case SMB_FIND_FILE_NAMES_INFO:
1401 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1403 SIVAL(p,0,reskey); p += 4;
1405 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1406 acl on a dir (tridge) */
1407 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1410 SIVAL(p,0,0); /* Ensure any padding is null. */
1411 len = PTR_DIFF(p, pdata);
1412 len = (len + 3) & ~3;
1417 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1418 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1420 SIVAL(p,0,reskey); p += 4;
1421 put_long_date(p,cdate); p += 8;
1422 put_long_date(p,adate); p += 8;
1423 put_long_date(p,mdate); p += 8;
1424 put_long_date(p,mdate); p += 8;
1425 SOFF_T(p,0,file_size); p += 8;
1426 SOFF_T(p,0,allocation_size); p += 8;
1427 SIVAL(p,0,nt_extmode); p += 4;
1428 q = p; p += 4; /* q is placeholder for name length. */
1430 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1431 SIVAL(p,0,ea_size); /* Extended attributes */
1434 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1435 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1436 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1437 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1440 SIVAL(p,0,0); /* Ensure any padding is null. */
1441 len = PTR_DIFF(p, pdata);
1442 len = (len + 3) & ~3;
1447 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1448 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1449 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1451 SIVAL(p,0,reskey); p += 4;
1452 put_long_date(p,cdate); p += 8;
1453 put_long_date(p,adate); p += 8;
1454 put_long_date(p,mdate); p += 8;
1455 put_long_date(p,mdate); p += 8;
1456 SOFF_T(p,0,file_size); p += 8;
1457 SOFF_T(p,0,allocation_size); p += 8;
1458 SIVAL(p,0,nt_extmode); p += 4;
1459 q = p; p += 4; /* q is placeholder for name length */
1461 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1462 SIVAL(p,0,ea_size); /* Extended attributes */
1465 /* Clear the short name buffer. This is
1466 * IMPORTANT as not doing so will trigger
1467 * a Win2k client bug. JRA.
1469 if (!was_8_3 && check_mangled_names) {
1470 pstring mangled_name;
1471 pstrcpy(mangled_name, fname);
1472 mangle_map(mangled_name,True,True,SNUM(conn));
1473 mangled_name[12] = 0;
1474 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1477 memset(p + 2 + len,'\0',24 - len);
1484 SSVAL(p,0,0); p += 2; /* Reserved ? */
1485 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1486 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1487 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1490 SIVAL(p,0,0); /* Ensure any padding is null. */
1491 len = PTR_DIFF(p, pdata);
1492 len = (len + 3) & ~3;
1497 /* CIFS UNIX Extension. */
1499 case SMB_FIND_FILE_UNIX:
1500 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1502 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1504 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1505 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1508 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1511 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1512 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1513 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1516 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1520 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1524 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1527 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1531 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1535 SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1538 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1542 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1546 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1548 SIVAL(p,0,0); /* Ensure any padding is null. */
1550 len = PTR_DIFF(p, pdata);
1551 len = (len + 3) & ~3;
1552 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1554 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1563 if (PTR_DIFF(p,pdata) > space_remaining) {
1564 /* Move the dirptr back to prev_dirpos */
1565 dptr_SeekDir(conn->dirptr, prev_dirpos);
1566 *out_of_space = True;
1567 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1568 return False; /* Not finished - just out of space */
1571 /* Setup the last entry pointer, as an offset from base_data */
1572 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1573 /* Advance the data pointer to the next slot */
1579 /****************************************************************************
1580 Reply to a TRANS2_FINDFIRST.
1581 ****************************************************************************/
1583 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1584 char **pparams, int total_params, char **ppdata, int total_data,
1585 unsigned int max_data_bytes)
1587 /* We must be careful here that we don't return more than the
1588 allowed number of data bytes. If this means returning fewer than
1589 maxentries then so be it. We assume that the redirector has
1590 enough room for the fixed number of parameter bytes it has
1592 char *params = *pparams;
1593 char *pdata = *ppdata;
1594 uint32 dirtype = SVAL(params,0);
1595 int maxentries = SVAL(params,2);
1596 uint16 findfirst_flags = SVAL(params,4);
1597 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1598 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1599 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1600 int info_level = SVAL(params,6);
1604 int last_entry_off=0;
1608 BOOL finished = False;
1609 BOOL dont_descend = False;
1610 BOOL out_of_space = False;
1611 int space_remaining;
1612 BOOL bad_path = False;
1613 BOOL mask_contains_wcard = False;
1614 SMB_STRUCT_STAT sbuf;
1615 TALLOC_CTX *ea_ctx = NULL;
1616 struct ea_list *ea_list = NULL;
1617 NTSTATUS ntstatus = NT_STATUS_OK;
1619 if (total_params < 12) {
1620 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1623 *directory = *mask = 0;
1625 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1626 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1627 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1628 info_level, max_data_bytes));
1631 /* W2K3 seems to treat zero as 1. */
1635 switch (info_level) {
1636 case SMB_FIND_INFO_STANDARD:
1637 case SMB_FIND_EA_SIZE:
1638 case SMB_FIND_EA_LIST:
1639 case SMB_FIND_FILE_DIRECTORY_INFO:
1640 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1641 case SMB_FIND_FILE_NAMES_INFO:
1642 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1643 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1644 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1646 case SMB_FIND_FILE_UNIX:
1647 if (!lp_unix_extensions())
1648 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1651 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1654 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1655 if (!NT_STATUS_IS_OK(ntstatus)) {
1656 return ERROR_NT(ntstatus);
1659 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1661 unix_convert(directory,conn,0,&bad_path,&sbuf);
1663 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1665 if(!check_name(directory,conn)) {
1666 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1669 p = strrchr_m(directory,'/');
1671 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1672 if((directory[0] == '.') && (directory[1] == '\0')) {
1674 mask_contains_wcard = True;
1676 pstrcpy(mask,directory);
1678 pstrcpy(directory,"./");
1684 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1686 if (info_level == SMB_FIND_EA_LIST) {
1689 if (total_data < 4) {
1690 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1693 ea_size = IVAL(pdata,0);
1694 if (ea_size != total_data) {
1695 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1696 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1697 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1700 if (!lp_ea_support(SNUM(conn))) {
1701 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1704 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1705 return ERROR_NT(NT_STATUS_NO_MEMORY);
1708 /* Pull out the list of names. */
1709 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1711 talloc_destroy(ea_ctx);
1712 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1716 *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1717 if(*ppdata == NULL ) {
1718 talloc_destroy(ea_ctx);
1719 return ERROR_NT(NT_STATUS_NO_MEMORY);
1723 /* Realloc the params space */
1724 *pparams = SMB_REALLOC(*pparams, 10);
1725 if (*pparams == NULL) {
1726 talloc_destroy(ea_ctx);
1727 return ERROR_NT(NT_STATUS_NO_MEMORY);
1731 /* Save the wildcard match and attribs we are using on this directory -
1732 needed as lanman2 assumes these are being saved between calls */
1734 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1736 talloc_destroy(ea_ctx);
1737 return(UNIXERROR(ERRDOS,ERRbadfile));
1740 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1742 /* We don't need to check for VOL here as this is returned by
1743 a different TRANS2 call. */
1745 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1746 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1747 dont_descend = True;
1750 space_remaining = max_data_bytes;
1751 out_of_space = False;
1753 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1754 BOOL got_exact_match = False;
1756 /* this is a heuristic to avoid seeking the dirptr except when
1757 absolutely necessary. It allows for a filename of about 40 chars */
1758 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1759 out_of_space = True;
1762 finished = !get_lanman2_dir_entry(conn,
1764 mask,dirtype,info_level,
1765 requires_resume_key,dont_descend,
1766 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1767 &last_entry_off, ea_list, ea_ctx);
1770 if (finished && out_of_space)
1773 if (!finished && !out_of_space)
1777 * As an optimisation if we know we aren't looking
1778 * for a wildcard name (ie. the name matches the wildcard exactly)
1779 * then we can finish on any (first) match.
1780 * This speeds up large directory searches. JRA.
1786 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1789 talloc_destroy(ea_ctx);
1791 /* Check if we can close the dirptr */
1792 if(close_after_first || (finished && close_if_end)) {
1793 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1794 dptr_close(&dptr_num);
1798 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1799 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1800 * the protocol level is less than NT1. Tested with smbclient. JRA.
1801 * This should fix the OS/2 client bug #2335.
1804 if(numentries == 0) {
1805 dptr_close(&dptr_num);
1806 if (Protocol < PROTOCOL_NT1) {
1807 return ERROR_DOS(ERRDOS,ERRnofiles);
1809 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1813 /* At this point pdata points to numentries directory entries. */
1815 /* Set up the return parameter block */
1816 SSVAL(params,0,dptr_num);
1817 SSVAL(params,2,numentries);
1818 SSVAL(params,4,finished);
1819 SSVAL(params,6,0); /* Never an EA error */
1820 SSVAL(params,8,last_entry_off);
1822 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1824 if ((! *directory) && dptr_path(dptr_num))
1825 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1827 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1828 smb_fn_name(CVAL(inbuf,smb_com)),
1829 mask, directory, dirtype, numentries ) );
1832 * Force a name mangle here to ensure that the
1833 * mask as an 8.3 name is top of the mangled cache.
1834 * The reasons for this are subtle. Don't remove
1835 * this code unless you know what you are doing
1836 * (see PR#13758). JRA.
1839 if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn)))
1840 mangle_map(mask, True, True, SNUM(conn));
1845 /****************************************************************************
1846 Reply to a TRANS2_FINDNEXT.
1847 ****************************************************************************/
1849 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1850 char **pparams, int total_params, char **ppdata, int total_data,
1851 unsigned int max_data_bytes)
1853 /* We must be careful here that we don't return more than the
1854 allowed number of data bytes. If this means returning fewer than
1855 maxentries then so be it. We assume that the redirector has
1856 enough room for the fixed number of parameter bytes it has
1858 char *params = *pparams;
1859 char *pdata = *ppdata;
1860 int dptr_num = SVAL(params,0);
1861 int maxentries = SVAL(params,2);
1862 uint16 info_level = SVAL(params,4);
1863 uint32 resume_key = IVAL(params,6);
1864 uint16 findnext_flags = SVAL(params,10);
1865 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1866 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1867 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1868 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1869 BOOL mask_contains_wcard = False;
1870 pstring resume_name;
1876 int i, last_entry_off=0;
1877 BOOL finished = False;
1878 BOOL dont_descend = False;
1879 BOOL out_of_space = False;
1880 int space_remaining;
1881 TALLOC_CTX *ea_ctx = NULL;
1882 struct ea_list *ea_list = NULL;
1883 NTSTATUS ntstatus = NT_STATUS_OK;
1885 if (total_params < 12) {
1886 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1889 *mask = *directory = *resume_name = 0;
1891 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1892 if (!NT_STATUS_IS_OK(ntstatus)) {
1893 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1894 complain (it thinks we're asking for the directory above the shared
1895 path or an invalid name). Catch this as the resume name is only compared, never used in
1896 a file access. JRA. */
1897 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1898 pstrcpy(resume_name, "..");
1899 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1900 pstrcpy(resume_name, ".");
1902 return ERROR_NT(ntstatus);
1906 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1907 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1908 resume_key = %d resume name = %s continue=%d level = %d\n",
1909 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1910 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1913 /* W2K3 seems to treat zero as 1. */
1917 switch (info_level) {
1918 case SMB_FIND_INFO_STANDARD:
1919 case SMB_FIND_EA_SIZE:
1920 case SMB_FIND_EA_LIST:
1921 case SMB_FIND_FILE_DIRECTORY_INFO:
1922 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1923 case SMB_FIND_FILE_NAMES_INFO:
1924 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1925 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1926 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1928 case SMB_FIND_FILE_UNIX:
1929 if (!lp_unix_extensions())
1930 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1933 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1936 if (info_level == SMB_FIND_EA_LIST) {
1939 if (total_data < 4) {
1940 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1943 ea_size = IVAL(pdata,0);
1944 if (ea_size != total_data) {
1945 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1946 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1947 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1950 if (!lp_ea_support(SNUM(conn))) {
1951 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1954 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1955 return ERROR_NT(NT_STATUS_NO_MEMORY);
1958 /* Pull out the list of names. */
1959 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1961 talloc_destroy(ea_ctx);
1962 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1966 *ppdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1967 if(*ppdata == NULL) {
1968 talloc_destroy(ea_ctx);
1969 return ERROR_NT(NT_STATUS_NO_MEMORY);
1974 /* Realloc the params space */
1975 *pparams = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1976 if(*pparams == NULL ) {
1977 talloc_destroy(ea_ctx);
1978 return ERROR_NT(NT_STATUS_NO_MEMORY);
1983 /* Check that the dptr is valid */
1984 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
1985 talloc_destroy(ea_ctx);
1986 return ERROR_DOS(ERRDOS,ERRnofiles);
1989 string_set(&conn->dirpath,dptr_path(dptr_num));
1991 /* Get the wildcard mask from the dptr */
1992 if((p = dptr_wcard(dptr_num))== NULL) {
1993 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1994 talloc_destroy(ea_ctx);
1995 return ERROR_DOS(ERRDOS,ERRnofiles);
1999 pstrcpy(directory,conn->dirpath);
2001 /* Get the attr mask from the dptr */
2002 dirtype = dptr_attr(dptr_num);
2004 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2005 dptr_num, mask, dirtype,
2007 dptr_TellDir(conn->dirptr)));
2009 /* We don't need to check for VOL here as this is returned by
2010 a different TRANS2 call. */
2012 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2013 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2014 dont_descend = True;
2017 space_remaining = max_data_bytes;
2018 out_of_space = False;
2021 * Seek to the correct position. We no longer use the resume key but
2022 * depend on the last file name instead.
2025 if(*resume_name && !continue_bit) {
2028 long current_pos = 0;
2030 * Remember, mangle_map is called by
2031 * get_lanman2_dir_entry(), so the resume name
2032 * could be mangled. Ensure we check the unmangled name.
2035 if (mangle_is_mangled(resume_name, SNUM(conn))) {
2036 mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn));
2040 * Fix for NT redirector problem triggered by resume key indexes
2041 * changing between directory scans. We now return a resume key of 0
2042 * and instead look for the filename to continue from (also given
2043 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2044 * findfirst/findnext (as is usual) then the directory pointer
2045 * should already be at the correct place.
2048 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2049 } /* end if resume_name && !continue_bit */
2051 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2052 BOOL got_exact_match = False;
2054 /* this is a heuristic to avoid seeking the dirptr except when
2055 absolutely necessary. It allows for a filename of about 40 chars */
2056 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2057 out_of_space = True;
2060 finished = !get_lanman2_dir_entry(conn,
2062 mask,dirtype,info_level,
2063 requires_resume_key,dont_descend,
2064 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2065 &last_entry_off, ea_list, ea_ctx);
2068 if (finished && out_of_space)
2071 if (!finished && !out_of_space)
2075 * As an optimisation if we know we aren't looking
2076 * for a wildcard name (ie. the name matches the wildcard exactly)
2077 * then we can finish on any (first) match.
2078 * This speeds up large directory searches. JRA.
2084 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2087 talloc_destroy(ea_ctx);
2089 /* Check if we can close the dirptr */
2090 if(close_after_request || (finished && close_if_end)) {
2091 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2092 dptr_close(&dptr_num); /* This frees up the saved mask */
2095 /* Set up the return parameter block */
2096 SSVAL(params,0,numentries);
2097 SSVAL(params,2,finished);
2098 SSVAL(params,4,0); /* Never an EA error */
2099 SSVAL(params,6,last_entry_off);
2101 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2103 if ((! *directory) && dptr_path(dptr_num))
2104 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2106 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2107 smb_fn_name(CVAL(inbuf,smb_com)),
2108 mask, directory, dirtype, numentries ) );
2113 /****************************************************************************
2114 Reply to a TRANS2_QFSINFO (query filesystem info).
2115 ****************************************************************************/
2117 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2118 char **pparams, int total_params, char **ppdata, int total_data,
2119 unsigned int max_data_bytes)
2121 char *pdata = *ppdata;
2122 char *params = *pparams;
2123 uint16 info_level = SVAL(params,0);
2126 char *vname = volume_label(SNUM(conn));
2127 int snum = SNUM(conn);
2128 char *fstype = lp_fstype(SNUM(conn));
2131 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2133 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2134 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2135 return ERROR_DOS(ERRSRV,ERRinvdevice);
2138 *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2139 if (*ppdata == NULL ) {
2140 return ERROR_NT(NT_STATUS_NO_MEMORY);
2144 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2146 switch (info_level) {
2147 case SMB_INFO_ALLOCATION:
2149 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2151 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2152 return(UNIXERROR(ERRHRD,ERRgeneral));
2155 block_size = lp_block_size(snum);
2156 if (bsize < block_size) {
2157 SMB_BIG_UINT factor = block_size/bsize;
2162 if (bsize > block_size) {
2163 SMB_BIG_UINT factor = bsize/block_size;
2168 bytes_per_sector = 512;
2169 sectors_per_unit = bsize/bytes_per_sector;
2171 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2172 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2173 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2175 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2176 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2177 SIVAL(pdata,l1_cUnit,dsize);
2178 SIVAL(pdata,l1_cUnitAvail,dfree);
2179 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2183 case SMB_INFO_VOLUME:
2184 /* Return volume name */
2186 * Add volume serial number - hash of a combination of
2187 * the called hostname and the service name.
2189 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2191 * Win2k3 and previous mess this up by sending a name length
2192 * one byte short. I believe only older clients (OS/2 Win9x) use
2193 * this call so try fixing this by adding a terminating null to
2194 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2196 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2197 SCVAL(pdata,l2_vol_cch,len);
2198 data_len = l2_vol_szVolLabel + len;
2199 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2200 (unsigned)st.st_ctime, len, vname));
2203 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2204 case SMB_FS_ATTRIBUTE_INFORMATION:
2207 #if defined(HAVE_SYS_QUOTAS)
2208 quota_flag = FILE_VOLUME_QUOTAS;
2211 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2212 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2213 quota_flag); /* FS ATTRIBUTES */
2215 SIVAL(pdata,4,255); /* Max filename component length */
2216 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2217 and will think we can't do long filenames */
2218 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2220 data_len = 12 + len;
2223 case SMB_QUERY_FS_LABEL_INFO:
2224 case SMB_FS_LABEL_INFORMATION:
2225 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2230 case SMB_QUERY_FS_VOLUME_INFO:
2231 case SMB_FS_VOLUME_INFORMATION:
2234 * Add volume serial number - hash of a combination of
2235 * the called hostname and the service name.
2237 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2238 (str_checksum(get_local_machine_name())<<16));
2240 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2241 SIVAL(pdata,12,len);
2243 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2244 (int)strlen(vname),vname, lp_servicename(snum)));
2247 case SMB_QUERY_FS_SIZE_INFO:
2248 case SMB_FS_SIZE_INFORMATION:
2250 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2252 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2253 return(UNIXERROR(ERRHRD,ERRgeneral));
2255 block_size = lp_block_size(snum);
2256 if (bsize < block_size) {
2257 SMB_BIG_UINT factor = block_size/bsize;
2262 if (bsize > block_size) {
2263 SMB_BIG_UINT factor = bsize/block_size;
2268 bytes_per_sector = 512;
2269 sectors_per_unit = bsize/bytes_per_sector;
2270 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2271 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2272 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2273 SBIG_UINT(pdata,0,dsize);
2274 SBIG_UINT(pdata,8,dfree);
2275 SIVAL(pdata,16,sectors_per_unit);
2276 SIVAL(pdata,20,bytes_per_sector);
2280 case SMB_FS_FULL_SIZE_INFORMATION:
2282 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2284 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2285 return(UNIXERROR(ERRHRD,ERRgeneral));
2287 block_size = lp_block_size(snum);
2288 if (bsize < block_size) {
2289 SMB_BIG_UINT factor = block_size/bsize;
2294 if (bsize > block_size) {
2295 SMB_BIG_UINT factor = bsize/block_size;
2300 bytes_per_sector = 512;
2301 sectors_per_unit = bsize/bytes_per_sector;
2302 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2303 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2304 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2305 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2306 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2307 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2308 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2309 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2313 case SMB_QUERY_FS_DEVICE_INFO:
2314 case SMB_FS_DEVICE_INFORMATION:
2316 SIVAL(pdata,0,0); /* dev type */
2317 SIVAL(pdata,4,0); /* characteristics */
2320 #ifdef HAVE_SYS_QUOTAS
2321 case SMB_FS_QUOTA_INFORMATION:
2323 * what we have to send --metze:
2325 * Unknown1: 24 NULL bytes
2326 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2327 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2328 * Quota Flags: 2 byte :
2329 * Unknown3: 6 NULL bytes
2333 * details for Quota Flags:
2335 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2336 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2337 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2338 * 0x0001 Enable Quotas: enable quota for this fs
2342 /* we need to fake up a fsp here,
2343 * because its not send in this call
2346 SMB_NTQUOTA_STRUCT quotas;
2349 ZERO_STRUCT(quotas);
2355 if (current_user.ut.uid != 0) {
2356 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2357 lp_servicename(SNUM(conn)),conn->user));
2358 return ERROR_DOS(ERRDOS,ERRnoaccess);
2361 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2362 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2363 return ERROR_DOS(ERRSRV,ERRerror);
2368 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2370 /* Unknown1 24 NULL bytes*/
2371 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2372 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2373 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2375 /* Default Soft Quota 8 bytes */
2376 SBIG_UINT(pdata,24,quotas.softlim);
2378 /* Default Hard Quota 8 bytes */
2379 SBIG_UINT(pdata,32,quotas.hardlim);
2381 /* Quota flag 2 bytes */
2382 SSVAL(pdata,40,quotas.qflags);
2384 /* Unknown3 6 NULL bytes */
2390 #endif /* HAVE_SYS_QUOTAS */
2391 case SMB_FS_OBJECTID_INFORMATION:
2396 * Query the version and capabilities of the CIFS UNIX extensions
2400 case SMB_QUERY_CIFS_UNIX_INFO:
2401 if (!lp_unix_extensions())
2402 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2404 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2405 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2406 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(CIFS_UNIX_POSIX_ACLS_CAP|
2407 CIFS_UNIX_POSIX_PATHNAMES_CAP))); /* We have POSIX ACLs and pathname capability. */
2410 case SMB_QUERY_POSIX_FS_INFO:
2413 vfs_statvfs_struct svfs;
2415 if (!lp_unix_extensions())
2416 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2418 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2422 SIVAL(pdata,0,svfs.OptimalTransferSize);
2423 SIVAL(pdata,4,svfs.BlockSize);
2424 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2425 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2426 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2427 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2428 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2429 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2430 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2432 } else if (rc == EOPNOTSUPP) {
2433 return ERROR_DOS(ERRDOS, ERRunknownlevel);
2434 #endif /* EOPNOTSUPP */
2436 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2437 return ERROR_DOS(ERRSRV,ERRerror);
2442 case SMB_MAC_QUERY_FS_INFO:
2444 * Thursby MAC extension... ONLY on NTFS filesystems
2445 * once we do streams then we don't need this
2447 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2449 SIVAL(pdata,84,0x100); /* Don't support mac... */
2454 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2458 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2460 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2465 /****************************************************************************
2466 Reply to a TRANS2_SETFSINFO (set filesystem info).
2467 ****************************************************************************/
2469 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2470 char **pparams, int total_params, char **ppdata, int total_data,
2471 unsigned int max_data_bytes)
2473 char *pdata = *ppdata;
2474 char *params = *pparams;
2478 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2481 if (total_params < 4) {
2482 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2484 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2487 info_level = SVAL(params,2);
2489 switch(info_level) {
2490 case SMB_SET_CIFS_UNIX_INFO:
2492 uint16 client_unix_major;
2493 uint16 client_unix_minor;
2494 uint32 client_unix_cap_low;
2495 uint32 client_unix_cap_high;
2497 if (!lp_unix_extensions()) {
2498 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2501 /* There should be 12 bytes of capabilities set. */
2502 if (total_data < 8) {
2503 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2505 client_unix_major = SVAL(pdata,0);
2506 client_unix_minor = SVAL(pdata,2);
2507 client_unix_cap_low = IVAL(pdata,4);
2508 client_unix_cap_high = IVAL(pdata,8);
2509 /* Just print these values for now. */
2510 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2511 cap_low = 0x%x, cap_high = 0x%x\n",
2512 (unsigned int)client_unix_major,
2513 (unsigned int)client_unix_minor,
2514 (unsigned int)client_unix_cap_low,
2515 (unsigned int)client_unix_cap_high ));
2517 /* Here is where we must switch to posix pathname processing... */
2518 lp_set_posix_pathnames();
2519 mangle_change_to_posix();
2522 case SMB_FS_QUOTA_INFORMATION:
2524 files_struct *fsp = NULL;
2525 SMB_NTQUOTA_STRUCT quotas;
2527 ZERO_STRUCT(quotas);
2530 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2531 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2532 lp_servicename(SNUM(conn)),conn->user));
2533 return ERROR_DOS(ERRSRV,ERRaccess);
2536 /* note: normaly there're 48 bytes,
2537 * but we didn't use the last 6 bytes for now
2540 fsp = file_fsp(params,0);
2541 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2542 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2543 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2546 if (total_data < 42) {
2547 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2549 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2552 /* unknown_1 24 NULL bytes in pdata*/
2554 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2555 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2556 #ifdef LARGE_SMB_OFF_T
2557 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2558 #else /* LARGE_SMB_OFF_T */
2559 if ((IVAL(pdata,28) != 0)&&
2560 ((quotas.softlim != 0xFFFFFFFF)||
2561 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2562 /* more than 32 bits? */
2563 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2565 #endif /* LARGE_SMB_OFF_T */
2567 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2568 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2569 #ifdef LARGE_SMB_OFF_T
2570 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2571 #else /* LARGE_SMB_OFF_T */
2572 if ((IVAL(pdata,36) != 0)&&
2573 ((quotas.hardlim != 0xFFFFFFFF)||
2574 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2575 /* more than 32 bits? */
2576 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2578 #endif /* LARGE_SMB_OFF_T */
2580 /* quota_flags 2 bytes **/
2581 quotas.qflags = SVAL(pdata,40);
2583 /* unknown_2 6 NULL bytes follow*/
2585 /* now set the quotas */
2586 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2587 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2588 return ERROR_DOS(ERRSRV,ERRerror);
2594 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2596 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2601 * sending this reply works fine,
2602 * but I'm not sure it's the same
2603 * like windows do...
2606 outsize = set_message(outbuf,10,0,True);
2611 /****************************************************************************
2612 Utility function to set bad path error.
2613 ****************************************************************************/
2615 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2617 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2618 err, (int)bad_path ));
2622 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2624 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2627 return UNIXERROR(def_class,def_code);
2630 #if defined(HAVE_POSIX_ACLS)
2631 /****************************************************************************
2632 Utility function to count the number of entries in a POSIX acl.
2633 ****************************************************************************/
2635 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2637 unsigned int ace_count = 0;
2638 int entry_id = SMB_ACL_FIRST_ENTRY;
2639 SMB_ACL_ENTRY_T entry;
2641 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2643 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2644 entry_id = SMB_ACL_NEXT_ENTRY;
2651 /****************************************************************************
2652 Utility function to marshall a POSIX acl into wire format.
2653 ****************************************************************************/
2655 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2657 int entry_id = SMB_ACL_FIRST_ENTRY;
2658 SMB_ACL_ENTRY_T entry;
2660 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2661 SMB_ACL_TAG_T tagtype;
2662 SMB_ACL_PERMSET_T permset;
2663 unsigned char perms = 0;
2664 unsigned int own_grp;
2667 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2668 entry_id = SMB_ACL_NEXT_ENTRY;
2671 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2672 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2676 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2677 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2681 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2682 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2683 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2685 SCVAL(pdata,1,perms);
2688 case SMB_ACL_USER_OBJ:
2689 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2690 own_grp = (unsigned int)pst->st_uid;
2691 SIVAL(pdata,2,own_grp);
2696 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2698 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2700 own_grp = (unsigned int)*puid;
2701 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2702 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2703 SIVAL(pdata,2,own_grp);
2707 case SMB_ACL_GROUP_OBJ:
2708 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2709 own_grp = (unsigned int)pst->st_gid;
2710 SIVAL(pdata,2,own_grp);
2715 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2717 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2719 own_grp = (unsigned int)*pgid;
2720 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2721 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2722 SIVAL(pdata,2,own_grp);
2727 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2728 SIVAL(pdata,2,0xFFFFFFFF);
2729 SIVAL(pdata,6,0xFFFFFFFF);
2732 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2733 SIVAL(pdata,2,0xFFFFFFFF);
2734 SIVAL(pdata,6,0xFFFFFFFF);
2737 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2740 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2747 /****************************************************************************
2748 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2749 file name or file id).
2750 ****************************************************************************/
2752 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2753 unsigned int tran_call,
2754 char **pparams, int total_params, char **ppdata, int total_data,
2755 unsigned int max_data_bytes)
2757 char *params = *pparams;
2758 char *pdata = *ppdata;
2762 SMB_OFF_T file_size=0;
2763 SMB_BIG_UINT allocation_size=0;
2764 unsigned int data_size = 0;
2765 unsigned int param_size = 2;
2766 SMB_STRUCT_STAT sbuf;
2767 pstring fname, dos_fname;
2772 BOOL bad_path = False;
2773 BOOL delete_pending = False;
2776 files_struct *fsp = NULL;
2777 TALLOC_CTX *ea_ctx = NULL;
2778 struct ea_list *ea_list = NULL;
2779 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2782 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2786 if (tran_call == TRANSACT2_QFILEINFO) {
2787 if (total_params < 4) {
2788 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2791 fsp = file_fsp(params,0);
2792 info_level = SVAL(params,2);
2794 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2796 if(fsp && (fsp->fake_file_handle)) {
2798 * This is actually for the QUOTA_FAKE_FILE --metze
2801 pstrcpy(fname, fsp->fsp_name);
2802 /* We know this name is ok, it's already passed the checks. */
2804 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2806 * This is actually a QFILEINFO on a directory
2807 * handle (returned from an NT SMB). NT5.0 seems
2808 * to do this call. JRA.
2810 /* We know this name is ok, it's already passed the checks. */
2811 pstrcpy(fname, fsp->fsp_name);
2813 if (INFO_LEVEL_IS_UNIX(info_level)) {
2814 /* Always do lstat for UNIX calls. */
2815 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2816 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2817 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2819 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2820 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2821 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2824 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2827 * Original code - this is an open file.
2829 CHECK_FSP(fsp,conn);
2831 pstrcpy(fname, fsp->fsp_name);
2832 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2833 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2834 return(UNIXERROR(ERRDOS,ERRbadfid));
2836 pos = fsp->fh->position_information;
2837 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2838 access_mask = fsp->access_mask;
2841 NTSTATUS status = NT_STATUS_OK;
2844 if (total_params < 6) {
2845 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2848 info_level = SVAL(params,0);
2850 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2852 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
2853 if (!NT_STATUS_IS_OK(status)) {
2854 return ERROR_NT(status);
2857 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2859 unix_convert(fname,conn,0,&bad_path,&sbuf);
2861 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2863 if (!check_name(fname,conn)) {
2864 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2865 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2868 if (INFO_LEVEL_IS_UNIX(info_level)) {
2869 /* Always do lstat for UNIX calls. */
2870 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2871 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2872 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2874 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2875 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2876 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2879 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2880 if (delete_pending) {
2881 return ERROR_NT(NT_STATUS_DELETE_PENDING);
2885 nlink = sbuf.st_nlink;
2887 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2888 /* NTFS does not seem to count ".." */
2892 if ((nlink > 0) && delete_pending) {
2896 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2897 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2899 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2900 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2902 p = strrchr_m(fname,'/');
2908 mode = dos_mode(conn,fname,&sbuf);
2910 mode = FILE_ATTRIBUTE_NORMAL;
2912 fullpathname = fname;
2914 file_size = get_file_size(sbuf);
2916 /* Pull any EA list from the data portion. */
2917 if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2920 if (total_data < 4) {
2921 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2923 ea_size = IVAL(pdata,0);
2925 if (total_data > 0 && ea_size != total_data) {
2926 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2927 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2928 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2931 if (!lp_ea_support(SNUM(conn))) {
2932 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2935 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2936 return ERROR_NT(NT_STATUS_NO_MEMORY);
2939 /* Pull out the list of names. */
2940 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2942 talloc_destroy(ea_ctx);
2943 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2947 *pparams = SMB_REALLOC(*pparams,2);
2948 if (*pparams == NULL) {
2949 talloc_destroy(ea_ctx);
2950 return ERROR_NT(NT_STATUS_NO_MEMORY);
2954 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2955 *ppdata = SMB_REALLOC(*ppdata, data_size);
2956 if (*ppdata == NULL ) {
2957 talloc_destroy(ea_ctx);
2958 return ERROR_NT(NT_STATUS_NO_MEMORY);
2962 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2964 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2967 if (fsp->pending_modtime) {
2968 /* the pending modtime overrides the current modtime */
2969 sbuf.st_mtime = fsp->pending_modtime;
2972 /* Do we have this path open ? */
2973 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2974 if (fsp1 && fsp1->pending_modtime) {
2975 /* the pending modtime overrides the current modtime */
2976 sbuf.st_mtime = fsp1->pending_modtime;
2978 if (fsp1 && fsp1->initial_allocation_size) {
2979 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
2983 if (lp_dos_filetime_resolution(SNUM(conn))) {
2985 sbuf.st_atime &= ~1;
2986 sbuf.st_ctime &= ~1;
2987 sbuf.st_mtime &= ~1;
2990 /* NT expects the name to be in an exact form of the *full*
2991 filename. See the trans2 torture test */
2992 if (strequal(base_name,".")) {
2993 pstrcpy(dos_fname, "\\");
2995 pstr_sprintf(dos_fname, "\\%s", fname);
2996 string_replace(dos_fname, '/', '\\');
2999 switch (info_level) {
3000 case SMB_INFO_STANDARD:
3001 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3003 srv_put_dos_date2(pdata,l1_fdateCreation,c_time);
3004 srv_put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
3005 srv_put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
3006 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3007 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3008 SSVAL(pdata,l1_attrFile,mode);
3011 case SMB_INFO_QUERY_EA_SIZE:
3013 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3014 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3016 srv_put_dos_date2(pdata,0,c_time);
3017 srv_put_dos_date2(pdata,4,sbuf.st_atime);
3018 srv_put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */
3019 SIVAL(pdata,12,(uint32)file_size);
3020 SIVAL(pdata,16,(uint32)allocation_size);
3021 SSVAL(pdata,20,mode);
3022 SIVAL(pdata,22,ea_size);
3026 case SMB_INFO_IS_NAME_VALID:
3027 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3028 if (tran_call == TRANSACT2_QFILEINFO) {
3029 /* os/2 needs this ? really ?*/
3030 return ERROR_DOS(ERRDOS,ERRbadfunc);
3036 case SMB_INFO_QUERY_EAS_FROM_LIST:
3038 size_t total_ea_len = 0;
3039 struct ea_list *ea_file_list = NULL;
3041 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3043 ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3044 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3046 if (!ea_list || (total_ea_len > data_size)) {
3047 talloc_destroy(ea_ctx);
3049 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3053 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3054 talloc_destroy(ea_ctx);
3058 case SMB_INFO_QUERY_ALL_EAS:
3060 /* We have data_size bytes to put EA's into. */
3061 size_t total_ea_len = 0;
3063 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3065 ea_ctx = talloc_init("ea_ctx");
3067 return ERROR_NT(NT_STATUS_NO_MEMORY);
3070 ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3071 if (!ea_list || (total_ea_len > data_size)) {
3072 talloc_destroy(ea_ctx);
3074 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3078 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3079 talloc_destroy(ea_ctx);
3083 case SMB_FILE_BASIC_INFORMATION:
3084 case SMB_QUERY_FILE_BASIC_INFO:
3086 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3087 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3088 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3090 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3094 put_long_date(pdata,c_time);
3095 put_long_date(pdata+8,sbuf.st_atime);
3096 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3097 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3098 SIVAL(pdata,32,mode);
3100 DEBUG(5,("SMB_QFBI - "));
3102 time_t create_time = c_time;
3103 DEBUG(5,("create: %s ", ctime(&create_time)));
3105 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3106 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3107 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3108 DEBUG(5,("mode: %x\n", mode));
3111 case SMB_FILE_STANDARD_INFORMATION:
3112 case SMB_QUERY_FILE_STANDARD_INFO:
3114 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3116 SOFF_T(pdata,0,allocation_size);
3117 SOFF_T(pdata,8,file_size);
3118 SIVAL(pdata,16,nlink);
3119 SCVAL(pdata,20,delete_pending?1:0);
3120 SCVAL(pdata,21,(mode&aDIR)?1:0);
3121 SSVAL(pdata,22,0); /* Padding. */
3124 case SMB_FILE_EA_INFORMATION:
3125 case SMB_QUERY_FILE_EA_INFO:
3127 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3128 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3130 SIVAL(pdata,0,ea_size);
3134 /* Get the 8.3 name - used if NT SMB was negotiated. */
3135 case SMB_QUERY_FILE_ALT_NAME_INFO:
3136 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3140 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3141 pstrcpy(short_name,base_name);
3142 /* Mangle if not already 8.3 */
3143 if(!mangle_is_8_3(short_name, True, SNUM(conn))) {
3144 mangle_map(short_name,True,True,SNUM(conn));
3146 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3147 data_size = 4 + len;
3152 case SMB_QUERY_FILE_NAME_INFO:
3154 this must be *exactly* right for ACLs on mapped drives to work
3156 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3157 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3158 data_size = 4 + len;
3162 case SMB_FILE_ALLOCATION_INFORMATION:
3163 case SMB_QUERY_FILE_ALLOCATION_INFO:
3164 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3166 SOFF_T(pdata,0,allocation_size);
3169 case SMB_FILE_END_OF_FILE_INFORMATION:
3170 case SMB_QUERY_FILE_END_OF_FILEINFO:
3171 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3173 SOFF_T(pdata,0,file_size);
3176 case SMB_QUERY_FILE_ALL_INFO:
3177 case SMB_FILE_ALL_INFORMATION:
3179 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3180 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3181 put_long_date(pdata,c_time);
3182 put_long_date(pdata+8,sbuf.st_atime);
3183 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3184 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3185 SIVAL(pdata,32,mode);
3186 SIVAL(pdata,36,0); /* padding. */
3188 SOFF_T(pdata,0,allocation_size);
3189 SOFF_T(pdata,8,file_size);
3190 SIVAL(pdata,16,nlink);
3191 SCVAL(pdata,20,delete_pending);
3192 SCVAL(pdata,21,(mode&aDIR)?1:0);
3195 SIVAL(pdata,0,ea_size);
3196 pdata += 4; /* EA info */
3197 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3200 data_size = PTR_DIFF(pdata,(*ppdata));
3203 case SMB_FILE_INTERNAL_INFORMATION:
3204 /* This should be an index number - looks like
3207 I think this causes us to fail the IFSKIT
3208 BasicFileInformationTest. -tpot */
3210 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3211 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3212 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3216 case SMB_FILE_ACCESS_INFORMATION:
3217 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3218 SIVAL(pdata,0,access_mask);
3222 case SMB_FILE_NAME_INFORMATION:
3223 /* Pathname with leading '\'. */
3226 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3227 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3228 SIVAL(pdata,0,byte_len);
3229 data_size = 4 + byte_len;
3233 case SMB_FILE_DISPOSITION_INFORMATION:
3234 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3236 SCVAL(pdata,0,delete_pending);
3239 case SMB_FILE_POSITION_INFORMATION:
3240 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3242 SOFF_T(pdata,0,pos);
3245 case SMB_FILE_MODE_INFORMATION:
3246 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3247 SIVAL(pdata,0,mode);
3251 case SMB_FILE_ALIGNMENT_INFORMATION:
3252 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3253 SIVAL(pdata,0,0); /* No alignment needed. */
3259 * NT4 server just returns "invalid query" to this - if we try to answer
3260 * it then NTws gets a BSOD! (tridge).
3261 * W2K seems to want this. JRA.
3263 case SMB_QUERY_FILE_STREAM_INFO:
3265 case SMB_FILE_STREAM_INFORMATION:
3266 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3270 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3271 SIVAL(pdata,0,0); /* ??? */
3272 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3273 SOFF_T(pdata,8,file_size);
3274 SIVAL(pdata,16,allocation_size);
3275 SIVAL(pdata,20,0); /* ??? */
3276 data_size = 24 + byte_len;
3280 case SMB_QUERY_COMPRESSION_INFO:
3281 case SMB_FILE_COMPRESSION_INFORMATION:
3282 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3283 SOFF_T(pdata,0,file_size);
3284 SIVAL(pdata,8,0); /* ??? */
3285 SIVAL(pdata,12,0); /* ??? */
3289 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3290 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3291 put_long_date(pdata,c_time);
3292 put_long_date(pdata+8,sbuf.st_atime);
3293 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3294 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3295 SIVAL(pdata,32,allocation_size);
3296 SOFF_T(pdata,40,file_size);
3297 SIVAL(pdata,48,mode);
3298 SIVAL(pdata,52,0); /* ??? */
3302 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3303 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3304 SIVAL(pdata,0,mode);
3310 * CIFS UNIX Extensions.
3313 case SMB_QUERY_FILE_UNIX_BASIC:
3315 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3316 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3318 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3321 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3324 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3325 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3326 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3329 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3333 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3337 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3340 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3344 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3348 SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3351 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3355 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3358 data_size = PTR_DIFF(pdata,(*ppdata));
3362 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3364 for (i=0; i<100; i++)
3365 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3371 case SMB_QUERY_FILE_UNIX_LINK:
3375 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3377 if(!S_ISLNK(sbuf.st_mode))
3378 return(UNIXERROR(ERRSRV,ERRbadlink));
3380 return(UNIXERROR(ERRDOS,ERRbadlink));
3382 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3384 return(UNIXERROR(ERRDOS,ERRnoaccess));
3386 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3388 data_size = PTR_DIFF(pdata,(*ppdata));
3393 #if defined(HAVE_POSIX_ACLS)
3394 case SMB_QUERY_POSIX_ACL:
3396 SMB_ACL_T file_acl = NULL;
3397 SMB_ACL_T def_acl = NULL;
3398 uint16 num_file_acls = 0;
3399 uint16 num_def_acls = 0;
3401 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3402 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3404 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3407 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3408 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3410 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3413 if (S_ISDIR(sbuf.st_mode)) {
3414 if (fsp && fsp->is_directory) {
3415 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3417 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3419 def_acl = free_empty_sys_acl(conn, def_acl);
3422 num_file_acls = count_acl_entries(conn, file_acl);
3423 num_def_acls = count_acl_entries(conn, def_acl);
3425 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3426 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3428 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3429 SMB_POSIX_ACL_HEADER_SIZE) ));
3431 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3434 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3436 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3439 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3440 SSVAL(pdata,2,num_file_acls);
3441 SSVAL(pdata,4,num_def_acls);
3442 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3444 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3447 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3449 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3451 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3453 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3456 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3458 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3462 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3465 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3467 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3473 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3476 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3481 /****************************************************************************
3482 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3484 ****************************************************************************/
3486 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3488 BOOL bad_path_oldname = False;
3489 BOOL bad_path_newname = False;
3490 SMB_STRUCT_STAT sbuf1, sbuf2;
3491 pstring last_component_oldname;
3492 pstring last_component_newname;
3493 NTSTATUS status = NT_STATUS_OK;
3499 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3500 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3503 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3504 if (bad_path_oldname) {
3505 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3508 /* Quick check for "." and ".." */
3509 if (last_component_oldname[0] == '.') {
3510 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3511 return NT_STATUS_OBJECT_NAME_INVALID;
3515 /* source must already exist. */
3516 if (!VALID_STAT(sbuf1)) {
3517 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3520 if (!check_name(oldname,conn)) {
3521 return NT_STATUS_ACCESS_DENIED;
3524 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3525 if (bad_path_newname) {
3526 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3529 /* Quick check for "." and ".." */
3530 if (last_component_newname[0] == '.') {
3531 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3532 return NT_STATUS_OBJECT_NAME_INVALID;
3536 /* Disallow if newname already exists. */
3537 if (VALID_STAT(sbuf2)) {
3538 return NT_STATUS_OBJECT_NAME_COLLISION;
3541 if (!check_name(newname,conn)) {
3542 return NT_STATUS_ACCESS_DENIED;
3545 /* No links from a directory. */
3546 if (S_ISDIR(sbuf1.st_mode)) {
3547 return NT_STATUS_FILE_IS_A_DIRECTORY;
3550 /* Ensure this is within the share. */
3551 if (!reduce_name(conn, oldname) != 0)
3552 return NT_STATUS_ACCESS_DENIED;
3554 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3556 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3557 status = map_nt_error_from_unix(errno);
3558 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3559 nt_errstr(status), newname, oldname));
3565 /****************************************************************************
3566 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3567 ****************************************************************************/
3569 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3570 unsigned int tran_call,
3571 char **pparams, int total_params, char **ppdata, int total_data,
3572 unsigned int max_data_bytes)
3574 char *params = *pparams;
3575 char *pdata = *ppdata;
3580 SMB_STRUCT_STAT sbuf;
3583 BOOL bad_path = False;
3584 files_struct *fsp = NULL;
3585 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3586 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3587 mode_t unixmode = 0;
3588 NTSTATUS status = NT_STATUS_OK;
3591 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3596 if (tran_call == TRANSACT2_SETFILEINFO) {
3597 if (total_params < 4) {
3598 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3601 fsp = file_fsp(params,0);
3602 info_level = SVAL(params,2);
3604 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3606 * This is actually a SETFILEINFO on a directory
3607 * handle (returned from an NT SMB). NT5.0 seems
3608 * to do this call. JRA.
3610 pstrcpy(fname, fsp->fsp_name);
3611 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3612 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3613 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3615 } else if (fsp && fsp->print_file) {
3617 * Doing a DELETE_ON_CLOSE should cancel a print job.
3619 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3620 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
3622 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3625 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3628 return (UNIXERROR(ERRDOS,ERRbadpath));
3631 * Original code - this is an open file.
3633 CHECK_FSP(fsp,conn);
3635 pstrcpy(fname, fsp->fsp_name);
3638 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3639 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3640 return(UNIXERROR(ERRDOS,ERRbadfid));
3645 if (total_params < 6) {
3646 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3649 info_level = SVAL(params,0);
3650 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
3651 if (!NT_STATUS_IS_OK(status)) {
3652 return ERROR_NT(status);
3654 unix_convert(fname,conn,0,&bad_path,&sbuf);
3656 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3660 * For CIFS UNIX extensions the target name may not exist.
3663 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3664 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3665 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3668 if(!check_name(fname, conn)) {
3669 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3674 if (!CAN_WRITE(conn))
3675 return ERROR_DOS(ERRSRV,ERRaccess);
3677 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3678 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3680 if (VALID_STAT(sbuf))
3681 unixmode = sbuf.st_mode;
3683 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3684 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3686 /* Realloc the parameter size */
3687 *pparams = SMB_REALLOC(*pparams,2);
3688 if (*pparams == NULL) {
3689 return ERROR_NT(NT_STATUS_NO_MEMORY);
3695 if (fsp && fsp->pending_modtime) {
3696 /* the pending modtime overrides the current modtime */
3697 sbuf.st_mtime = fsp->pending_modtime;
3700 size = get_file_size(sbuf);
3701 tvs.modtime = sbuf.st_mtime;
3702 tvs.actime = sbuf.st_atime;
3703 dosmode = dos_mode(conn,fname,&sbuf);
3704 unixmode = sbuf.st_mode;
3706 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3707 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3709 switch (info_level) {
3710 case SMB_INFO_STANDARD:
3712 if (total_data < 12) {
3713 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3717 tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
3719 tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
3723 case SMB_INFO_SET_EA:
3725 struct ea_list *ea_list = NULL;
3726 TALLOC_CTX *ctx = NULL;
3728 if (total_data < 10) {
3730 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3731 length. They seem to have no effect. Bug #3212. JRA */
3733 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3734 /* We're done. We only get EA info in this call. */
3736 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3740 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3743 if (IVAL(pdata,0) > total_data) {
3744 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3745 IVAL(pdata,0), (unsigned int)total_data));
3746 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3749 ctx = talloc_init("SMB_INFO_SET_EA");
3751 return ERROR_NT(NT_STATUS_NO_MEMORY);
3753 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3755 talloc_destroy(ctx);
3756 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3758 status = set_ea(conn, fsp, fname, ea_list);
3759 talloc_destroy(ctx);
3761 if (!NT_STATUS_IS_OK(status)) {
3762 return ERROR_NT(status);
3765 /* We're done. We only get EA info in this call. */
3767 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3772 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3773 /* XXXX um, i don't think this is right.
3774 it's also not in the cifs6.txt spec.
3776 case SMB_INFO_QUERY_EAS_FROM_LIST:
3777 if (total_data < 28)
3778 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3780 tvs.actime = make_unix_date2(pdata+8);
3781 tvs.modtime = make_unix_date2(pdata+12);
3782 size = IVAL(pdata,16);
3783 dosmode = IVAL(pdata,24);
3786 /* XXXX nor this. not in cifs6.txt, either. */
3787 case SMB_INFO_QUERY_ALL_EAS:
3788 if (total_data < 28)
3789 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3791 tvs.actime = make_unix_date2(pdata+8);
3792 tvs.modtime = make_unix_date2(pdata+12);
3793 size = IVAL(pdata,16);
3794 dosmode = IVAL(pdata,24);
3798 case SMB_SET_FILE_BASIC_INFO:
3799 case SMB_FILE_BASIC_INFORMATION:
3801 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3803 time_t changed_time;
3805 if (total_data < 36) {
3806 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3809 /* Ignore create time at offset pdata. */
3812 tvs.actime = interpret_long_date(pdata+8);
3814 write_time = interpret_long_date(pdata+16);
3815 changed_time = interpret_long_date(pdata+24);
3817 tvs.modtime = MIN(write_time, changed_time);
3819 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3820 tvs.modtime = write_time;
3822 /* Prefer a defined time to an undefined one. */
3823 if (null_mtime(tvs.modtime)) {
3824 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3828 dosmode = IVAL(pdata,32);
3832 case SMB_FILE_ALLOCATION_INFORMATION:
3833 case SMB_SET_FILE_ALLOCATION_INFO:
3836 SMB_BIG_UINT allocation_size;
3838 if (total_data < 8) {
3839 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3842 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3843 #ifdef LARGE_SMB_OFF_T
3844 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3845 #else /* LARGE_SMB_OFF_T */
3846 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3847 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3848 #endif /* LARGE_SMB_OFF_T */
3849 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3850 fname, (double)allocation_size ));
3852 if (allocation_size) {
3853 allocation_size = smb_roundup(conn, allocation_size);
3856 if(allocation_size != get_file_size(sbuf)) {
3857 SMB_STRUCT_STAT new_sbuf;
3859 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3860 fname, (double)allocation_size ));
3863 files_struct *new_fsp = NULL;
3865 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
3867 FILE_SHARE_READ|FILE_SHARE_WRITE,
3870 FILE_ATTRIBUTE_NORMAL,
3874 if (new_fsp == NULL) {
3875 return(UNIXERROR(ERRDOS,ERRbadpath));
3877 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3878 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
3879 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3880 new_fsp->fnum, strerror(errno)));
3883 close_file(new_fsp,NORMAL_CLOSE);
3885 ret = vfs_allocate_file_space(fsp, allocation_size);
3886 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3887 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3888 fsp->fnum, strerror(errno)));
3893 return ERROR_NT(NT_STATUS_DISK_FULL);
3895 /* Allocate can truncate size... */
3896 size = get_file_size(new_sbuf);
3902 case SMB_FILE_END_OF_FILE_INFORMATION:
3903 case SMB_SET_FILE_END_OF_FILE_INFO:
3905 if (total_data < 8) {
3906 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3909 size = IVAL(pdata,0);
3910 #ifdef LARGE_SMB_OFF_T
3911 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3912 #else /* LARGE_SMB_OFF_T */
3913 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3914 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3915 #endif /* LARGE_SMB_OFF_T */
3916 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3920 case SMB_FILE_DISPOSITION_INFORMATION:
3921 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3923 BOOL delete_on_close;
3925 if (total_data < 1) {
3926 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3929 delete_on_close = (CVAL(pdata,0) ? True : False);
3931 /* Just ignore this set on a path. */
3932 if (tran_call != TRANSACT2_SETFILEINFO)
3936 return(UNIXERROR(ERRDOS,ERRbadfid));
3938 status = can_set_delete_on_close(fsp, delete_on_close,
3941 if (!NT_STATUS_IS_OK(status)) {
3942 return ERROR_NT(status);
3945 /* The set is across all open files on this dev/inode pair. */
3946 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
3947 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3951 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3955 case SMB_FILE_POSITION_INFORMATION:
3957 SMB_BIG_UINT position_information;
3959 if (total_data < 8) {
3960 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3963 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3964 #ifdef LARGE_SMB_OFF_T
3965 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3966 #else /* LARGE_SMB_OFF_T */
3967 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3968 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3969 #endif /* LARGE_SMB_OFF_T */
3970 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3971 fname, (double)position_information ));
3973 fsp->fh->position_information = position_information;
3976 /* We're done. We only get position info in this call. */
3978 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3982 /* From tridge Samba4 :
3983 * MODE_INFORMATION in setfileinfo (I have no
3984 * idea what "mode information" on a file is - it takes a value of 0,
3985 * 2, 4 or 6. What could it be?).
3988 case SMB_FILE_MODE_INFORMATION:
3992 if (total_data < 4) {
3993 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3995 mode = IVAL(pdata,0);
3996 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
3997 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4000 /* We're done. We only get mode info in this call. */
4002 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4007 * CIFS UNIX extensions.
4010 case SMB_SET_FILE_UNIX_BASIC:
4012 uint32 raw_unixmode;
4014 if (total_data < 100) {
4015 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4018 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4019 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4020 size=IVAL(pdata,0); /* first 8 Bytes are size */
4021 #ifdef LARGE_SMB_OFF_T
4022 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4023 #else /* LARGE_SMB_OFF_T */
4024 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
4025 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4026 #endif /* LARGE_SMB_OFF_T */
4028 pdata+=24; /* ctime & st_blocks are not changed */
4029 tvs.actime = interpret_long_date(pdata); /* access_time */
4030 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
4032 set_owner = (uid_t)IVAL(pdata,0);
4034 set_grp = (gid_t)IVAL(pdata,0);
4036 raw_unixmode = IVAL(pdata,28);
4037 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4038 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4040 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4041 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4042 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4044 if (!VALID_STAT(sbuf)) {
4047 * The only valid use of this is to create character and block
4048 * devices, and named pipes. This is deprecated (IMHO) and
4049 * a new info level should be used for mknod. JRA.
4052 uint32 file_type = IVAL(pdata,0);
4053 #if defined(HAVE_MAKEDEV)
4054 uint32 dev_major = IVAL(pdata,4);
4055 uint32 dev_minor = IVAL(pdata,12);
4058 uid_t myuid = geteuid();
4059 gid_t mygid = getegid();
4060 SMB_DEV_T dev = (SMB_DEV_T)0;
4062 if (tran_call == TRANSACT2_SETFILEINFO)
4063 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4065 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4066 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4069 #if defined(HAVE_MAKEDEV)
4070 dev = makedev(dev_major, dev_minor);
4073 /* We can only create as the owner/group we are. */
4075 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4076 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4077 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4078 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4080 switch (file_type) {
4081 #if defined(S_IFIFO)
4082 case UNIX_TYPE_FIFO:
4083 unixmode |= S_IFIFO;
4086 #if defined(S_IFSOCK)
4087 case UNIX_TYPE_SOCKET:
4088 unixmode |= S_IFSOCK;
4091 #if defined(S_IFCHR)
4092 case UNIX_TYPE_CHARDEV:
4093 unixmode |= S_IFCHR;
4096 #if defined(S_IFBLK)
4097 case UNIX_TYPE_BLKDEV:
4098 unixmode |= S_IFBLK;
4102 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4105 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4106 0%o for file %s\n", (double)dev, unixmode, fname ));
4108 /* Ok - do the mknod. */
4109 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4110 return(UNIXERROR(ERRDOS,ERRnoaccess));
4112 inherit_access_acl(conn, fname, unixmode);
4115 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4120 * Deal with the UNIX specific mode set.
4123 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4124 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4125 (unsigned int)unixmode, fname ));
4126 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4127 return(UNIXERROR(ERRDOS,ERRnoaccess));
4131 * Deal with the UNIX specific uid set.
4134 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4135 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4136 (unsigned int)set_owner, fname ));
4137 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4138 return(UNIXERROR(ERRDOS,ERRnoaccess));
4142 * Deal with the UNIX specific gid set.
4145 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4146 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4147 (unsigned int)set_owner, fname ));
4148 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4149 return(UNIXERROR(ERRDOS,ERRnoaccess));
4154 case SMB_SET_FILE_UNIX_LINK:
4156 pstring link_target;
4157 char *newname = fname;
4159 /* Set a symbolic link. */
4160 /* Don't allow this if follow links is false. */
4162 if (!lp_symlinks(SNUM(conn)))
4163 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4165 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4167 /* !widelinks forces the target path to be within the share. */
4168 /* This means we can interpret the target as a pathname. */
4169 if (!lp_widelinks(SNUM(conn))) {
4171 char *last_dirp = NULL;
4173 unix_format(link_target);
4174 if (*link_target == '/') {
4175 /* No absolute paths allowed. */
4176 return(UNIXERROR(ERRDOS,ERRnoaccess));
4178 pstrcpy(rel_name, newname);
4179 last_dirp = strrchr_m(rel_name, '/');
4181 last_dirp[1] = '\0';
4183 pstrcpy(rel_name, "./");
4185 pstrcat(rel_name, link_target);
4187 if (!check_name(rel_name, conn)) {
4188 return(UNIXERROR(ERRDOS,ERRnoaccess));
4192 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4193 fname, link_target ));
4195 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4196 return(UNIXERROR(ERRDOS,ERRnoaccess));
4198 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4202 case SMB_SET_FILE_UNIX_HLINK:
4205 char *newname = fname;
4207 /* Set a hard link. */
4208 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
4209 if (!NT_STATUS_IS_OK(status)) {
4210 return ERROR_NT(status);
4213 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4216 status = hardlink_internals(conn, oldname, newname);
4217 if (!NT_STATUS_IS_OK(status)) {
4218 return ERROR_NT(status);
4222 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4226 case SMB_FILE_RENAME_INFORMATION:
4235 if (total_data < 12) {
4236 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4239 overwrite = (CVAL(pdata,0) ? True : False);
4240 root_fid = IVAL(pdata,4);
4241 len = IVAL(pdata,8);
4242 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
4243 if (!NT_STATUS_IS_OK(status)) {
4244 return ERROR_NT(status);
4247 /* Check the new name has no '/' characters. */
4248 if (strchr_m(newname, '/'))
4249 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4251 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4253 /* Create the base directory. */
4254 pstrcpy(base_name, fname);
4255 p = strrchr_m(base_name, '/');
4258 /* Append the new name. */
4259 pstrcat(base_name, "/");
4260 pstrcat(base_name, newname);
4263 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4264 fsp->fnum, fsp->fsp_name, base_name ));
4265 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4267 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4269 status = rename_internals(conn, fname, base_name, 0, overwrite, False);
4271 if (!NT_STATUS_IS_OK(status)) {
4272 return ERROR_NT(status);
4274 process_pending_change_notify_queue((time_t)0);
4276 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4280 #if defined(HAVE_POSIX_ACLS)
4281 case SMB_SET_POSIX_ACL:
4283 uint16 posix_acl_version;
4284 uint16 num_file_acls;
4285 uint16 num_def_acls;
4286 BOOL valid_file_acls = True;
4287 BOOL valid_def_acls = True;
4289 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4290 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4292 posix_acl_version = SVAL(pdata,0);
4293 num_file_acls = SVAL(pdata,2);
4294 num_def_acls = SVAL(pdata,4);
4296 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4297 valid_file_acls = False;
4301 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4302 valid_def_acls = False;
4306 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4307 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4310 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4311 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4312 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4315 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4316 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4317 return(UNIXERROR(ERRDOS,ERRnoaccess));
4320 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4321 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4322 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4323 return(UNIXERROR(ERRDOS,ERRnoaccess));
4327 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4333 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4336 /* get some defaults (no modifications) if any info is zero or -1. */
4337 if (null_mtime(tvs.actime)) {
4338 tvs.actime = sbuf.st_atime;
4341 if (null_mtime(tvs.modtime)) {
4342 tvs.modtime = sbuf.st_mtime;
4345 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4346 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4347 DEBUG(6,("size: %.0f ", (double)size));
4350 if (S_ISDIR(sbuf.st_mode))
4356 DEBUG(6,("dosmode: %x\n" , dosmode));
4358 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4359 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4360 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4361 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4364 * Only do this test if we are not explicitly
4365 * changing the size of a file.
4368 size = get_file_size(sbuf);
4372 * Try and set the times, size and mode of this file -
4373 * if they are different from the current values
4376 /* check the mode isn't different, before changing it */
4377 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4379 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4381 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4382 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4383 return(UNIXERROR(ERRDOS,ERRnoaccess));
4388 if (size != get_file_size(sbuf)) {
4392 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4393 fname, (double)size ));
4396 files_struct *new_fsp = NULL;
4398 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
4400 FILE_SHARE_READ|FILE_SHARE_WRITE,
4403 FILE_ATTRIBUTE_NORMAL,
4407 if (new_fsp == NULL) {
4408 return(UNIXERROR(ERRDOS,ERRbadpath));
4410 ret = vfs_set_filelen(new_fsp, size);
4411 close_file(new_fsp,NORMAL_CLOSE);
4413 ret = vfs_set_filelen(fsp, size);
4417 return (UNIXERROR(ERRHRD,ERRdiskfull));
4422 * Finally the times.
4424 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4427 * This was a setfileinfo on an open file.
4428 * NT does this a lot. We also need to
4429 * set the time here, as it can be read by
4430 * FindFirst/FindNext and with the patch for bug #2045
4431 * in smbd/fileio.c it ensures that this timestamp is
4432 * kept sticky even after a write. We save the request
4433 * away and will set it on file close and after a write. JRA.
4436 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4437 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4438 fsp_set_pending_modtime(fsp, tvs.modtime);
4442 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4444 if(file_utime(conn, fname, &tvs)!=0) {
4445 return(UNIXERROR(ERRDOS,ERRnoaccess));
4450 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4455 /****************************************************************************
4456 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4457 ****************************************************************************/
4459 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4460 char **pparams, int total_params, char **ppdata, int total_data,
4461 unsigned int max_data_bytes)
4463 char *params = *pparams;
4464 char *pdata = *ppdata;
4467 SMB_STRUCT_STAT sbuf;
4468 BOOL bad_path = False;
4469 NTSTATUS status = NT_STATUS_OK;
4470 TALLOC_CTX *ctx = NULL;
4471 struct ea_list *ea_list = NULL;
4473 if (!CAN_WRITE(conn))
4474 return ERROR_DOS(ERRSRV,ERRaccess);
4476 if (total_params < 4) {
4477 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4480 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status);
4481 if (!NT_STATUS_IS_OK(status)) {
4482 return ERROR_NT(status);
4485 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4487 unix_convert(directory,conn,0,&bad_path,&sbuf);
4489 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4492 /* Any data in this call is an EA list. */
4493 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
4494 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4498 * OS/2 workplace shell seems to send SET_EA requests of "null"
4499 * length (4 bytes containing IVAL 4).
4500 * They seem to have no effect. Bug #3212. JRA.
4503 if (total_data != 4) {
4504 if (total_data < 10) {
4505 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4508 if (IVAL(pdata,0) > total_data) {
4509 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4510 IVAL(pdata,0), (unsigned int)total_data));
4511 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4514 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4516 return ERROR_NT(NT_STATUS_NO_MEMORY);
4518 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4520 talloc_destroy(ctx);
4521 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4523 } else if (IVAL(pdata,0) != 4) {
4524 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4527 if (check_name(directory,conn)) {
4528 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4532 talloc_destroy(ctx);
4533 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4534 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4537 /* Try and set any given EA. */
4539 status = set_ea(conn, NULL, directory, ea_list);
4540 talloc_destroy(ctx);
4541 if (!NT_STATUS_IS_OK(status)) {
4542 return ERROR_NT(status);
4546 /* Realloc the parameter and data sizes */
4547 *pparams = SMB_REALLOC(*pparams,2);
4548 if(*pparams == NULL) {
4549 return ERROR_NT(NT_STATUS_NO_MEMORY);
4555 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4560 /****************************************************************************
4561 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4562 We don't actually do this - we just send a null response.
4563 ****************************************************************************/
4565 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4566 char **pparams, int total_params, char **ppdata, int total_data,
4567 unsigned int max_data_bytes)
4569 static uint16 fnf_handle = 257;
4570 char *params = *pparams;
4573 if (total_params < 6) {
4574 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4577 info_level = SVAL(params,4);
4578 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4580 switch (info_level) {
4585 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4588 /* Realloc the parameter and data sizes */
4589 *pparams = SMB_REALLOC(*pparams,6);
4590 if (*pparams == NULL) {
4591 return ERROR_NT(NT_STATUS_NO_MEMORY);
4595 SSVAL(params,0,fnf_handle);
4596 SSVAL(params,2,0); /* No changes */
4597 SSVAL(params,4,0); /* No EA errors */
4604 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4609 /****************************************************************************
4610 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4611 changes). Currently this does nothing.
4612 ****************************************************************************/
4614 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4615 char **pparams, int total_params, char **ppdata, int total_data,
4616 unsigned int max_data_bytes)
4618 char *params = *pparams;
4620 DEBUG(3,("call_trans2findnotifynext\n"));
4622 /* Realloc the parameter and data sizes */
4623 *pparams = SMB_REALLOC(*pparams,4);
4624 if (*pparams == NULL) {
4625 return ERROR_NT(NT_STATUS_NO_MEMORY);
4629 SSVAL(params,0,0); /* No changes */
4630 SSVAL(params,2,0); /* No EA errors */
4632 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4637 /****************************************************************************
4638 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4639 ****************************************************************************/
4641 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4642 char **pparams, int total_params, char **ppdata, int total_data,
4643 unsigned int max_data_bytes)
4645 char *params = *pparams;
4648 int max_referral_level;
4650 DEBUG(10,("call_trans2getdfsreferral\n"));
4652 if (total_params < 2) {
4653 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4656 max_referral_level = SVAL(params,0);
4658 if(!lp_host_msdfs())
4659 return ERROR_DOS(ERRDOS,ERRbadfunc);
4661 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4662 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4663 return UNIXERROR(ERRDOS,ERRbadfile);
4665 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4666 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4671 #define LMCAT_SPL 0x53
4672 #define LMFUNC_GETJOBID 0x60
4674 /****************************************************************************
4675 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4676 ****************************************************************************/
4678 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4679 char **pparams, int total_params, char **ppdata, int total_data,
4680 unsigned int max_data_bytes)
4682 char *pdata = *ppdata;
4683 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4685 /* check for an invalid fid before proceeding */
4688 return(ERROR_DOS(ERRDOS,ERRbadfid));
4690 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4691 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4692 *ppdata = SMB_REALLOC(*ppdata, 32);
4693 if (*ppdata == NULL) {
4694 return ERROR_NT(NT_STATUS_NO_MEMORY);
4698 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4699 CAN ACCEPT THIS IN UNICODE. JRA. */
4701 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4702 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4703 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4704 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4707 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4708 return ERROR_DOS(ERRSRV,ERRerror);
4712 /****************************************************************************
4713 Reply to a SMBfindclose (stop trans2 directory search).
4714 ****************************************************************************/
4716 int reply_findclose(connection_struct *conn,
4717 char *inbuf,char *outbuf,int length,int bufsize)
4720 int dptr_num=SVALS(inbuf,smb_vwv0);
4721 START_PROFILE(SMBfindclose);
4723 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4725 dptr_close(&dptr_num);
4727 outsize = set_message(outbuf,0,0,True);
4729 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4731 END_PROFILE(SMBfindclose);
4735 /****************************************************************************
4736 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4737 ****************************************************************************/
4739 int reply_findnclose(connection_struct *conn,
4740 char *inbuf,char *outbuf,int length,int bufsize)
4744 START_PROFILE(SMBfindnclose);
4746 dptr_num = SVAL(inbuf,smb_vwv0);
4748 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4750 /* We never give out valid handles for a
4751 findnotifyfirst - so any dptr_num is ok here.
4754 outsize = set_message(outbuf,0,0,True);
4756 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4758 END_PROFILE(SMBfindnclose);
4762 /****************************************************************************
4763 Reply to a SMBtranss2 - just ignore it!
4764 ****************************************************************************/
4766 int reply_transs2(connection_struct *conn,
4767 char *inbuf,char *outbuf,int length,int bufsize)
4769 START_PROFILE(SMBtranss2);
4770 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4771 END_PROFILE(SMBtranss2);
4775 /****************************************************************************
4776 Reply to a SMBtrans2.
4777 ****************************************************************************/
4779 int reply_trans2(connection_struct *conn,
4780 char *inbuf,char *outbuf,int length,int bufsize)
4783 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4784 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4785 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4787 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4788 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4789 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4790 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4791 int32 timeout = IVALS(inbuf,smb_timeout);
4793 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4794 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4795 char *params = NULL, *data = NULL;
4796 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4797 START_PROFILE(SMBtrans2);
4799 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4800 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4801 END_PROFILE(SMBtrans2);
4802 return ERROR_DOS(ERRSRV,ERRaccess);
4805 outsize = set_message(outbuf,0,0,True);
4807 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4808 is so as a sanity check */
4811 * Need to have rc=0 for ioctl to get job id for OS/2.
4812 * Network printing will fail if function is not successful.
4813 * Similar function in reply.c will be used if protocol
4814 * is LANMAN1.0 instead of LM1.2X002.
4815 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4816 * outbuf doesn't have to be set(only job id is used).
4818 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4819 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4820 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4821 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4823 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4824 DEBUG(2,("Transaction is %d\n",tran_call));
4825 END_PROFILE(SMBtrans2);
4826 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4830 /* Allocate the space for the maximum needed parameters and data */
4831 if (total_params > 0)
4832 params = (char *)SMB_MALLOC(total_params);
4834 data = (char *)SMB_MALLOC(total_data);
4836 if ((total_params && !params) || (total_data && !data)) {
4837 DEBUG(2,("Out of memory in reply_trans2\n"));
4840 END_PROFILE(SMBtrans2);
4841 return ERROR_NT(NT_STATUS_NO_MEMORY);
4844 /* Copy the param and data bytes sent with this request into
4845 the params buffer */
4846 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4847 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4849 if (num_params > total_params || num_data > total_data)
4850 exit_server("invalid params in reply_trans2");
4853 unsigned int psoff = SVAL(inbuf, smb_psoff);
4854 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4856 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4857 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4859 memcpy( params, smb_base(inbuf) + psoff, num_params);
4862 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4863 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4865 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4866 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4868 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4871 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4873 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4874 /* We need to send an interim response then receive the rest
4875 of the parameter/data bytes */
4876 outsize = set_message(outbuf,0,0,True);
4877 srv_signing_trans_stop();
4879 if (!send_smb(smbd_server_fd(),outbuf))
4880 exit_server("reply_trans2: send_smb failed.");
4882 while (num_data_sofar < total_data ||
4883 num_params_sofar < total_params) {
4885 unsigned int param_disp;
4886 unsigned int param_off;
4887 unsigned int data_disp;
4888 unsigned int data_off;
4890 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4892 /* We need to re-calcuate the new length after we've read the secondary packet. */
4893 length = smb_len(inbuf) + 4;
4896 * The sequence number for the trans reply is always
4897 * based on the last secondary received.
4900 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4903 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4904 outsize = set_message(outbuf,0,0,True);
4906 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4908 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4909 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4913 /* Revise total_params and total_data in case
4914 they have changed downwards */
4915 if (SVAL(inbuf, smb_tpscnt) < total_params)
4916 total_params = SVAL(inbuf, smb_tpscnt);
4917 if (SVAL(inbuf, smb_tdscnt) < total_data)
4918 total_data = SVAL(inbuf, smb_tdscnt);
4920 num_params = SVAL(inbuf,smb_spscnt);
4921 param_off = SVAL(inbuf, smb_spsoff);
4922 param_disp = SVAL(inbuf, smb_spsdisp);
4923 num_params_sofar += num_params;
4925 num_data = SVAL(inbuf, smb_sdscnt);
4926 data_off = SVAL(inbuf, smb_sdsoff);
4927 data_disp = SVAL(inbuf, smb_sdsdisp);
4928 num_data_sofar += num_data;
4930 if (num_params_sofar > total_params || num_data_sofar > total_data)
4934 if (param_disp + num_params > total_params)
4936 if ((param_disp + num_params < param_disp) ||
4937 (param_disp + num_params < num_params))
4939 if (param_disp > total_params)
4941 if ((smb_base(inbuf) + param_off + num_params > inbuf + length) ||
4942 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4944 if (params + param_disp < params)
4947 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
4950 if (data_disp + num_data > total_data)
4952 if ((data_disp + num_data < data_disp) ||
4953 (data_disp + num_data < num_data))
4955 if (data_disp > total_data)
4957 if ((smb_base(inbuf) + data_off + num_data > inbuf + length) ||
4958 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4960 if (data + data_disp < data)
4963 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4968 if (Protocol >= PROTOCOL_NT1) {
4969 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4972 /* Now we must call the relevant TRANS2 function */
4974 case TRANSACT2_OPEN:
4975 START_PROFILE_NESTED(Trans2_open);
4976 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4977 ¶ms, total_params, &data, total_data, max_data_bytes);
4978 END_PROFILE_NESTED(Trans2_open);
4981 case TRANSACT2_FINDFIRST:
4982 START_PROFILE_NESTED(Trans2_findfirst);
4983 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4984 ¶ms, total_params, &data, total_data, max_data_bytes);
4985 END_PROFILE_NESTED(Trans2_findfirst);
4988 case TRANSACT2_FINDNEXT:
4989 START_PROFILE_NESTED(Trans2_findnext);
4990 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4991 ¶ms, total_params, &data, total_data, max_data_bytes);
4992 END_PROFILE_NESTED(Trans2_findnext);
4995 case TRANSACT2_QFSINFO:
4996 START_PROFILE_NESTED(Trans2_qfsinfo);
4997 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4998 ¶ms, total_params, &data, total_data, max_data_bytes);
4999 END_PROFILE_NESTED(Trans2_qfsinfo);
5002 case TRANSACT2_SETFSINFO:
5003 START_PROFILE_NESTED(Trans2_setfsinfo);
5004 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
5005 ¶ms, total_params, &data, total_data, max_data_bytes);
5006 END_PROFILE_NESTED(Trans2_setfsinfo);
5009 case TRANSACT2_QPATHINFO:
5010 case TRANSACT2_QFILEINFO:
5011 START_PROFILE_NESTED(Trans2_qpathinfo);
5012 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5013 ¶ms, total_params, &data, total_data, max_data_bytes);
5014 END_PROFILE_NESTED(Trans2_qpathinfo);
5016 case TRANSACT2_SETPATHINFO:
5017 case TRANSACT2_SETFILEINFO:
5018 START_PROFILE_NESTED(Trans2_setpathinfo);
5019 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5020 ¶ms, total_params, &data, total_data, max_data_bytes);
5021 END_PROFILE_NESTED(Trans2_setpathinfo);
5024 case TRANSACT2_FINDNOTIFYFIRST:
5025 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5026 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
5027 ¶ms, total_params, &data, total_data, max_data_bytes);
5028 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5031 case TRANSACT2_FINDNOTIFYNEXT:
5032 START_PROFILE_NESTED(Trans2_findnotifynext);
5033 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
5034 ¶ms, total_params, &data, total_data, max_data_bytes);
5035 END_PROFILE_NESTED(Trans2_findnotifynext);
5037 case TRANSACT2_MKDIR:
5038 START_PROFILE_NESTED(Trans2_mkdir);
5039 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
5040 ¶ms, total_params, &data, total_data, max_data_bytes);
5041 END_PROFILE_NESTED(Trans2_mkdir);
5044 case TRANSACT2_GET_DFS_REFERRAL:
5045 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5046 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
5047 ¶ms, total_params, &data, total_data, max_data_bytes);
5048 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5050 case TRANSACT2_IOCTL:
5051 START_PROFILE_NESTED(Trans2_ioctl);
5052 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
5053 ¶ms, total_params, &data, total_data, max_data_bytes);
5054 END_PROFILE_NESTED(Trans2_ioctl);
5057 /* Error in request */
5058 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
5061 END_PROFILE(SMBtrans2);
5062 srv_signing_trans_stop();
5063 return ERROR_DOS(ERRSRV,ERRerror);
5066 /* As we do not know how many data packets will need to be
5067 returned here the various call_trans2xxxx calls
5068 must send their own. Thus a call_trans2xxx routine only
5069 returns a value other than -1 when it wants to send
5073 srv_signing_trans_stop();
5077 END_PROFILE(SMBtrans2);
5078 return outsize; /* If a correct response was needed the
5079 call_trans2xxx calls have already sent
5080 it. If outsize != -1 then it is returning */
5084 srv_signing_trans_stop();
5087 END_PROFILE(SMBtrans2);
5088 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);