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));
1169 mangle_map(fname,False,True,SNUM(conn));
1174 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1176 switch (info_level) {
1177 case SMB_FIND_INFO_STANDARD:
1178 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1179 if(requires_resume_key) {
1183 srv_put_dos_date2(p,0,cdate);
1184 srv_put_dos_date2(p,4,adate);
1185 srv_put_dos_date2(p,8,mdate);
1186 SIVAL(p,12,(uint32)file_size);
1187 SIVAL(p,16,(uint32)allocation_size);
1191 p += align_string(outbuf, p, 0);
1192 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1193 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1195 SCVAL(nameptr, -1, len - 2);
1197 SCVAL(nameptr, -1, 0);
1201 SCVAL(nameptr, -1, len - 1);
1203 SCVAL(nameptr, -1, 0);
1209 case SMB_FIND_EA_SIZE:
1210 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1211 if(requires_resume_key) {
1215 srv_put_dos_date2(p,0,cdate);
1216 srv_put_dos_date2(p,4,adate);
1217 srv_put_dos_date2(p,8,mdate);
1218 SIVAL(p,12,(uint32)file_size);
1219 SIVAL(p,16,(uint32)allocation_size);
1222 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1223 SIVAL(p,22,ea_size); /* Extended attributes */
1227 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1228 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1241 SCVAL(nameptr,0,len);
1243 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1246 case SMB_FIND_EA_LIST:
1248 struct ea_list *file_list = NULL;
1251 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1255 if(requires_resume_key) {
1259 srv_put_dos_date2(p,0,cdate);
1260 srv_put_dos_date2(p,4,adate);
1261 srv_put_dos_date2(p,8,mdate);
1262 SIVAL(p,12,(uint32)file_size);
1263 SIVAL(p,16,(uint32)allocation_size);
1265 p += 22; /* p now points to the EA area. */
1267 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1268 name_list = ea_list_union(name_list, file_list, &ea_len);
1270 /* We need to determine if this entry will fit in the space available. */
1271 /* Max string size is 255 bytes. */
1272 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1273 /* Move the dirptr back to prev_dirpos */
1274 dptr_SeekDir(conn->dirptr, prev_dirpos);
1275 *out_of_space = True;
1276 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1277 return False; /* Not finished - just out of space */
1280 /* Push the ea_data followed by the name. */
1281 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1283 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1284 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1297 SCVAL(nameptr,0,len);
1299 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1303 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1304 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1305 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1307 SIVAL(p,0,reskey); p += 4;
1308 put_long_date(p,cdate); p += 8;
1309 put_long_date(p,adate); p += 8;
1310 put_long_date(p,mdate); p += 8;
1311 put_long_date(p,mdate); p += 8;
1312 SOFF_T(p,0,file_size); p += 8;
1313 SOFF_T(p,0,allocation_size); p += 8;
1314 SIVAL(p,0,nt_extmode); p += 4;
1315 q = p; p += 4; /* q is placeholder for name length. */
1317 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1318 SIVAL(p,0,ea_size); /* Extended attributes */
1321 /* Clear the short name buffer. This is
1322 * IMPORTANT as not doing so will trigger
1323 * a Win2k client bug. JRA.
1325 if (!was_8_3 && check_mangled_names) {
1326 pstring mangled_name;
1327 pstrcpy(mangled_name, fname);
1328 mangle_map(mangled_name,True,True,SNUM(conn));
1329 mangled_name[12] = 0;
1330 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1332 memset(p + 2 + len,'\0',24 - len);
1339 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1342 SIVAL(p,0,0); /* Ensure any padding is null. */
1343 len = PTR_DIFF(p, pdata);
1344 len = (len + 3) & ~3;
1349 case SMB_FIND_FILE_DIRECTORY_INFO:
1350 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1352 SIVAL(p,0,reskey); p += 4;
1353 put_long_date(p,cdate); p += 8;
1354 put_long_date(p,adate); p += 8;
1355 put_long_date(p,mdate); p += 8;
1356 put_long_date(p,mdate); p += 8;
1357 SOFF_T(p,0,file_size); p += 8;
1358 SOFF_T(p,0,allocation_size); p += 8;
1359 SIVAL(p,0,nt_extmode); p += 4;
1360 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1363 SIVAL(p,0,0); /* Ensure any padding is null. */
1364 len = PTR_DIFF(p, pdata);
1365 len = (len + 3) & ~3;
1370 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1371 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1373 SIVAL(p,0,reskey); p += 4;
1374 put_long_date(p,cdate); p += 8;
1375 put_long_date(p,adate); p += 8;
1376 put_long_date(p,mdate); p += 8;
1377 put_long_date(p,mdate); p += 8;
1378 SOFF_T(p,0,file_size); p += 8;
1379 SOFF_T(p,0,allocation_size); p += 8;
1380 SIVAL(p,0,nt_extmode); p += 4;
1381 q = p; p += 4; /* q is placeholder for name length. */
1383 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1384 SIVAL(p,0,ea_size); /* Extended attributes */
1387 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1391 SIVAL(p,0,0); /* Ensure any padding is null. */
1392 len = PTR_DIFF(p, pdata);
1393 len = (len + 3) & ~3;
1398 case SMB_FIND_FILE_NAMES_INFO:
1399 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1401 SIVAL(p,0,reskey); p += 4;
1403 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1404 acl on a dir (tridge) */
1405 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1408 SIVAL(p,0,0); /* Ensure any padding is null. */
1409 len = PTR_DIFF(p, pdata);
1410 len = (len + 3) & ~3;
1415 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1416 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1418 SIVAL(p,0,reskey); p += 4;
1419 put_long_date(p,cdate); p += 8;
1420 put_long_date(p,adate); p += 8;
1421 put_long_date(p,mdate); p += 8;
1422 put_long_date(p,mdate); p += 8;
1423 SOFF_T(p,0,file_size); p += 8;
1424 SOFF_T(p,0,allocation_size); p += 8;
1425 SIVAL(p,0,nt_extmode); p += 4;
1426 q = p; p += 4; /* q is placeholder for name length. */
1428 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1429 SIVAL(p,0,ea_size); /* Extended attributes */
1432 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1433 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1434 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1435 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1438 SIVAL(p,0,0); /* Ensure any padding is null. */
1439 len = PTR_DIFF(p, pdata);
1440 len = (len + 3) & ~3;
1445 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1446 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1447 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1449 SIVAL(p,0,reskey); p += 4;
1450 put_long_date(p,cdate); p += 8;
1451 put_long_date(p,adate); p += 8;
1452 put_long_date(p,mdate); p += 8;
1453 put_long_date(p,mdate); p += 8;
1454 SOFF_T(p,0,file_size); p += 8;
1455 SOFF_T(p,0,allocation_size); p += 8;
1456 SIVAL(p,0,nt_extmode); p += 4;
1457 q = p; p += 4; /* q is placeholder for name length */
1459 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1460 SIVAL(p,0,ea_size); /* Extended attributes */
1463 /* Clear the short name buffer. This is
1464 * IMPORTANT as not doing so will trigger
1465 * a Win2k client bug. JRA.
1467 if (!was_8_3 && check_mangled_names) {
1468 pstring mangled_name;
1469 pstrcpy(mangled_name, fname);
1470 mangle_map(mangled_name,True,True,SNUM(conn));
1471 mangled_name[12] = 0;
1472 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1475 memset(p + 2 + len,'\0',24 - len);
1482 SSVAL(p,0,0); p += 2; /* Reserved ? */
1483 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1484 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1485 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1488 SIVAL(p,0,0); /* Ensure any padding is null. */
1489 len = PTR_DIFF(p, pdata);
1490 len = (len + 3) & ~3;
1495 /* CIFS UNIX Extension. */
1497 case SMB_FIND_FILE_UNIX:
1498 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1500 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1502 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1503 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1506 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1509 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1510 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1511 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1514 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1518 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1522 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1525 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1529 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1533 SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1536 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1540 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1544 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1546 SIVAL(p,0,0); /* Ensure any padding is null. */
1548 len = PTR_DIFF(p, pdata);
1549 len = (len + 3) & ~3;
1550 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1552 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1561 if (PTR_DIFF(p,pdata) > space_remaining) {
1562 /* Move the dirptr back to prev_dirpos */
1563 dptr_SeekDir(conn->dirptr, prev_dirpos);
1564 *out_of_space = True;
1565 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1566 return False; /* Not finished - just out of space */
1569 /* Setup the last entry pointer, as an offset from base_data */
1570 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1571 /* Advance the data pointer to the next slot */
1577 /****************************************************************************
1578 Reply to a TRANS2_FINDFIRST.
1579 ****************************************************************************/
1581 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1582 char **pparams, int total_params, char **ppdata, int total_data,
1583 unsigned int max_data_bytes)
1585 /* We must be careful here that we don't return more than the
1586 allowed number of data bytes. If this means returning fewer than
1587 maxentries then so be it. We assume that the redirector has
1588 enough room for the fixed number of parameter bytes it has
1590 char *params = *pparams;
1591 char *pdata = *ppdata;
1592 uint32 dirtype = SVAL(params,0);
1593 int maxentries = SVAL(params,2);
1594 uint16 findfirst_flags = SVAL(params,4);
1595 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1596 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1597 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1598 int info_level = SVAL(params,6);
1602 int last_entry_off=0;
1606 BOOL finished = False;
1607 BOOL dont_descend = False;
1608 BOOL out_of_space = False;
1609 int space_remaining;
1610 BOOL bad_path = False;
1611 BOOL mask_contains_wcard = False;
1612 SMB_STRUCT_STAT sbuf;
1613 TALLOC_CTX *ea_ctx = NULL;
1614 struct ea_list *ea_list = NULL;
1615 NTSTATUS ntstatus = NT_STATUS_OK;
1617 if (total_params < 12) {
1618 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1621 *directory = *mask = 0;
1623 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1624 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1625 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1626 info_level, max_data_bytes));
1629 /* W2K3 seems to treat zero as 1. */
1633 switch (info_level) {
1634 case SMB_FIND_INFO_STANDARD:
1635 case SMB_FIND_EA_SIZE:
1636 case SMB_FIND_EA_LIST:
1637 case SMB_FIND_FILE_DIRECTORY_INFO:
1638 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1639 case SMB_FIND_FILE_NAMES_INFO:
1640 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1641 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1642 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1644 case SMB_FIND_FILE_UNIX:
1645 if (!lp_unix_extensions())
1646 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1649 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1652 srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1653 if (!NT_STATUS_IS_OK(ntstatus)) {
1654 return ERROR_NT(ntstatus);
1657 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1659 unix_convert(directory,conn,0,&bad_path,&sbuf);
1661 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1663 if(!check_name(directory,conn)) {
1664 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1667 p = strrchr_m(directory,'/');
1669 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1670 if((directory[0] == '.') && (directory[1] == '\0')) {
1672 mask_contains_wcard = True;
1674 pstrcpy(mask,directory);
1676 pstrcpy(directory,"./");
1682 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1684 if (info_level == SMB_FIND_EA_LIST) {
1687 if (total_data < 4) {
1688 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1691 ea_size = IVAL(pdata,0);
1692 if (ea_size != total_data) {
1693 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1694 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1695 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1698 if (!lp_ea_support(SNUM(conn))) {
1699 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1702 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1703 return ERROR_NT(NT_STATUS_NO_MEMORY);
1706 /* Pull out the list of names. */
1707 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1709 talloc_destroy(ea_ctx);
1710 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1714 *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1715 if(*ppdata == NULL ) {
1716 talloc_destroy(ea_ctx);
1717 return ERROR_NT(NT_STATUS_NO_MEMORY);
1721 /* Realloc the params space */
1722 *pparams = SMB_REALLOC(*pparams, 10);
1723 if (*pparams == NULL) {
1724 talloc_destroy(ea_ctx);
1725 return ERROR_NT(NT_STATUS_NO_MEMORY);
1729 /* Save the wildcard match and attribs we are using on this directory -
1730 needed as lanman2 assumes these are being saved between calls */
1732 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1734 talloc_destroy(ea_ctx);
1735 return(UNIXERROR(ERRDOS,ERRbadfile));
1738 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1740 /* We don't need to check for VOL here as this is returned by
1741 a different TRANS2 call. */
1743 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1744 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1745 dont_descend = True;
1748 space_remaining = max_data_bytes;
1749 out_of_space = False;
1751 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1752 BOOL got_exact_match = False;
1754 /* this is a heuristic to avoid seeking the dirptr except when
1755 absolutely necessary. It allows for a filename of about 40 chars */
1756 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1757 out_of_space = True;
1760 finished = !get_lanman2_dir_entry(conn,
1762 mask,dirtype,info_level,
1763 requires_resume_key,dont_descend,
1764 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1765 &last_entry_off, ea_list, ea_ctx);
1768 if (finished && out_of_space)
1771 if (!finished && !out_of_space)
1775 * As an optimisation if we know we aren't looking
1776 * for a wildcard name (ie. the name matches the wildcard exactly)
1777 * then we can finish on any (first) match.
1778 * This speeds up large directory searches. JRA.
1784 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1787 talloc_destroy(ea_ctx);
1789 /* Check if we can close the dirptr */
1790 if(close_after_first || (finished && close_if_end)) {
1791 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1792 dptr_close(&dptr_num);
1796 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1797 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1798 * the protocol level is less than NT1. Tested with smbclient. JRA.
1799 * This should fix the OS/2 client bug #2335.
1802 if(numentries == 0) {
1803 dptr_close(&dptr_num);
1804 if (Protocol < PROTOCOL_NT1) {
1805 return ERROR_DOS(ERRDOS,ERRnofiles);
1807 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1811 /* At this point pdata points to numentries directory entries. */
1813 /* Set up the return parameter block */
1814 SSVAL(params,0,dptr_num);
1815 SSVAL(params,2,numentries);
1816 SSVAL(params,4,finished);
1817 SSVAL(params,6,0); /* Never an EA error */
1818 SSVAL(params,8,last_entry_off);
1820 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1822 if ((! *directory) && dptr_path(dptr_num))
1823 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1825 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1826 smb_fn_name(CVAL(inbuf,smb_com)),
1827 mask, directory, dirtype, numentries ) );
1830 * Force a name mangle here to ensure that the
1831 * mask as an 8.3 name is top of the mangled cache.
1832 * The reasons for this are subtle. Don't remove
1833 * this code unless you know what you are doing
1834 * (see PR#13758). JRA.
1837 if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn)))
1838 mangle_map(mask, True, True, SNUM(conn));
1843 /****************************************************************************
1844 Reply to a TRANS2_FINDNEXT.
1845 ****************************************************************************/
1847 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1848 char **pparams, int total_params, char **ppdata, int total_data,
1849 unsigned int max_data_bytes)
1851 /* We must be careful here that we don't return more than the
1852 allowed number of data bytes. If this means returning fewer than
1853 maxentries then so be it. We assume that the redirector has
1854 enough room for the fixed number of parameter bytes it has
1856 char *params = *pparams;
1857 char *pdata = *ppdata;
1858 int dptr_num = SVAL(params,0);
1859 int maxentries = SVAL(params,2);
1860 uint16 info_level = SVAL(params,4);
1861 uint32 resume_key = IVAL(params,6);
1862 uint16 findnext_flags = SVAL(params,10);
1863 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1864 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1865 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1866 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1867 BOOL mask_contains_wcard = False;
1868 pstring resume_name;
1874 int i, last_entry_off=0;
1875 BOOL finished = False;
1876 BOOL dont_descend = False;
1877 BOOL out_of_space = False;
1878 int space_remaining;
1879 TALLOC_CTX *ea_ctx = NULL;
1880 struct ea_list *ea_list = NULL;
1881 NTSTATUS ntstatus = NT_STATUS_OK;
1883 if (total_params < 12) {
1884 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1887 *mask = *directory = *resume_name = 0;
1889 srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1890 if (!NT_STATUS_IS_OK(ntstatus)) {
1891 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1892 complain (it thinks we're asking for the directory above the shared
1893 path or an invalid name). Catch this as the resume name is only compared, never used in
1894 a file access. JRA. */
1895 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1896 pstrcpy(resume_name, "..");
1897 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1898 pstrcpy(resume_name, ".");
1900 return ERROR_NT(ntstatus);
1904 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1905 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1906 resume_key = %d resume name = %s continue=%d level = %d\n",
1907 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1908 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1911 /* W2K3 seems to treat zero as 1. */
1915 switch (info_level) {
1916 case SMB_FIND_INFO_STANDARD:
1917 case SMB_FIND_EA_SIZE:
1918 case SMB_FIND_EA_LIST:
1919 case SMB_FIND_FILE_DIRECTORY_INFO:
1920 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1921 case SMB_FIND_FILE_NAMES_INFO:
1922 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1923 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1924 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1926 case SMB_FIND_FILE_UNIX:
1927 if (!lp_unix_extensions())
1928 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1931 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1934 if (info_level == SMB_FIND_EA_LIST) {
1937 if (total_data < 4) {
1938 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1941 ea_size = IVAL(pdata,0);
1942 if (ea_size != total_data) {
1943 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1944 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1945 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1948 if (!lp_ea_support(SNUM(conn))) {
1949 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1952 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1953 return ERROR_NT(NT_STATUS_NO_MEMORY);
1956 /* Pull out the list of names. */
1957 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1959 talloc_destroy(ea_ctx);
1960 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1964 *ppdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1965 if(*ppdata == NULL) {
1966 talloc_destroy(ea_ctx);
1967 return ERROR_NT(NT_STATUS_NO_MEMORY);
1972 /* Realloc the params space */
1973 *pparams = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1974 if(*pparams == NULL ) {
1975 talloc_destroy(ea_ctx);
1976 return ERROR_NT(NT_STATUS_NO_MEMORY);
1981 /* Check that the dptr is valid */
1982 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
1983 talloc_destroy(ea_ctx);
1984 return ERROR_DOS(ERRDOS,ERRnofiles);
1987 string_set(&conn->dirpath,dptr_path(dptr_num));
1989 /* Get the wildcard mask from the dptr */
1990 if((p = dptr_wcard(dptr_num))== NULL) {
1991 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1992 talloc_destroy(ea_ctx);
1993 return ERROR_DOS(ERRDOS,ERRnofiles);
1997 pstrcpy(directory,conn->dirpath);
1999 /* Get the attr mask from the dptr */
2000 dirtype = dptr_attr(dptr_num);
2002 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2003 dptr_num, mask, dirtype,
2005 dptr_TellDir(conn->dirptr)));
2007 /* We don't need to check for VOL here as this is returned by
2008 a different TRANS2 call. */
2010 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2011 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2012 dont_descend = True;
2015 space_remaining = max_data_bytes;
2016 out_of_space = False;
2019 * Seek to the correct position. We no longer use the resume key but
2020 * depend on the last file name instead.
2023 if(*resume_name && !continue_bit) {
2026 long current_pos = 0;
2028 * Remember, mangle_map is called by
2029 * get_lanman2_dir_entry(), so the resume name
2030 * could be mangled. Ensure we check the unmangled name.
2033 if (mangle_is_mangled(resume_name, SNUM(conn))) {
2034 mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn));
2038 * Fix for NT redirector problem triggered by resume key indexes
2039 * changing between directory scans. We now return a resume key of 0
2040 * and instead look for the filename to continue from (also given
2041 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2042 * findfirst/findnext (as is usual) then the directory pointer
2043 * should already be at the correct place.
2046 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2047 } /* end if resume_name && !continue_bit */
2049 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2050 BOOL got_exact_match = False;
2052 /* this is a heuristic to avoid seeking the dirptr except when
2053 absolutely necessary. It allows for a filename of about 40 chars */
2054 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2055 out_of_space = True;
2058 finished = !get_lanman2_dir_entry(conn,
2060 mask,dirtype,info_level,
2061 requires_resume_key,dont_descend,
2062 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2063 &last_entry_off, ea_list, ea_ctx);
2066 if (finished && out_of_space)
2069 if (!finished && !out_of_space)
2073 * As an optimisation if we know we aren't looking
2074 * for a wildcard name (ie. the name matches the wildcard exactly)
2075 * then we can finish on any (first) match.
2076 * This speeds up large directory searches. JRA.
2082 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2085 talloc_destroy(ea_ctx);
2087 /* Check if we can close the dirptr */
2088 if(close_after_request || (finished && close_if_end)) {
2089 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2090 dptr_close(&dptr_num); /* This frees up the saved mask */
2093 /* Set up the return parameter block */
2094 SSVAL(params,0,numentries);
2095 SSVAL(params,2,finished);
2096 SSVAL(params,4,0); /* Never an EA error */
2097 SSVAL(params,6,last_entry_off);
2099 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2101 if ((! *directory) && dptr_path(dptr_num))
2102 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2104 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2105 smb_fn_name(CVAL(inbuf,smb_com)),
2106 mask, directory, dirtype, numentries ) );
2111 /****************************************************************************
2112 Reply to a TRANS2_QFSINFO (query filesystem info).
2113 ****************************************************************************/
2115 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2116 char **pparams, int total_params, char **ppdata, int total_data,
2117 unsigned int max_data_bytes)
2119 char *pdata = *ppdata;
2120 char *params = *pparams;
2121 uint16 info_level = SVAL(params,0);
2124 char *vname = volume_label(SNUM(conn));
2125 int snum = SNUM(conn);
2126 char *fstype = lp_fstype(SNUM(conn));
2129 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2131 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2132 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2133 return ERROR_DOS(ERRSRV,ERRinvdevice);
2136 *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2137 if (*ppdata == NULL ) {
2138 return ERROR_NT(NT_STATUS_NO_MEMORY);
2142 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2144 switch (info_level) {
2145 case SMB_INFO_ALLOCATION:
2147 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2149 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2150 return(UNIXERROR(ERRHRD,ERRgeneral));
2153 block_size = lp_block_size(snum);
2154 if (bsize < block_size) {
2155 SMB_BIG_UINT factor = block_size/bsize;
2160 if (bsize > block_size) {
2161 SMB_BIG_UINT factor = bsize/block_size;
2166 bytes_per_sector = 512;
2167 sectors_per_unit = bsize/bytes_per_sector;
2169 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2170 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2171 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2173 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2174 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2175 SIVAL(pdata,l1_cUnit,dsize);
2176 SIVAL(pdata,l1_cUnitAvail,dfree);
2177 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2181 case SMB_INFO_VOLUME:
2182 /* Return volume name */
2184 * Add volume serial number - hash of a combination of
2185 * the called hostname and the service name.
2187 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2189 * Win2k3 and previous mess this up by sending a name length
2190 * one byte short. I believe only older clients (OS/2 Win9x) use
2191 * this call so try fixing this by adding a terminating null to
2192 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2194 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2195 SCVAL(pdata,l2_vol_cch,len);
2196 data_len = l2_vol_szVolLabel + len;
2197 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2198 (unsigned)st.st_ctime, len, vname));
2201 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2202 case SMB_FS_ATTRIBUTE_INFORMATION:
2205 #if defined(HAVE_SYS_QUOTAS)
2206 quota_flag = FILE_VOLUME_QUOTAS;
2209 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2210 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2211 quota_flag); /* FS ATTRIBUTES */
2213 SIVAL(pdata,4,255); /* Max filename component length */
2214 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2215 and will think we can't do long filenames */
2216 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2218 data_len = 12 + len;
2221 case SMB_QUERY_FS_LABEL_INFO:
2222 case SMB_FS_LABEL_INFORMATION:
2223 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2228 case SMB_QUERY_FS_VOLUME_INFO:
2229 case SMB_FS_VOLUME_INFORMATION:
2232 * Add volume serial number - hash of a combination of
2233 * the called hostname and the service name.
2235 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2236 (str_checksum(get_local_machine_name())<<16));
2238 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2239 SIVAL(pdata,12,len);
2241 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2242 (int)strlen(vname),vname, lp_servicename(snum)));
2245 case SMB_QUERY_FS_SIZE_INFO:
2246 case SMB_FS_SIZE_INFORMATION:
2248 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2250 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2251 return(UNIXERROR(ERRHRD,ERRgeneral));
2253 block_size = lp_block_size(snum);
2254 if (bsize < block_size) {
2255 SMB_BIG_UINT factor = block_size/bsize;
2260 if (bsize > block_size) {
2261 SMB_BIG_UINT factor = bsize/block_size;
2266 bytes_per_sector = 512;
2267 sectors_per_unit = bsize/bytes_per_sector;
2268 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2269 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2270 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2271 SBIG_UINT(pdata,0,dsize);
2272 SBIG_UINT(pdata,8,dfree);
2273 SIVAL(pdata,16,sectors_per_unit);
2274 SIVAL(pdata,20,bytes_per_sector);
2278 case SMB_FS_FULL_SIZE_INFORMATION:
2280 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2282 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2283 return(UNIXERROR(ERRHRD,ERRgeneral));
2285 block_size = lp_block_size(snum);
2286 if (bsize < block_size) {
2287 SMB_BIG_UINT factor = block_size/bsize;
2292 if (bsize > block_size) {
2293 SMB_BIG_UINT factor = bsize/block_size;
2298 bytes_per_sector = 512;
2299 sectors_per_unit = bsize/bytes_per_sector;
2300 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2301 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2302 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2303 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2304 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2305 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2306 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2307 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2311 case SMB_QUERY_FS_DEVICE_INFO:
2312 case SMB_FS_DEVICE_INFORMATION:
2314 SIVAL(pdata,0,0); /* dev type */
2315 SIVAL(pdata,4,0); /* characteristics */
2318 #ifdef HAVE_SYS_QUOTAS
2319 case SMB_FS_QUOTA_INFORMATION:
2321 * what we have to send --metze:
2323 * Unknown1: 24 NULL bytes
2324 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2325 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2326 * Quota Flags: 2 byte :
2327 * Unknown3: 6 NULL bytes
2331 * details for Quota Flags:
2333 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2334 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2335 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2336 * 0x0001 Enable Quotas: enable quota for this fs
2340 /* we need to fake up a fsp here,
2341 * because its not send in this call
2344 SMB_NTQUOTA_STRUCT quotas;
2347 ZERO_STRUCT(quotas);
2353 if (current_user.ut.uid != 0) {
2354 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2355 lp_servicename(SNUM(conn)),conn->user));
2356 return ERROR_DOS(ERRDOS,ERRnoaccess);
2359 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2360 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2361 return ERROR_DOS(ERRSRV,ERRerror);
2366 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2368 /* Unknown1 24 NULL bytes*/
2369 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2370 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2371 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2373 /* Default Soft Quota 8 bytes */
2374 SBIG_UINT(pdata,24,quotas.softlim);
2376 /* Default Hard Quota 8 bytes */
2377 SBIG_UINT(pdata,32,quotas.hardlim);
2379 /* Quota flag 2 bytes */
2380 SSVAL(pdata,40,quotas.qflags);
2382 /* Unknown3 6 NULL bytes */
2388 #endif /* HAVE_SYS_QUOTAS */
2389 case SMB_FS_OBJECTID_INFORMATION:
2394 * Query the version and capabilities of the CIFS UNIX extensions
2398 case SMB_QUERY_CIFS_UNIX_INFO:
2399 if (!lp_unix_extensions())
2400 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2402 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2403 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2404 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(CIFS_UNIX_POSIX_ACLS_CAP|
2405 CIFS_UNIX_POSIX_PATHNAMES_CAP))); /* We have POSIX ACLs and pathname capability. */
2408 case SMB_QUERY_POSIX_FS_INFO:
2411 vfs_statvfs_struct svfs;
2413 if (!lp_unix_extensions())
2414 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2416 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2420 SIVAL(pdata,0,svfs.OptimalTransferSize);
2421 SIVAL(pdata,4,svfs.BlockSize);
2422 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2423 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2424 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2425 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2426 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2427 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2428 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2430 } else if (rc == EOPNOTSUPP) {
2431 return ERROR_DOS(ERRDOS, ERRunknownlevel);
2432 #endif /* EOPNOTSUPP */
2434 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2435 return ERROR_DOS(ERRSRV,ERRerror);
2440 case SMB_MAC_QUERY_FS_INFO:
2442 * Thursby MAC extension... ONLY on NTFS filesystems
2443 * once we do streams then we don't need this
2445 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2447 SIVAL(pdata,84,0x100); /* Don't support mac... */
2452 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2456 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2458 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2463 /****************************************************************************
2464 Reply to a TRANS2_SETFSINFO (set filesystem info).
2465 ****************************************************************************/
2467 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2468 char **pparams, int total_params, char **ppdata, int total_data,
2469 unsigned int max_data_bytes)
2471 char *pdata = *ppdata;
2472 char *params = *pparams;
2476 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2479 if (total_params < 4) {
2480 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2482 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2485 info_level = SVAL(params,2);
2487 switch(info_level) {
2488 case SMB_SET_CIFS_UNIX_INFO:
2490 uint16 client_unix_major;
2491 uint16 client_unix_minor;
2492 uint32 client_unix_cap_low;
2493 uint32 client_unix_cap_high;
2495 if (!lp_unix_extensions()) {
2496 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2499 /* There should be 12 bytes of capabilities set. */
2500 if (total_data < 8) {
2501 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2503 client_unix_major = SVAL(pdata,0);
2504 client_unix_minor = SVAL(pdata,2);
2505 client_unix_cap_low = IVAL(pdata,4);
2506 client_unix_cap_high = IVAL(pdata,8);
2507 /* Just print these values for now. */
2508 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2509 cap_low = 0x%x, cap_high = 0x%x\n",
2510 (unsigned int)client_unix_major,
2511 (unsigned int)client_unix_minor,
2512 (unsigned int)client_unix_cap_low,
2513 (unsigned int)client_unix_cap_high ));
2515 /* Here is where we must switch to posix pathname processing... */
2516 lp_set_posix_pathnames();
2517 mangle_change_to_posix();
2520 case SMB_FS_QUOTA_INFORMATION:
2522 files_struct *fsp = NULL;
2523 SMB_NTQUOTA_STRUCT quotas;
2525 ZERO_STRUCT(quotas);
2528 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2529 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2530 lp_servicename(SNUM(conn)),conn->user));
2531 return ERROR_DOS(ERRSRV,ERRaccess);
2534 /* note: normaly there're 48 bytes,
2535 * but we didn't use the last 6 bytes for now
2538 fsp = file_fsp(params,0);
2539 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2540 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2541 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2544 if (total_data < 42) {
2545 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2547 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2550 /* unknown_1 24 NULL bytes in pdata*/
2552 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2553 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2554 #ifdef LARGE_SMB_OFF_T
2555 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2556 #else /* LARGE_SMB_OFF_T */
2557 if ((IVAL(pdata,28) != 0)&&
2558 ((quotas.softlim != 0xFFFFFFFF)||
2559 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2560 /* more than 32 bits? */
2561 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2563 #endif /* LARGE_SMB_OFF_T */
2565 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2566 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2567 #ifdef LARGE_SMB_OFF_T
2568 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2569 #else /* LARGE_SMB_OFF_T */
2570 if ((IVAL(pdata,36) != 0)&&
2571 ((quotas.hardlim != 0xFFFFFFFF)||
2572 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2573 /* more than 32 bits? */
2574 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2576 #endif /* LARGE_SMB_OFF_T */
2578 /* quota_flags 2 bytes **/
2579 quotas.qflags = SVAL(pdata,40);
2581 /* unknown_2 6 NULL bytes follow*/
2583 /* now set the quotas */
2584 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2585 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2586 return ERROR_DOS(ERRSRV,ERRerror);
2592 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2594 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2599 * sending this reply works fine,
2600 * but I'm not sure it's the same
2601 * like windows do...
2604 outsize = set_message(outbuf,10,0,True);
2609 /****************************************************************************
2610 Utility function to set bad path error.
2611 ****************************************************************************/
2613 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2615 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2616 err, (int)bad_path ));
2620 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2622 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2625 return UNIXERROR(def_class,def_code);
2628 #if defined(HAVE_POSIX_ACLS)
2629 /****************************************************************************
2630 Utility function to count the number of entries in a POSIX acl.
2631 ****************************************************************************/
2633 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2635 unsigned int ace_count = 0;
2636 int entry_id = SMB_ACL_FIRST_ENTRY;
2637 SMB_ACL_ENTRY_T entry;
2639 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2641 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2642 entry_id = SMB_ACL_NEXT_ENTRY;
2649 /****************************************************************************
2650 Utility function to marshall a POSIX acl into wire format.
2651 ****************************************************************************/
2653 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2655 int entry_id = SMB_ACL_FIRST_ENTRY;
2656 SMB_ACL_ENTRY_T entry;
2658 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2659 SMB_ACL_TAG_T tagtype;
2660 SMB_ACL_PERMSET_T permset;
2661 unsigned char perms = 0;
2662 unsigned int own_grp;
2665 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2666 entry_id = SMB_ACL_NEXT_ENTRY;
2669 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2670 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2674 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2675 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2679 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2680 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2681 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2683 SCVAL(pdata,1,perms);
2686 case SMB_ACL_USER_OBJ:
2687 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2688 own_grp = (unsigned int)pst->st_uid;
2689 SIVAL(pdata,2,own_grp);
2694 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2696 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2698 own_grp = (unsigned int)*puid;
2699 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2700 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2701 SIVAL(pdata,2,own_grp);
2705 case SMB_ACL_GROUP_OBJ:
2706 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2707 own_grp = (unsigned int)pst->st_gid;
2708 SIVAL(pdata,2,own_grp);
2713 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2715 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2717 own_grp = (unsigned int)*pgid;
2718 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2719 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2720 SIVAL(pdata,2,own_grp);
2725 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2726 SIVAL(pdata,2,0xFFFFFFFF);
2727 SIVAL(pdata,6,0xFFFFFFFF);
2730 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2731 SIVAL(pdata,2,0xFFFFFFFF);
2732 SIVAL(pdata,6,0xFFFFFFFF);
2735 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2738 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2745 /****************************************************************************
2746 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2747 file name or file id).
2748 ****************************************************************************/
2750 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2751 unsigned int tran_call,
2752 char **pparams, int total_params, char **ppdata, int total_data,
2753 unsigned int max_data_bytes)
2755 char *params = *pparams;
2756 char *pdata = *ppdata;
2760 SMB_OFF_T file_size=0;
2761 SMB_BIG_UINT allocation_size=0;
2762 unsigned int data_size = 0;
2763 unsigned int param_size = 2;
2764 SMB_STRUCT_STAT sbuf;
2765 pstring fname, dos_fname;
2770 BOOL bad_path = False;
2771 BOOL delete_pending = False;
2774 files_struct *fsp = NULL;
2775 TALLOC_CTX *ea_ctx = NULL;
2776 struct ea_list *ea_list = NULL;
2777 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2780 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2784 if (tran_call == TRANSACT2_QFILEINFO) {
2785 if (total_params < 4) {
2786 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2789 fsp = file_fsp(params,0);
2790 info_level = SVAL(params,2);
2792 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2794 if(fsp && (fsp->fake_file_handle)) {
2796 * This is actually for the QUOTA_FAKE_FILE --metze
2799 pstrcpy(fname, fsp->fsp_name);
2800 /* We know this name is ok, it's already passed the checks. */
2802 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2804 * This is actually a QFILEINFO on a directory
2805 * handle (returned from an NT SMB). NT5.0 seems
2806 * to do this call. JRA.
2808 /* We know this name is ok, it's already passed the checks. */
2809 pstrcpy(fname, fsp->fsp_name);
2811 if (INFO_LEVEL_IS_UNIX(info_level)) {
2812 /* Always do lstat for UNIX calls. */
2813 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2814 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2815 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2817 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2818 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2819 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2822 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2825 * Original code - this is an open file.
2827 CHECK_FSP(fsp,conn);
2829 pstrcpy(fname, fsp->fsp_name);
2830 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2831 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2832 return(UNIXERROR(ERRDOS,ERRbadfid));
2834 pos = fsp->fh->position_information;
2835 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2836 access_mask = fsp->access_mask;
2839 NTSTATUS status = NT_STATUS_OK;
2842 if (total_params < 6) {
2843 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2846 info_level = SVAL(params,0);
2848 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2850 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
2851 if (!NT_STATUS_IS_OK(status)) {
2852 return ERROR_NT(status);
2855 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2857 unix_convert(fname,conn,0,&bad_path,&sbuf);
2859 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2861 if (!check_name(fname,conn)) {
2862 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2863 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2866 if (INFO_LEVEL_IS_UNIX(info_level)) {
2867 /* Always do lstat for UNIX calls. */
2868 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2869 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2870 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2872 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2873 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2874 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2877 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2878 if (delete_pending) {
2879 return ERROR_NT(NT_STATUS_DELETE_PENDING);
2883 nlink = sbuf.st_nlink;
2885 if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2886 /* NTFS does not seem to count ".." */
2890 if ((nlink > 0) && delete_pending) {
2894 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2895 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2897 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2898 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2900 p = strrchr_m(fname,'/');
2906 mode = dos_mode(conn,fname,&sbuf);
2908 mode = FILE_ATTRIBUTE_NORMAL;
2910 fullpathname = fname;
2912 file_size = get_file_size(sbuf);
2914 /* Pull any EA list from the data portion. */
2915 if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2918 if (total_data < 4) {
2919 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2921 ea_size = IVAL(pdata,0);
2923 if (total_data > 0 && ea_size != total_data) {
2924 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2925 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2926 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2929 if (!lp_ea_support(SNUM(conn))) {
2930 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2933 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2934 return ERROR_NT(NT_STATUS_NO_MEMORY);
2937 /* Pull out the list of names. */
2938 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2940 talloc_destroy(ea_ctx);
2941 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2945 *pparams = SMB_REALLOC(*pparams,2);
2946 if (*pparams == NULL) {
2947 talloc_destroy(ea_ctx);
2948 return ERROR_NT(NT_STATUS_NO_MEMORY);
2952 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2953 *ppdata = SMB_REALLOC(*ppdata, data_size);
2954 if (*ppdata == NULL ) {
2955 talloc_destroy(ea_ctx);
2956 return ERROR_NT(NT_STATUS_NO_MEMORY);
2960 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2962 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2965 if (fsp->pending_modtime) {
2966 /* the pending modtime overrides the current modtime */
2967 sbuf.st_mtime = fsp->pending_modtime;
2970 /* Do we have this path open ? */
2971 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2972 if (fsp1 && fsp1->pending_modtime) {
2973 /* the pending modtime overrides the current modtime */
2974 sbuf.st_mtime = fsp1->pending_modtime;
2976 if (fsp1 && fsp1->initial_allocation_size) {
2977 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
2981 if (lp_dos_filetime_resolution(SNUM(conn))) {
2983 sbuf.st_atime &= ~1;
2984 sbuf.st_ctime &= ~1;
2985 sbuf.st_mtime &= ~1;
2988 /* NT expects the name to be in an exact form of the *full*
2989 filename. See the trans2 torture test */
2990 if (strequal(base_name,".")) {
2991 pstrcpy(dos_fname, "\\");
2993 pstr_sprintf(dos_fname, "\\%s", fname);
2994 string_replace(dos_fname, '/', '\\');
2997 switch (info_level) {
2998 case SMB_INFO_STANDARD:
2999 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3001 srv_put_dos_date2(pdata,l1_fdateCreation,c_time);
3002 srv_put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
3003 srv_put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
3004 SIVAL(pdata,l1_cbFile,(uint32)file_size);
3005 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3006 SSVAL(pdata,l1_attrFile,mode);
3009 case SMB_INFO_QUERY_EA_SIZE:
3011 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3012 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3014 srv_put_dos_date2(pdata,0,c_time);
3015 srv_put_dos_date2(pdata,4,sbuf.st_atime);
3016 srv_put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */
3017 SIVAL(pdata,12,(uint32)file_size);
3018 SIVAL(pdata,16,(uint32)allocation_size);
3019 SSVAL(pdata,20,mode);
3020 SIVAL(pdata,22,ea_size);
3024 case SMB_INFO_IS_NAME_VALID:
3025 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3026 if (tran_call == TRANSACT2_QFILEINFO) {
3027 /* os/2 needs this ? really ?*/
3028 return ERROR_DOS(ERRDOS,ERRbadfunc);
3034 case SMB_INFO_QUERY_EAS_FROM_LIST:
3036 size_t total_ea_len = 0;
3037 struct ea_list *ea_file_list = NULL;
3039 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3041 ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3042 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3044 if (!ea_list || (total_ea_len > data_size)) {
3045 talloc_destroy(ea_ctx);
3047 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3051 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3052 talloc_destroy(ea_ctx);
3056 case SMB_INFO_QUERY_ALL_EAS:
3058 /* We have data_size bytes to put EA's into. */
3059 size_t total_ea_len = 0;
3061 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3063 ea_ctx = talloc_init("ea_ctx");
3065 return ERROR_NT(NT_STATUS_NO_MEMORY);
3068 ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3069 if (!ea_list || (total_ea_len > data_size)) {
3070 talloc_destroy(ea_ctx);
3072 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3076 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3077 talloc_destroy(ea_ctx);
3081 case SMB_FILE_BASIC_INFORMATION:
3082 case SMB_QUERY_FILE_BASIC_INFO:
3084 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3085 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3086 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3088 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3092 put_long_date(pdata,c_time);
3093 put_long_date(pdata+8,sbuf.st_atime);
3094 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3095 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3096 SIVAL(pdata,32,mode);
3098 DEBUG(5,("SMB_QFBI - "));
3100 time_t create_time = c_time;
3101 DEBUG(5,("create: %s ", ctime(&create_time)));
3103 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3104 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3105 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3106 DEBUG(5,("mode: %x\n", mode));
3109 case SMB_FILE_STANDARD_INFORMATION:
3110 case SMB_QUERY_FILE_STANDARD_INFO:
3112 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3114 SOFF_T(pdata,0,allocation_size);
3115 SOFF_T(pdata,8,file_size);
3116 SIVAL(pdata,16,nlink);
3117 SCVAL(pdata,20,delete_pending?1:0);
3118 SCVAL(pdata,21,(mode&aDIR)?1:0);
3119 SSVAL(pdata,22,0); /* Padding. */
3122 case SMB_FILE_EA_INFORMATION:
3123 case SMB_QUERY_FILE_EA_INFO:
3125 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3126 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3128 SIVAL(pdata,0,ea_size);
3132 /* Get the 8.3 name - used if NT SMB was negotiated. */
3133 case SMB_QUERY_FILE_ALT_NAME_INFO:
3134 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3138 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3139 pstrcpy(short_name,base_name);
3140 /* Mangle if not already 8.3 */
3141 if(!mangle_is_8_3(short_name, True, SNUM(conn))) {
3142 mangle_map(short_name,True,True,SNUM(conn));
3144 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3145 data_size = 4 + len;
3150 case SMB_QUERY_FILE_NAME_INFO:
3152 this must be *exactly* right for ACLs on mapped drives to work
3154 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3155 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3156 data_size = 4 + len;
3160 case SMB_FILE_ALLOCATION_INFORMATION:
3161 case SMB_QUERY_FILE_ALLOCATION_INFO:
3162 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3164 SOFF_T(pdata,0,allocation_size);
3167 case SMB_FILE_END_OF_FILE_INFORMATION:
3168 case SMB_QUERY_FILE_END_OF_FILEINFO:
3169 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3171 SOFF_T(pdata,0,file_size);
3174 case SMB_QUERY_FILE_ALL_INFO:
3175 case SMB_FILE_ALL_INFORMATION:
3177 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3178 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3179 put_long_date(pdata,c_time);
3180 put_long_date(pdata+8,sbuf.st_atime);
3181 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3182 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3183 SIVAL(pdata,32,mode);
3184 SIVAL(pdata,36,0); /* padding. */
3186 SOFF_T(pdata,0,allocation_size);
3187 SOFF_T(pdata,8,file_size);
3188 SIVAL(pdata,16,nlink);
3189 SCVAL(pdata,20,delete_pending);
3190 SCVAL(pdata,21,(mode&aDIR)?1:0);
3193 SIVAL(pdata,0,ea_size);
3194 pdata += 4; /* EA info */
3195 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3198 data_size = PTR_DIFF(pdata,(*ppdata));
3201 case SMB_FILE_INTERNAL_INFORMATION:
3202 /* This should be an index number - looks like
3205 I think this causes us to fail the IFSKIT
3206 BasicFileInformationTest. -tpot */
3208 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3209 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3210 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3214 case SMB_FILE_ACCESS_INFORMATION:
3215 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3216 SIVAL(pdata,0,access_mask);
3220 case SMB_FILE_NAME_INFORMATION:
3221 /* Pathname with leading '\'. */
3224 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
3225 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3226 SIVAL(pdata,0,byte_len);
3227 data_size = 4 + byte_len;
3231 case SMB_FILE_DISPOSITION_INFORMATION:
3232 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3234 SCVAL(pdata,0,delete_pending);
3237 case SMB_FILE_POSITION_INFORMATION:
3238 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3240 SOFF_T(pdata,0,pos);
3243 case SMB_FILE_MODE_INFORMATION:
3244 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3245 SIVAL(pdata,0,mode);
3249 case SMB_FILE_ALIGNMENT_INFORMATION:
3250 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3251 SIVAL(pdata,0,0); /* No alignment needed. */
3257 * NT4 server just returns "invalid query" to this - if we try to answer
3258 * it then NTws gets a BSOD! (tridge).
3259 * W2K seems to want this. JRA.
3261 case SMB_QUERY_FILE_STREAM_INFO:
3263 case SMB_FILE_STREAM_INFORMATION:
3264 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3268 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
3269 SIVAL(pdata,0,0); /* ??? */
3270 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3271 SOFF_T(pdata,8,file_size);
3272 SIVAL(pdata,16,allocation_size);
3273 SIVAL(pdata,20,0); /* ??? */
3274 data_size = 24 + byte_len;
3278 case SMB_QUERY_COMPRESSION_INFO:
3279 case SMB_FILE_COMPRESSION_INFORMATION:
3280 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3281 SOFF_T(pdata,0,file_size);
3282 SIVAL(pdata,8,0); /* ??? */
3283 SIVAL(pdata,12,0); /* ??? */
3287 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3288 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3289 put_long_date(pdata,c_time);
3290 put_long_date(pdata+8,sbuf.st_atime);
3291 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3292 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3293 SIVAL(pdata,32,allocation_size);
3294 SOFF_T(pdata,40,file_size);
3295 SIVAL(pdata,48,mode);
3296 SIVAL(pdata,52,0); /* ??? */
3300 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3301 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3302 SIVAL(pdata,0,mode);
3308 * CIFS UNIX Extensions.
3311 case SMB_QUERY_FILE_UNIX_BASIC:
3313 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3314 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3316 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3319 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3322 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3323 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3324 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3327 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3331 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3335 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3338 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3342 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3346 SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3349 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3353 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3356 data_size = PTR_DIFF(pdata,(*ppdata));
3360 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3362 for (i=0; i<100; i++)
3363 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3369 case SMB_QUERY_FILE_UNIX_LINK:
3373 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3375 if(!S_ISLNK(sbuf.st_mode))
3376 return(UNIXERROR(ERRSRV,ERRbadlink));
3378 return(UNIXERROR(ERRDOS,ERRbadlink));
3380 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3382 return(UNIXERROR(ERRDOS,ERRnoaccess));
3384 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3386 data_size = PTR_DIFF(pdata,(*ppdata));
3391 #if defined(HAVE_POSIX_ACLS)
3392 case SMB_QUERY_POSIX_ACL:
3394 SMB_ACL_T file_acl = NULL;
3395 SMB_ACL_T def_acl = NULL;
3396 uint16 num_file_acls = 0;
3397 uint16 num_def_acls = 0;
3399 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3400 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3402 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3405 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3406 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3408 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3411 if (S_ISDIR(sbuf.st_mode)) {
3412 if (fsp && fsp->is_directory) {
3413 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3415 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3417 def_acl = free_empty_sys_acl(conn, def_acl);
3420 num_file_acls = count_acl_entries(conn, file_acl);
3421 num_def_acls = count_acl_entries(conn, def_acl);
3423 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3424 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3426 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3427 SMB_POSIX_ACL_HEADER_SIZE) ));
3429 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3432 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3434 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3437 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3438 SSVAL(pdata,2,num_file_acls);
3439 SSVAL(pdata,4,num_def_acls);
3440 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3442 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3445 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3447 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3449 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3451 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3454 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3456 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3460 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3463 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3465 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3471 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3474 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3479 /****************************************************************************
3480 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3482 ****************************************************************************/
3484 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3486 BOOL bad_path_oldname = False;
3487 BOOL bad_path_newname = False;
3488 SMB_STRUCT_STAT sbuf1, sbuf2;
3489 pstring last_component_oldname;
3490 pstring last_component_newname;
3491 NTSTATUS status = NT_STATUS_OK;
3497 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3498 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3501 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3502 if (bad_path_oldname) {
3503 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3506 /* Quick check for "." and ".." */
3507 if (last_component_oldname[0] == '.') {
3508 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3509 return NT_STATUS_OBJECT_NAME_INVALID;
3513 /* source must already exist. */
3514 if (!VALID_STAT(sbuf1)) {
3515 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3518 if (!check_name(oldname,conn)) {
3519 return NT_STATUS_ACCESS_DENIED;
3522 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3523 if (bad_path_newname) {
3524 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3527 /* Quick check for "." and ".." */
3528 if (last_component_newname[0] == '.') {
3529 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3530 return NT_STATUS_OBJECT_NAME_INVALID;
3534 /* Disallow if newname already exists. */
3535 if (VALID_STAT(sbuf2)) {
3536 return NT_STATUS_OBJECT_NAME_COLLISION;
3539 if (!check_name(newname,conn)) {
3540 return NT_STATUS_ACCESS_DENIED;
3543 /* No links from a directory. */
3544 if (S_ISDIR(sbuf1.st_mode)) {
3545 return NT_STATUS_FILE_IS_A_DIRECTORY;
3548 /* Ensure this is within the share. */
3549 if (!reduce_name(conn, oldname) != 0)
3550 return NT_STATUS_ACCESS_DENIED;
3552 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3554 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3555 status = map_nt_error_from_unix(errno);
3556 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3557 nt_errstr(status), newname, oldname));
3563 /****************************************************************************
3564 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3565 ****************************************************************************/
3567 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3568 unsigned int tran_call,
3569 char **pparams, int total_params, char **ppdata, int total_data,
3570 unsigned int max_data_bytes)
3572 char *params = *pparams;
3573 char *pdata = *ppdata;
3578 SMB_STRUCT_STAT sbuf;
3581 BOOL bad_path = False;
3582 files_struct *fsp = NULL;
3583 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3584 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3585 mode_t unixmode = 0;
3586 NTSTATUS status = NT_STATUS_OK;
3589 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3594 if (tran_call == TRANSACT2_SETFILEINFO) {
3595 if (total_params < 4) {
3596 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3599 fsp = file_fsp(params,0);
3600 info_level = SVAL(params,2);
3602 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3604 * This is actually a SETFILEINFO on a directory
3605 * handle (returned from an NT SMB). NT5.0 seems
3606 * to do this call. JRA.
3608 pstrcpy(fname, fsp->fsp_name);
3609 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3610 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3611 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3613 } else if (fsp && fsp->print_file) {
3615 * Doing a DELETE_ON_CLOSE should cancel a print job.
3617 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3618 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
3620 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3623 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3626 return (UNIXERROR(ERRDOS,ERRbadpath));
3629 * Original code - this is an open file.
3631 CHECK_FSP(fsp,conn);
3633 pstrcpy(fname, fsp->fsp_name);
3636 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3637 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3638 return(UNIXERROR(ERRDOS,ERRbadfid));
3643 if (total_params < 6) {
3644 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3647 info_level = SVAL(params,0);
3648 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
3649 if (!NT_STATUS_IS_OK(status)) {
3650 return ERROR_NT(status);
3652 unix_convert(fname,conn,0,&bad_path,&sbuf);
3654 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3658 * For CIFS UNIX extensions the target name may not exist.
3661 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3662 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3663 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3666 if(!check_name(fname, conn)) {
3667 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3672 if (!CAN_WRITE(conn))
3673 return ERROR_DOS(ERRSRV,ERRaccess);
3675 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3676 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3678 if (VALID_STAT(sbuf))
3679 unixmode = sbuf.st_mode;
3681 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3682 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3684 /* Realloc the parameter size */
3685 *pparams = SMB_REALLOC(*pparams,2);
3686 if (*pparams == NULL) {
3687 return ERROR_NT(NT_STATUS_NO_MEMORY);
3693 if (fsp && fsp->pending_modtime) {
3694 /* the pending modtime overrides the current modtime */
3695 sbuf.st_mtime = fsp->pending_modtime;
3698 size = get_file_size(sbuf);
3699 tvs.modtime = sbuf.st_mtime;
3700 tvs.actime = sbuf.st_atime;
3701 dosmode = dos_mode(conn,fname,&sbuf);
3702 unixmode = sbuf.st_mode;
3704 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3705 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3707 switch (info_level) {
3708 case SMB_INFO_STANDARD:
3710 if (total_data < 12) {
3711 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3715 tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
3717 tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
3721 case SMB_INFO_SET_EA:
3723 struct ea_list *ea_list = NULL;
3724 TALLOC_CTX *ctx = NULL;
3726 if (total_data < 10) {
3728 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3729 length. They seem to have no effect. Bug #3212. JRA */
3731 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3732 /* We're done. We only get EA info in this call. */
3734 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3738 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3741 if (IVAL(pdata,0) > total_data) {
3742 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3743 IVAL(pdata,0), (unsigned int)total_data));
3744 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3747 ctx = talloc_init("SMB_INFO_SET_EA");
3749 return ERROR_NT(NT_STATUS_NO_MEMORY);
3751 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3753 talloc_destroy(ctx);
3754 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3756 status = set_ea(conn, fsp, fname, ea_list);
3757 talloc_destroy(ctx);
3759 if (!NT_STATUS_IS_OK(status)) {
3760 return ERROR_NT(status);
3763 /* We're done. We only get EA info in this call. */
3765 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3770 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3771 /* XXXX um, i don't think this is right.
3772 it's also not in the cifs6.txt spec.
3774 case SMB_INFO_QUERY_EAS_FROM_LIST:
3775 if (total_data < 28)
3776 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3778 tvs.actime = make_unix_date2(pdata+8);
3779 tvs.modtime = make_unix_date2(pdata+12);
3780 size = IVAL(pdata,16);
3781 dosmode = IVAL(pdata,24);
3784 /* XXXX nor this. not in cifs6.txt, either. */
3785 case SMB_INFO_QUERY_ALL_EAS:
3786 if (total_data < 28)
3787 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3789 tvs.actime = make_unix_date2(pdata+8);
3790 tvs.modtime = make_unix_date2(pdata+12);
3791 size = IVAL(pdata,16);
3792 dosmode = IVAL(pdata,24);
3796 case SMB_SET_FILE_BASIC_INFO:
3797 case SMB_FILE_BASIC_INFORMATION:
3799 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3801 time_t changed_time;
3803 if (total_data < 36) {
3804 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3807 /* Ignore create time at offset pdata. */
3810 tvs.actime = interpret_long_date(pdata+8);
3812 write_time = interpret_long_date(pdata+16);
3813 changed_time = interpret_long_date(pdata+24);
3815 tvs.modtime = MIN(write_time, changed_time);
3817 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3818 tvs.modtime = write_time;
3820 /* Prefer a defined time to an undefined one. */
3821 if (null_mtime(tvs.modtime)) {
3822 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3826 dosmode = IVAL(pdata,32);
3830 case SMB_FILE_ALLOCATION_INFORMATION:
3831 case SMB_SET_FILE_ALLOCATION_INFO:
3834 SMB_BIG_UINT allocation_size;
3836 if (total_data < 8) {
3837 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3840 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3841 #ifdef LARGE_SMB_OFF_T
3842 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3843 #else /* LARGE_SMB_OFF_T */
3844 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3845 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3846 #endif /* LARGE_SMB_OFF_T */
3847 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3848 fname, (double)allocation_size ));
3850 if (allocation_size) {
3851 allocation_size = smb_roundup(conn, allocation_size);
3854 if(allocation_size != get_file_size(sbuf)) {
3855 SMB_STRUCT_STAT new_sbuf;
3857 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3858 fname, (double)allocation_size ));
3861 files_struct *new_fsp = NULL;
3863 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
3865 FILE_SHARE_READ|FILE_SHARE_WRITE,
3868 FILE_ATTRIBUTE_NORMAL,
3872 if (new_fsp == NULL) {
3873 return(UNIXERROR(ERRDOS,ERRbadpath));
3875 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3876 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
3877 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3878 new_fsp->fnum, strerror(errno)));
3881 close_file(new_fsp,NORMAL_CLOSE);
3883 ret = vfs_allocate_file_space(fsp, allocation_size);
3884 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3885 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3886 fsp->fnum, strerror(errno)));
3891 return ERROR_NT(NT_STATUS_DISK_FULL);
3893 /* Allocate can truncate size... */
3894 size = get_file_size(new_sbuf);
3900 case SMB_FILE_END_OF_FILE_INFORMATION:
3901 case SMB_SET_FILE_END_OF_FILE_INFO:
3903 if (total_data < 8) {
3904 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3907 size = IVAL(pdata,0);
3908 #ifdef LARGE_SMB_OFF_T
3909 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3910 #else /* LARGE_SMB_OFF_T */
3911 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3912 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3913 #endif /* LARGE_SMB_OFF_T */
3914 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3918 case SMB_FILE_DISPOSITION_INFORMATION:
3919 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3921 BOOL delete_on_close;
3923 if (total_data < 1) {
3924 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3927 delete_on_close = (CVAL(pdata,0) ? True : False);
3929 /* Just ignore this set on a path. */
3930 if (tran_call != TRANSACT2_SETFILEINFO)
3934 return(UNIXERROR(ERRDOS,ERRbadfid));
3936 status = can_set_delete_on_close(fsp, delete_on_close,
3939 if (!NT_STATUS_IS_OK(status)) {
3940 return ERROR_NT(status);
3943 /* The set is across all open files on this dev/inode pair. */
3944 if (!set_delete_on_close(fsp, delete_on_close, ¤t_user.ut)) {
3945 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3949 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3953 case SMB_FILE_POSITION_INFORMATION:
3955 SMB_BIG_UINT position_information;
3957 if (total_data < 8) {
3958 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3961 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3962 #ifdef LARGE_SMB_OFF_T
3963 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3964 #else /* LARGE_SMB_OFF_T */
3965 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3966 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3967 #endif /* LARGE_SMB_OFF_T */
3968 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3969 fname, (double)position_information ));
3971 fsp->fh->position_information = position_information;
3974 /* We're done. We only get position info in this call. */
3976 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3980 /* From tridge Samba4 :
3981 * MODE_INFORMATION in setfileinfo (I have no
3982 * idea what "mode information" on a file is - it takes a value of 0,
3983 * 2, 4 or 6. What could it be?).
3986 case SMB_FILE_MODE_INFORMATION:
3990 if (total_data < 4) {
3991 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3993 mode = IVAL(pdata,0);
3994 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
3995 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3998 /* We're done. We only get mode info in this call. */
4000 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4005 * CIFS UNIX extensions.
4008 case SMB_SET_FILE_UNIX_BASIC:
4010 uint32 raw_unixmode;
4012 if (total_data < 100) {
4013 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4016 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4017 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4018 size=IVAL(pdata,0); /* first 8 Bytes are size */
4019 #ifdef LARGE_SMB_OFF_T
4020 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4021 #else /* LARGE_SMB_OFF_T */
4022 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
4023 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4024 #endif /* LARGE_SMB_OFF_T */
4026 pdata+=24; /* ctime & st_blocks are not changed */
4027 tvs.actime = interpret_long_date(pdata); /* access_time */
4028 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
4030 set_owner = (uid_t)IVAL(pdata,0);
4032 set_grp = (gid_t)IVAL(pdata,0);
4034 raw_unixmode = IVAL(pdata,28);
4035 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4036 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4038 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4039 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4040 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4042 if (!VALID_STAT(sbuf)) {
4045 * The only valid use of this is to create character and block
4046 * devices, and named pipes. This is deprecated (IMHO) and
4047 * a new info level should be used for mknod. JRA.
4050 uint32 file_type = IVAL(pdata,0);
4051 #if defined(HAVE_MAKEDEV)
4052 uint32 dev_major = IVAL(pdata,4);
4053 uint32 dev_minor = IVAL(pdata,12);
4056 uid_t myuid = geteuid();
4057 gid_t mygid = getegid();
4058 SMB_DEV_T dev = (SMB_DEV_T)0;
4060 if (tran_call == TRANSACT2_SETFILEINFO)
4061 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4063 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4064 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4067 #if defined(HAVE_MAKEDEV)
4068 dev = makedev(dev_major, dev_minor);
4071 /* We can only create as the owner/group we are. */
4073 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4074 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4075 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4076 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4078 switch (file_type) {
4079 #if defined(S_IFIFO)
4080 case UNIX_TYPE_FIFO:
4081 unixmode |= S_IFIFO;
4084 #if defined(S_IFSOCK)
4085 case UNIX_TYPE_SOCKET:
4086 unixmode |= S_IFSOCK;
4089 #if defined(S_IFCHR)
4090 case UNIX_TYPE_CHARDEV:
4091 unixmode |= S_IFCHR;
4094 #if defined(S_IFBLK)
4095 case UNIX_TYPE_BLKDEV:
4096 unixmode |= S_IFBLK;
4100 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4103 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4104 0%o for file %s\n", (double)dev, unixmode, fname ));
4106 /* Ok - do the mknod. */
4107 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4108 return(UNIXERROR(ERRDOS,ERRnoaccess));
4110 inherit_access_acl(conn, fname, unixmode);
4113 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4118 * Deal with the UNIX specific mode set.
4121 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4122 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4123 (unsigned int)unixmode, fname ));
4124 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4125 return(UNIXERROR(ERRDOS,ERRnoaccess));
4129 * Deal with the UNIX specific uid set.
4132 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4133 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4134 (unsigned int)set_owner, fname ));
4135 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4136 return(UNIXERROR(ERRDOS,ERRnoaccess));
4140 * Deal with the UNIX specific gid set.
4143 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4144 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4145 (unsigned int)set_owner, fname ));
4146 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4147 return(UNIXERROR(ERRDOS,ERRnoaccess));
4152 case SMB_SET_FILE_UNIX_LINK:
4154 pstring link_target;
4155 char *newname = fname;
4157 /* Set a symbolic link. */
4158 /* Don't allow this if follow links is false. */
4160 if (!lp_symlinks(SNUM(conn)))
4161 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4163 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4165 /* !widelinks forces the target path to be within the share. */
4166 /* This means we can interpret the target as a pathname. */
4167 if (!lp_widelinks(SNUM(conn))) {
4169 char *last_dirp = NULL;
4171 unix_format(link_target);
4172 if (*link_target == '/') {
4173 /* No absolute paths allowed. */
4174 return(UNIXERROR(ERRDOS,ERRnoaccess));
4176 pstrcpy(rel_name, newname);
4177 last_dirp = strrchr_m(rel_name, '/');
4179 last_dirp[1] = '\0';
4181 pstrcpy(rel_name, "./");
4183 pstrcat(rel_name, link_target);
4185 if (!check_name(rel_name, conn)) {
4186 return(UNIXERROR(ERRDOS,ERRnoaccess));
4190 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4191 fname, link_target ));
4193 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4194 return(UNIXERROR(ERRDOS,ERRnoaccess));
4196 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4200 case SMB_SET_FILE_UNIX_HLINK:
4203 char *newname = fname;
4205 /* Set a hard link. */
4206 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
4207 if (!NT_STATUS_IS_OK(status)) {
4208 return ERROR_NT(status);
4211 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4214 status = hardlink_internals(conn, oldname, newname);
4215 if (!NT_STATUS_IS_OK(status)) {
4216 return ERROR_NT(status);
4220 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4224 case SMB_FILE_RENAME_INFORMATION:
4233 if (total_data < 12) {
4234 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4237 overwrite = (CVAL(pdata,0) ? True : False);
4238 root_fid = IVAL(pdata,4);
4239 len = IVAL(pdata,8);
4240 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
4241 if (!NT_STATUS_IS_OK(status)) {
4242 return ERROR_NT(status);
4245 /* Check the new name has no '/' characters. */
4246 if (strchr_m(newname, '/'))
4247 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4249 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4251 /* Create the base directory. */
4252 pstrcpy(base_name, fname);
4253 p = strrchr_m(base_name, '/');
4256 /* Append the new name. */
4257 pstrcat(base_name, "/");
4258 pstrcat(base_name, newname);
4261 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4262 fsp->fnum, fsp->fsp_name, base_name ));
4263 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4265 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4267 status = rename_internals(conn, fname, base_name, 0, overwrite, False);
4269 if (!NT_STATUS_IS_OK(status)) {
4270 return ERROR_NT(status);
4272 process_pending_change_notify_queue((time_t)0);
4274 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4278 #if defined(HAVE_POSIX_ACLS)
4279 case SMB_SET_POSIX_ACL:
4281 uint16 posix_acl_version;
4282 uint16 num_file_acls;
4283 uint16 num_def_acls;
4284 BOOL valid_file_acls = True;
4285 BOOL valid_def_acls = True;
4287 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4288 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4290 posix_acl_version = SVAL(pdata,0);
4291 num_file_acls = SVAL(pdata,2);
4292 num_def_acls = SVAL(pdata,4);
4294 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4295 valid_file_acls = False;
4299 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4300 valid_def_acls = False;
4304 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4305 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4308 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4309 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4310 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4313 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4314 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4315 return(UNIXERROR(ERRDOS,ERRnoaccess));
4318 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4319 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4320 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4321 return(UNIXERROR(ERRDOS,ERRnoaccess));
4325 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4331 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4334 /* get some defaults (no modifications) if any info is zero or -1. */
4335 if (null_mtime(tvs.actime)) {
4336 tvs.actime = sbuf.st_atime;
4339 if (null_mtime(tvs.modtime)) {
4340 tvs.modtime = sbuf.st_mtime;
4343 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4344 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4345 DEBUG(6,("size: %.0f ", (double)size));
4348 if (S_ISDIR(sbuf.st_mode))
4354 DEBUG(6,("dosmode: %x\n" , dosmode));
4356 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4357 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4358 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4359 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4362 * Only do this test if we are not explicitly
4363 * changing the size of a file.
4366 size = get_file_size(sbuf);
4370 * Try and set the times, size and mode of this file -
4371 * if they are different from the current values
4374 /* check the mode isn't different, before changing it */
4375 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4377 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4379 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4380 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4381 return(UNIXERROR(ERRDOS,ERRnoaccess));
4386 if (size != get_file_size(sbuf)) {
4390 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4391 fname, (double)size ));
4394 files_struct *new_fsp = NULL;
4396 new_fsp = open_file_ntcreate(conn, fname, &sbuf,
4398 FILE_SHARE_READ|FILE_SHARE_WRITE,
4401 FILE_ATTRIBUTE_NORMAL,
4405 if (new_fsp == NULL) {
4406 return(UNIXERROR(ERRDOS,ERRbadpath));
4408 ret = vfs_set_filelen(new_fsp, size);
4409 close_file(new_fsp,NORMAL_CLOSE);
4411 ret = vfs_set_filelen(fsp, size);
4415 return (UNIXERROR(ERRHRD,ERRdiskfull));
4420 * Finally the times.
4422 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4425 * This was a setfileinfo on an open file.
4426 * NT does this a lot. We also need to
4427 * set the time here, as it can be read by
4428 * FindFirst/FindNext and with the patch for bug #2045
4429 * in smbd/fileio.c it ensures that this timestamp is
4430 * kept sticky even after a write. We save the request
4431 * away and will set it on file close and after a write. JRA.
4434 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4435 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4436 fsp_set_pending_modtime(fsp, tvs.modtime);
4440 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4442 if(file_utime(conn, fname, &tvs)!=0) {
4443 return(UNIXERROR(ERRDOS,ERRnoaccess));
4448 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4453 /****************************************************************************
4454 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4455 ****************************************************************************/
4457 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4458 char **pparams, int total_params, char **ppdata, int total_data,
4459 unsigned int max_data_bytes)
4461 char *params = *pparams;
4462 char *pdata = *ppdata;
4465 SMB_STRUCT_STAT sbuf;
4466 BOOL bad_path = False;
4467 NTSTATUS status = NT_STATUS_OK;
4468 TALLOC_CTX *ctx = NULL;
4469 struct ea_list *ea_list = NULL;
4471 if (!CAN_WRITE(conn))
4472 return ERROR_DOS(ERRSRV,ERRaccess);
4474 if (total_params < 4) {
4475 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4478 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status);
4479 if (!NT_STATUS_IS_OK(status)) {
4480 return ERROR_NT(status);
4483 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4485 unix_convert(directory,conn,0,&bad_path,&sbuf);
4487 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4490 /* Any data in this call is an EA list. */
4491 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
4492 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4496 * OS/2 workplace shell seems to send SET_EA requests of "null"
4497 * length (4 bytes containing IVAL 4).
4498 * They seem to have no effect. Bug #3212. JRA.
4501 if (total_data != 4) {
4502 if (total_data < 10) {
4503 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4506 if (IVAL(pdata,0) > total_data) {
4507 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4508 IVAL(pdata,0), (unsigned int)total_data));
4509 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4512 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4514 return ERROR_NT(NT_STATUS_NO_MEMORY);
4516 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4518 talloc_destroy(ctx);
4519 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4521 } else if (IVAL(pdata,0) != 4) {
4522 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4525 if (check_name(directory,conn)) {
4526 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4530 talloc_destroy(ctx);
4531 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4532 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4535 /* Try and set any given EA. */
4537 status = set_ea(conn, NULL, directory, ea_list);
4538 talloc_destroy(ctx);
4539 if (!NT_STATUS_IS_OK(status)) {
4540 return ERROR_NT(status);
4544 /* Realloc the parameter and data sizes */
4545 *pparams = SMB_REALLOC(*pparams,2);
4546 if(*pparams == NULL) {
4547 return ERROR_NT(NT_STATUS_NO_MEMORY);
4553 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4558 /****************************************************************************
4559 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4560 We don't actually do this - we just send a null response.
4561 ****************************************************************************/
4563 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4564 char **pparams, int total_params, char **ppdata, int total_data,
4565 unsigned int max_data_bytes)
4567 static uint16 fnf_handle = 257;
4568 char *params = *pparams;
4571 if (total_params < 6) {
4572 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4575 info_level = SVAL(params,4);
4576 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4578 switch (info_level) {
4583 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4586 /* Realloc the parameter and data sizes */
4587 *pparams = SMB_REALLOC(*pparams,6);
4588 if (*pparams == NULL) {
4589 return ERROR_NT(NT_STATUS_NO_MEMORY);
4593 SSVAL(params,0,fnf_handle);
4594 SSVAL(params,2,0); /* No changes */
4595 SSVAL(params,4,0); /* No EA errors */
4602 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4607 /****************************************************************************
4608 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4609 changes). Currently this does nothing.
4610 ****************************************************************************/
4612 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4613 char **pparams, int total_params, char **ppdata, int total_data,
4614 unsigned int max_data_bytes)
4616 char *params = *pparams;
4618 DEBUG(3,("call_trans2findnotifynext\n"));
4620 /* Realloc the parameter and data sizes */
4621 *pparams = SMB_REALLOC(*pparams,4);
4622 if (*pparams == NULL) {
4623 return ERROR_NT(NT_STATUS_NO_MEMORY);
4627 SSVAL(params,0,0); /* No changes */
4628 SSVAL(params,2,0); /* No EA errors */
4630 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4635 /****************************************************************************
4636 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4637 ****************************************************************************/
4639 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4640 char **pparams, int total_params, char **ppdata, int total_data,
4641 unsigned int max_data_bytes)
4643 char *params = *pparams;
4646 int max_referral_level;
4648 DEBUG(10,("call_trans2getdfsreferral\n"));
4650 if (total_params < 2) {
4651 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4654 max_referral_level = SVAL(params,0);
4656 if(!lp_host_msdfs())
4657 return ERROR_DOS(ERRDOS,ERRbadfunc);
4659 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4660 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4661 return UNIXERROR(ERRDOS,ERRbadfile);
4663 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4664 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4669 #define LMCAT_SPL 0x53
4670 #define LMFUNC_GETJOBID 0x60
4672 /****************************************************************************
4673 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4674 ****************************************************************************/
4676 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4677 char **pparams, int total_params, char **ppdata, int total_data,
4678 unsigned int max_data_bytes)
4680 char *pdata = *ppdata;
4681 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4683 /* check for an invalid fid before proceeding */
4686 return(ERROR_DOS(ERRDOS,ERRbadfid));
4688 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4689 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4690 *ppdata = SMB_REALLOC(*ppdata, 32);
4691 if (*ppdata == NULL) {
4692 return ERROR_NT(NT_STATUS_NO_MEMORY);
4696 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4697 CAN ACCEPT THIS IN UNICODE. JRA. */
4699 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4700 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4701 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4702 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4705 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4706 return ERROR_DOS(ERRSRV,ERRerror);
4710 /****************************************************************************
4711 Reply to a SMBfindclose (stop trans2 directory search).
4712 ****************************************************************************/
4714 int reply_findclose(connection_struct *conn,
4715 char *inbuf,char *outbuf,int length,int bufsize)
4718 int dptr_num=SVALS(inbuf,smb_vwv0);
4719 START_PROFILE(SMBfindclose);
4721 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4723 dptr_close(&dptr_num);
4725 outsize = set_message(outbuf,0,0,True);
4727 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4729 END_PROFILE(SMBfindclose);
4733 /****************************************************************************
4734 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4735 ****************************************************************************/
4737 int reply_findnclose(connection_struct *conn,
4738 char *inbuf,char *outbuf,int length,int bufsize)
4742 START_PROFILE(SMBfindnclose);
4744 dptr_num = SVAL(inbuf,smb_vwv0);
4746 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4748 /* We never give out valid handles for a
4749 findnotifyfirst - so any dptr_num is ok here.
4752 outsize = set_message(outbuf,0,0,True);
4754 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4756 END_PROFILE(SMBfindnclose);
4760 /****************************************************************************
4761 Reply to a SMBtranss2 - just ignore it!
4762 ****************************************************************************/
4764 int reply_transs2(connection_struct *conn,
4765 char *inbuf,char *outbuf,int length,int bufsize)
4767 START_PROFILE(SMBtranss2);
4768 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4769 END_PROFILE(SMBtranss2);
4773 /****************************************************************************
4774 Reply to a SMBtrans2.
4775 ****************************************************************************/
4777 int reply_trans2(connection_struct *conn,
4778 char *inbuf,char *outbuf,int length,int bufsize)
4781 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4782 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4783 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4785 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4786 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4787 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4788 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4789 int32 timeout = IVALS(inbuf,smb_timeout);
4791 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4792 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4793 char *params = NULL, *data = NULL;
4794 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4795 START_PROFILE(SMBtrans2);
4797 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4798 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4799 END_PROFILE(SMBtrans2);
4800 return ERROR_DOS(ERRSRV,ERRaccess);
4803 outsize = set_message(outbuf,0,0,True);
4805 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4806 is so as a sanity check */
4809 * Need to have rc=0 for ioctl to get job id for OS/2.
4810 * Network printing will fail if function is not successful.
4811 * Similar function in reply.c will be used if protocol
4812 * is LANMAN1.0 instead of LM1.2X002.
4813 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4814 * outbuf doesn't have to be set(only job id is used).
4816 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4817 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4818 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4819 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4821 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4822 DEBUG(2,("Transaction is %d\n",tran_call));
4823 END_PROFILE(SMBtrans2);
4824 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4828 /* Allocate the space for the maximum needed parameters and data */
4829 if (total_params > 0)
4830 params = (char *)SMB_MALLOC(total_params);
4832 data = (char *)SMB_MALLOC(total_data);
4834 if ((total_params && !params) || (total_data && !data)) {
4835 DEBUG(2,("Out of memory in reply_trans2\n"));
4838 END_PROFILE(SMBtrans2);
4839 return ERROR_NT(NT_STATUS_NO_MEMORY);
4842 /* Copy the param and data bytes sent with this request into
4843 the params buffer */
4844 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4845 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4847 if (num_params > total_params || num_data > total_data)
4848 exit_server("invalid params in reply_trans2");
4851 unsigned int psoff = SVAL(inbuf, smb_psoff);
4852 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4854 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4855 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4857 memcpy( params, smb_base(inbuf) + psoff, num_params);
4860 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4861 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4863 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4864 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4866 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4869 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4871 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4872 /* We need to send an interim response then receive the rest
4873 of the parameter/data bytes */
4874 outsize = set_message(outbuf,0,0,True);
4875 srv_signing_trans_stop();
4877 if (!send_smb(smbd_server_fd(),outbuf))
4878 exit_server("reply_trans2: send_smb failed.");
4880 while (num_data_sofar < total_data ||
4881 num_params_sofar < total_params) {
4883 unsigned int param_disp;
4884 unsigned int param_off;
4885 unsigned int data_disp;
4886 unsigned int data_off;
4888 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4890 /* We need to re-calcuate the new length after we've read the secondary packet. */
4891 length = smb_len(inbuf) + 4;
4894 * The sequence number for the trans reply is always
4895 * based on the last secondary received.
4898 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4901 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4902 outsize = set_message(outbuf,0,0,True);
4904 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4906 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4907 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4911 /* Revise total_params and total_data in case
4912 they have changed downwards */
4913 if (SVAL(inbuf, smb_tpscnt) < total_params)
4914 total_params = SVAL(inbuf, smb_tpscnt);
4915 if (SVAL(inbuf, smb_tdscnt) < total_data)
4916 total_data = SVAL(inbuf, smb_tdscnt);
4918 num_params = SVAL(inbuf,smb_spscnt);
4919 param_off = SVAL(inbuf, smb_spsoff);
4920 param_disp = SVAL(inbuf, smb_spsdisp);
4921 num_params_sofar += num_params;
4923 num_data = SVAL(inbuf, smb_sdscnt);
4924 data_off = SVAL(inbuf, smb_sdsoff);
4925 data_disp = SVAL(inbuf, smb_sdsdisp);
4926 num_data_sofar += num_data;
4928 if (num_params_sofar > total_params || num_data_sofar > total_data)
4932 if (param_disp + num_params > total_params)
4934 if ((param_disp + num_params < param_disp) ||
4935 (param_disp + num_params < num_params))
4937 if (param_disp > total_params)
4939 if ((smb_base(inbuf) + param_off + num_params > inbuf + length) ||
4940 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4942 if (params + param_disp < params)
4945 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
4948 if (data_disp + num_data > total_data)
4950 if ((data_disp + num_data < data_disp) ||
4951 (data_disp + num_data < num_data))
4953 if (data_disp > total_data)
4955 if ((smb_base(inbuf) + data_off + num_data > inbuf + length) ||
4956 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4958 if (data + data_disp < data)
4961 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4966 if (Protocol >= PROTOCOL_NT1) {
4967 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4970 /* Now we must call the relevant TRANS2 function */
4972 case TRANSACT2_OPEN:
4973 START_PROFILE_NESTED(Trans2_open);
4974 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4975 ¶ms, total_params, &data, total_data, max_data_bytes);
4976 END_PROFILE_NESTED(Trans2_open);
4979 case TRANSACT2_FINDFIRST:
4980 START_PROFILE_NESTED(Trans2_findfirst);
4981 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4982 ¶ms, total_params, &data, total_data, max_data_bytes);
4983 END_PROFILE_NESTED(Trans2_findfirst);
4986 case TRANSACT2_FINDNEXT:
4987 START_PROFILE_NESTED(Trans2_findnext);
4988 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4989 ¶ms, total_params, &data, total_data, max_data_bytes);
4990 END_PROFILE_NESTED(Trans2_findnext);
4993 case TRANSACT2_QFSINFO:
4994 START_PROFILE_NESTED(Trans2_qfsinfo);
4995 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4996 ¶ms, total_params, &data, total_data, max_data_bytes);
4997 END_PROFILE_NESTED(Trans2_qfsinfo);
5000 case TRANSACT2_SETFSINFO:
5001 START_PROFILE_NESTED(Trans2_setfsinfo);
5002 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
5003 ¶ms, total_params, &data, total_data, max_data_bytes);
5004 END_PROFILE_NESTED(Trans2_setfsinfo);
5007 case TRANSACT2_QPATHINFO:
5008 case TRANSACT2_QFILEINFO:
5009 START_PROFILE_NESTED(Trans2_qpathinfo);
5010 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5011 ¶ms, total_params, &data, total_data, max_data_bytes);
5012 END_PROFILE_NESTED(Trans2_qpathinfo);
5014 case TRANSACT2_SETPATHINFO:
5015 case TRANSACT2_SETFILEINFO:
5016 START_PROFILE_NESTED(Trans2_setpathinfo);
5017 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5018 ¶ms, total_params, &data, total_data, max_data_bytes);
5019 END_PROFILE_NESTED(Trans2_setpathinfo);
5022 case TRANSACT2_FINDNOTIFYFIRST:
5023 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5024 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
5025 ¶ms, total_params, &data, total_data, max_data_bytes);
5026 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5029 case TRANSACT2_FINDNOTIFYNEXT:
5030 START_PROFILE_NESTED(Trans2_findnotifynext);
5031 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
5032 ¶ms, total_params, &data, total_data, max_data_bytes);
5033 END_PROFILE_NESTED(Trans2_findnotifynext);
5035 case TRANSACT2_MKDIR:
5036 START_PROFILE_NESTED(Trans2_mkdir);
5037 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
5038 ¶ms, total_params, &data, total_data, max_data_bytes);
5039 END_PROFILE_NESTED(Trans2_mkdir);
5042 case TRANSACT2_GET_DFS_REFERRAL:
5043 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5044 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
5045 ¶ms, total_params, &data, total_data, max_data_bytes);
5046 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5048 case TRANSACT2_IOCTL:
5049 START_PROFILE_NESTED(Trans2_ioctl);
5050 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
5051 ¶ms, total_params, &data, total_data, max_data_bytes);
5052 END_PROFILE_NESTED(Trans2_ioctl);
5055 /* Error in request */
5056 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
5059 END_PROFILE(SMBtrans2);
5060 srv_signing_trans_stop();
5061 return ERROR_DOS(ERRSRV,ERRerror);
5064 /* As we do not know how many data packets will need to be
5065 returned here the various call_trans2xxxx calls
5066 must send their own. Thus a call_trans2xxx routine only
5067 returns a value other than -1 when it wants to send
5071 srv_signing_trans_stop();
5075 END_PROFILE(SMBtrans2);
5076 return outsize; /* If a correct response was needed the
5077 call_trans2xxx calls have already sent
5078 it. If outsize != -1 then it is returning */
5082 srv_signing_trans_stop();
5085 END_PROFILE(SMBtrans2);
5086 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);