2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2003
5 Copyright (C) Stefan (metze) Metzmacher 2003
7 Extensively modified by Andrew Tridgell, 1995
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 extern enum protocol_types Protocol;
28 extern int smb_read_error;
29 extern int global_oplock_break;
30 extern uint32 global_client_caps;
31 extern struct current_user current_user;
33 #define get_file_size(sbuf) ((sbuf).st_size)
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
36 /********************************************************************
37 Roundup a value to the nearest allocation roundup size boundary.
38 Only do this for Windows clients.
39 ********************************************************************/
41 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
43 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
45 /* Only roundup for Windows clients. */
46 enum remote_arch_types ra_type = get_remote_arch();
47 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
48 val = SMB_ROUNDUP(val,rval);
53 /********************************************************************
54 Given a stat buffer return the allocated size on disk, taking into
56 ********************************************************************/
58 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
62 if(S_ISDIR(sbuf->st_mode)) {
66 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
67 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
69 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
72 if (fsp && fsp->initial_allocation_size)
73 ret = MAX(ret,fsp->initial_allocation_size);
75 return smb_roundup(conn, ret);
78 /****************************************************************************
79 Utility functions for dealing with extended attributes.
80 ****************************************************************************/
82 static const char *prohibited_ea_names[] = {
83 SAMBA_POSIX_INHERITANCE_EA_NAME,
84 SAMBA_XATTR_DOS_ATTRIB,
88 /****************************************************************************
89 Refuse to allow clients to overwrite our private xattrs.
90 ****************************************************************************/
92 static BOOL samba_private_attr_name(const char *unix_ea_name)
96 for (i = 0; prohibited_ea_names[i]; i++) {
97 if (strequal( prohibited_ea_names[i], unix_ea_name))
103 /****************************************************************************
104 Get one EA value. Fill in a struct ea_struct.
105 ****************************************************************************/
107 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
108 const char *fname, char *ea_name, struct ea_struct *pea)
110 /* Get the value of this xattr. Max size is 64k. */
111 size_t attr_size = 256;
117 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
122 if (fsp && fsp->fd != -1) {
123 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
125 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
128 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
137 DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
138 dump_data(10, val, sizeret);
141 if (strnequal(ea_name, "user.", 5)) {
142 pea->name = &ea_name[5];
146 pea->value.data = (unsigned char *)val;
147 pea->value.length = (size_t)sizeret;
151 /****************************************************************************
152 Return a linked list of the total EA's. Plus the total size
153 ****************************************************************************/
155 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
156 const char *fname, size_t *pea_total_len)
158 /* Get a list of all xattrs. Max namesize is 64k. */
159 size_t ea_namelist_size = 1024;
164 struct ea_list *ea_list_head = NULL;
168 if (!lp_ea_support(SNUM(conn))) {
172 for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
173 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
174 if (fsp && fsp->fd != -1) {
175 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
177 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
180 if (sizeret == -1 && errno == ERANGE) {
181 ea_namelist_size *= 2;
190 DEBUG(10,("get_ea_list_from_file: ea_namelist size = %d\n", sizeret ));
193 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
194 struct ea_list *listp, *tmp;
196 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
199 listp = TALLOC_P(mem_ctx, struct ea_list);
203 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
209 push_ascii_fstring(dos_ea_name, listp->ea.name);
210 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
211 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
212 *pea_total_len, dos_ea_name,
213 (unsigned int)listp->ea.value.length ));
215 DLIST_ADD_END(ea_list_head, listp, tmp);
217 /* Add on 4 for total length. */
218 if (*pea_total_len) {
223 DEBUG(10,("get_ea_list_from_file: total_len = %u\n", *pea_total_len));
227 /****************************************************************************
228 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
230 ****************************************************************************/
232 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
233 connection_struct *conn, struct ea_list *ea_list)
235 unsigned int ret_data_size = 4;
238 SMB_ASSERT(total_data_size >= 4);
240 if (!lp_ea_support(SNUM(conn))) {
245 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
248 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
249 dos_namelen = strlen(dos_ea_name);
250 if (dos_namelen > 255 || dos_namelen == 0) {
253 if (ea_list->ea.value.length > 65535) {
256 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
260 /* We know we have room. */
261 SCVAL(p,0,ea_list->ea.flags);
262 SCVAL(p,1,dos_namelen);
263 SSVAL(p,2,ea_list->ea.value.length);
264 fstrcpy(p+4, dos_ea_name);
265 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
267 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
268 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
271 ret_data_size = PTR_DIFF(p, pdata);
272 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
273 SIVAL(pdata,0,ret_data_size);
274 return ret_data_size;
277 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
279 size_t total_ea_len = 0;
280 TALLOC_CTX *mem_ctx = NULL;
282 if (!lp_ea_support(SNUM(conn))) {
285 mem_ctx = talloc_init("estimate_ea_size");
286 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
287 talloc_destroy(mem_ctx);
291 /****************************************************************************
292 Ensure the EA name is case insensitive by matching any existing EA name.
293 ****************************************************************************/
295 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
298 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
299 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
301 for (; ea_list; ea_list = ea_list->next) {
302 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
303 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
304 &unix_ea_name[5], ea_list->ea.name));
305 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
309 talloc_destroy(mem_ctx);
312 /****************************************************************************
313 Set or delete an extended attribute.
314 ****************************************************************************/
316 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
318 if (!lp_ea_support(SNUM(conn))) {
319 return NT_STATUS_EAS_NOT_SUPPORTED;
322 for (;ea_list; ea_list = ea_list->next) {
324 fstring unix_ea_name;
326 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
327 fstrcat(unix_ea_name, ea_list->ea.name);
329 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
331 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ea_list->ea.value.length));
333 if (samba_private_attr_name(unix_ea_name)) {
334 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
335 return NT_STATUS_ACCESS_DENIED;
338 if (ea_list->ea.value.length == 0) {
339 /* Remove the attribute. */
340 if (fsp && (fsp->fd != -1)) {
341 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
342 unix_ea_name, fsp->fsp_name));
343 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
345 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
346 unix_ea_name, fname));
347 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
350 /* Removing a non existent attribute always succeeds. */
351 if (ret == -1 && errno == ENOATTR) {
352 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
358 if (fsp && (fsp->fd != -1)) {
359 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
360 unix_ea_name, fsp->fsp_name));
361 ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name,
362 ea_list->ea.value.data, ea_list->ea.value.length, 0);
364 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
365 unix_ea_name, fname));
366 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
367 ea_list->ea.value.data, ea_list->ea.value.length, 0);
373 if (errno == ENOTSUP) {
374 return NT_STATUS_EAS_NOT_SUPPORTED;
377 return map_nt_error_from_unix(errno);
383 /****************************************************************************
384 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
385 ****************************************************************************/
387 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
389 struct ea_list *ea_list_head = NULL;
392 while (offset + 2 < data_size) {
394 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
395 unsigned int namelen = CVAL(pdata,offset);
397 offset++; /* Go past the namelen byte. */
399 /* integer wrap paranioa. */
400 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
401 (offset > data_size) || (namelen > data_size) ||
402 (offset + namelen >= data_size)) {
405 /* Ensure the name is null terminated. */
406 if (pdata[offset + namelen] != '\0') {
409 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
414 offset += (namelen + 1); /* Go past the name + terminating zero. */
415 DLIST_ADD_END(ea_list_head, eal, tmp);
416 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
422 /****************************************************************************
423 Read one EA list entry from the buffer.
424 ****************************************************************************/
426 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
428 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
430 unsigned int namelen;
440 eal->ea.flags = CVAL(pdata,0);
441 namelen = CVAL(pdata,1);
442 val_len = SVAL(pdata,2);
444 if (4 + namelen + 1 + val_len > data_size) {
448 /* Ensure the name is null terminated. */
449 if (pdata[namelen + 4] != '\0') {
452 pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
457 eal->ea.value = data_blob(NULL, (size_t)val_len + 1);
458 if (!eal->ea.value.data) {
462 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
464 /* Ensure we're null terminated just in case we print the value. */
465 eal->ea.value.data[val_len] = '\0';
466 /* But don't count the null. */
467 eal->ea.value.length--;
470 *pbytes_used = 4 + namelen + 1 + val_len;
473 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
474 dump_data(10, eal->ea.value.data, eal->ea.value.length);
479 /****************************************************************************
480 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
481 ****************************************************************************/
483 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
485 struct ea_list *ea_list_head = NULL;
487 size_t bytes_used = 0;
489 while (offset < data_size) {
491 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
497 DLIST_ADD_END(ea_list_head, eal, tmp);
498 offset += bytes_used;
504 /****************************************************************************
505 Count the total EA size needed.
506 ****************************************************************************/
508 static size_t ea_list_size(struct ea_list *ealist)
511 struct ea_list *listp;
514 for (listp = ealist; listp; listp = listp->next) {
515 push_ascii_fstring(dos_ea_name, listp->ea.name);
516 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
518 /* Add on 4 for total length. */
526 /****************************************************************************
527 Return a union of EA's from a file list and a list of names.
528 The TALLOC context for the two lists *MUST* be identical as we steal
529 memory from one list to add to another. JRA.
530 ****************************************************************************/
532 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
534 struct ea_list *nlistp, *flistp;
536 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
537 for (flistp = file_list; flistp; flistp = flistp->next) {
538 if (strequal(nlistp->ea.name, flistp->ea.name)) {
544 /* Copy the data from this entry. */
545 nlistp->ea.flags = flistp->ea.flags;
546 nlistp->ea.value = flistp->ea.value;
549 nlistp->ea.flags = 0;
550 ZERO_STRUCT(nlistp->ea.value);
554 *total_ea_len = ea_list_size(name_list);
558 /****************************************************************************
559 Send the required number of replies back.
560 We assume all fields other than the data fields are
561 set correctly for the type of call.
562 HACK ! Always assumes smb_setup field is zero.
563 ****************************************************************************/
565 static int send_trans2_replies(char *outbuf,
572 /* As we are using a protocol > LANMAN1 then the max_send
573 variable must have been set in the sessetupX call.
574 This takes precedence over the max_xmit field in the
575 global struct. These different max_xmit variables should
576 be merged as this is now too confusing */
578 int data_to_send = datasize;
579 int params_to_send = paramsize;
583 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
584 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
585 int data_alignment_offset = 0;
587 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
589 set_message(outbuf,10,0,True);
591 /* If there genuinely are no parameters or data to send just send the empty packet */
593 if(params_to_send == 0 && data_to_send == 0) {
594 if (!send_smb(smbd_server_fd(),outbuf))
595 exit_server("send_trans2_replies: send_smb failed.");
599 /* When sending params and data ensure that both are nicely aligned */
600 /* Only do this alignment when there is also data to send - else
601 can cause NT redirector problems. */
603 if (((params_to_send % 4) != 0) && (data_to_send != 0))
604 data_alignment_offset = 4 - (params_to_send % 4);
606 /* Space is bufsize minus Netbios over TCP header minus SMB header */
607 /* The alignment_offset is to align the param bytes on an even byte
608 boundary. NT 4.0 Beta needs this to work correctly. */
610 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
612 /* useable_space can never be more than max_send minus the alignment offset. */
614 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
616 while (params_to_send || data_to_send) {
617 /* Calculate whether we will totally or partially fill this packet */
619 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
621 /* We can never send more than useable_space */
623 * Note that 'useable_space' does not include the alignment offsets,
624 * but we must include the alignment offsets in the calculation of
625 * the length of the data we send over the wire, as the alignment offsets
626 * are sent here. Fix from Marc_Jacobsen@hp.com.
629 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
631 set_message(outbuf, 10, total_sent_thistime, True);
633 /* Set total params and data to be sent */
634 SSVAL(outbuf,smb_tprcnt,paramsize);
635 SSVAL(outbuf,smb_tdrcnt,datasize);
637 /* Calculate how many parameters and data we can fit into
638 * this packet. Parameters get precedence
641 params_sent_thistime = MIN(params_to_send,useable_space);
642 data_sent_thistime = useable_space - params_sent_thistime;
643 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
645 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
647 /* smb_proff is the offset from the start of the SMB header to the
648 parameter bytes, however the first 4 bytes of outbuf are
649 the Netbios over TCP header. Thus use smb_base() to subtract
650 them from the calculation */
652 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
654 if(params_sent_thistime == 0)
655 SSVAL(outbuf,smb_prdisp,0);
657 /* Absolute displacement of param bytes sent in this packet */
658 SSVAL(outbuf,smb_prdisp,pp - params);
660 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
661 if(data_sent_thistime == 0) {
662 SSVAL(outbuf,smb_droff,0);
663 SSVAL(outbuf,smb_drdisp, 0);
665 /* The offset of the data bytes is the offset of the
666 parameter bytes plus the number of parameters being sent this time */
667 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
668 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
669 SSVAL(outbuf,smb_drdisp, pd - pdata);
672 /* Copy the param bytes into the packet */
674 if(params_sent_thistime)
675 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
677 /* Copy in the data bytes */
678 if(data_sent_thistime)
679 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
680 data_alignment_offset,pd,data_sent_thistime);
682 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
683 params_sent_thistime, data_sent_thistime, useable_space));
684 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
685 params_to_send, data_to_send, paramsize, datasize));
687 /* Send the packet */
688 if (!send_smb(smbd_server_fd(),outbuf))
689 exit_server("send_trans2_replies: send_smb failed.");
691 pp += params_sent_thistime;
692 pd += data_sent_thistime;
694 params_to_send -= params_sent_thistime;
695 data_to_send -= data_sent_thistime;
698 if(params_to_send < 0 || data_to_send < 0) {
699 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
700 params_to_send, data_to_send));
708 /****************************************************************************
709 Reply to a TRANSACT2_OPEN.
710 ****************************************************************************/
712 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
713 char **pparams, int total_params, char **ppdata, int total_data,
714 unsigned int max_data_bytes)
716 char *params = *pparams;
717 char *pdata = *ppdata;
722 BOOL return_additional_info;
731 int fmode=0,mtime=0,rmode;
733 SMB_STRUCT_STAT sbuf;
735 BOOL bad_path = False;
737 TALLOC_CTX *ctx = NULL;
738 struct ea_list *ea_list = NULL;
743 * Ensure we have enough parameters to perform the operation.
746 if (total_params < 29) {
747 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
750 flags = SVAL(params, 0);
751 open_mode = SVAL(params, 2);
752 open_attr = SVAL(params,6);
753 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
754 if (oplock_request) {
755 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
759 return_additional_info = BITSETW(params,0);
760 open_sattr = SVAL(params, 4);
761 open_time = make_unix_date3(params+8);
763 open_ofun = SVAL(params,12);
764 open_size = IVAL(params,14);
768 return(ERROR_DOS(ERRSRV,ERRaccess));
770 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
771 if (!NT_STATUS_IS_OK(status)) {
772 return ERROR_NT(status);
775 DEBUG(3,("call_trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
776 fname,open_mode, open_attr, open_ofun, open_size));
778 /* XXXX we need to handle passed times, sattr and flags */
780 unix_convert(fname,conn,0,&bad_path,&sbuf);
782 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
785 if (!check_name(fname,conn)) {
786 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
789 /* Strange open mode mapping. */
790 if (open_ofun == 0) {
791 if (GET_OPEN_MODE(open_mode) == DOS_OPEN_EXEC) {
792 open_ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST;
796 /* Any data in this call is an EA list. */
797 if (total_data && !lp_ea_support(SNUM(conn))) {
798 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
802 if (total_data < 10) {
803 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
806 if (IVAL(pdata,0) > total_data) {
807 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
808 IVAL(pdata,0), (unsigned int)total_data));
809 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
812 ctx = talloc_init("TRANS2_OPEN_SET_EA");
814 return ERROR_NT(NT_STATUS_NO_MEMORY);
816 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
819 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
823 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
824 oplock_request, &rmode,&smb_action);
828 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
829 /* We have re-scheduled this call. */
832 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
835 size = get_file_size(sbuf);
836 fmode = dos_mode(conn,fname,&sbuf);
837 mtime = sbuf.st_mtime;
841 close_file(fsp,False);
842 return(ERROR_DOS(ERRDOS,ERRnoaccess));
845 if (total_data && smb_action == FILE_WAS_CREATED) {
846 status = set_ea(conn, fsp, fname, ea_list);
848 if (!NT_STATUS_IS_OK(status)) {
849 close_file(fsp,False);
850 return ERROR_NT(status);
854 /* Realloc the size of parameters and data we will return */
855 params = SMB_REALLOC(*pparams, 30);
856 if( params == NULL ) {
857 return ERROR_NT(NT_STATUS_NO_MEMORY);
861 memset((char *)params,'\0',30);
862 SSVAL(params,0,fsp->fnum);
863 SSVAL(params,2,fmode);
864 put_dos_date2(params,4, mtime);
865 SIVAL(params,8, (uint32)size);
866 SSVAL(params,12,rmode);
868 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
869 smb_action |= EXTENDED_OPLOCK_GRANTED;
872 SSVAL(params,18,smb_action);
875 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
877 SIVAL(params,20,inode);
879 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
880 SIVAL(params, 26, ea_size);
883 /* Send the required number of replies */
884 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0);
889 /*********************************************************
890 Routine to check if a given string matches exactly.
891 as a special case a mask of "." does NOT match. That
892 is required for correct wildcard semantics
893 Case can be significant or not.
894 **********************************************************/
896 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
898 if (mask[0] == '.' && mask[1] == 0)
901 return strcmp(str,mask)==0;
902 if (StrCaseCmp(str,mask) != 0) {
905 if (ms_has_wild(str)) {
911 /****************************************************************************
912 Return the filetype for UNIX extensions.
913 ****************************************************************************/
915 static uint32 unix_filetype(mode_t mode)
918 return UNIX_TYPE_FILE;
919 else if(S_ISDIR(mode))
920 return UNIX_TYPE_DIR;
922 else if(S_ISLNK(mode))
923 return UNIX_TYPE_SYMLINK;
926 else if(S_ISCHR(mode))
927 return UNIX_TYPE_CHARDEV;
930 else if(S_ISBLK(mode))
931 return UNIX_TYPE_BLKDEV;
934 else if(S_ISFIFO(mode))
935 return UNIX_TYPE_FIFO;
938 else if(S_ISSOCK(mode))
939 return UNIX_TYPE_SOCKET;
942 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
943 return UNIX_TYPE_UNKNOWN;
946 /****************************************************************************
947 Map wire perms onto standard UNIX permissions. Obey share restrictions.
948 ****************************************************************************/
950 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
954 if (perms == SMB_MODE_NO_CHANGE)
957 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
958 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
959 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
960 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
961 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
962 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
963 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
964 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
965 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
967 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
970 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
973 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
976 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
977 ret &= lp_dir_mask(SNUM(conn));
978 /* Add in force bits */
979 ret |= lp_force_dir_mode(SNUM(conn));
981 /* Apply mode mask */
982 ret &= lp_create_mask(SNUM(conn));
983 /* Add in force bits */
984 ret |= lp_force_create_mode(SNUM(conn));
990 /****************************************************************************
991 Get a level dependent lanman2 dir entry.
992 ****************************************************************************/
994 static BOOL get_lanman2_dir_entry(connection_struct *conn,
995 void *inbuf, void *outbuf,
996 char *path_mask,int dirtype,int info_level,
997 int requires_resume_key,
998 BOOL dont_descend,char **ppdata,
999 char *base_data, int space_remaining,
1000 BOOL *out_of_space, BOOL *got_exact_match,
1001 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1005 SMB_STRUCT_STAT sbuf;
1009 char *p, *q, *pdata = *ppdata;
1013 SMB_OFF_T file_size = 0;
1014 SMB_BIG_UINT allocation_size = 0;
1016 time_t mdate=0, adate=0, cdate=0;
1018 char *last_entry_ptr;
1020 int nt_extmode; /* Used for NT connections instead of mode */
1021 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1024 *out_of_space = False;
1025 *got_exact_match = False;
1030 p = strrchr_m(path_mask,'/');
1033 pstrcpy(mask,"*.*");
1037 pstrcpy(mask, path_mask);
1042 /* Needed if we run out of space */
1043 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1044 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1047 * Due to bugs in NT client redirectors we are not using
1048 * resume keys any more - set them to zero.
1049 * Check out the related comments in findfirst/findnext.
1055 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1056 (long)conn->dirptr,curr_dirpos));
1061 pstrcpy(fname,dname);
1063 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
1064 got_match = mask_match(fname, mask, conn->case_sensitive);
1066 if(!got_match && !mangle_is_8_3(fname, False)) {
1069 * It turns out that NT matches wildcards against
1070 * both long *and* short names. This may explain some
1071 * of the wildcard wierdness from old DOS clients
1072 * that some people have been seeing.... JRA.
1076 pstrcpy( newname, fname);
1077 mangle_map( newname, True, False, SNUM(conn));
1078 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
1079 got_match = mask_match(newname, mask, conn->case_sensitive);
1083 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1084 if (dont_descend && !isdots)
1087 pstrcpy(pathreal,conn->dirpath);
1089 pstrcat(pathreal,"/");
1090 pstrcat(pathreal,dname);
1092 if (INFO_LEVEL_IS_UNIX(info_level)) {
1093 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1094 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1095 pathreal,strerror(errno)));
1098 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1100 /* Needed to show the msdfs symlinks as
1103 if(lp_host_msdfs() &&
1104 lp_msdfs_root(SNUM(conn)) &&
1105 is_msdfs_link(conn, pathreal, NULL, NULL,
1108 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1109 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1113 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1114 pathreal,strerror(errno)));
1119 mode = dos_mode(conn,pathreal,&sbuf);
1121 if (!dir_check_ftype(conn,mode,dirtype)) {
1122 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1126 file_size = get_file_size(sbuf);
1127 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1128 mdate = sbuf.st_mtime;
1129 adate = sbuf.st_atime;
1130 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1132 if (lp_dos_filetime_resolution(SNUM(conn))) {
1139 /* This is necessary, as otherwise the
1140 * desktop.ini file in this folder is
1142 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
1146 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1152 mangle_map(fname,False,True,SNUM(conn));
1157 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1159 switch (info_level) {
1160 case SMB_FIND_INFO_STANDARD:
1161 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1162 if(requires_resume_key) {
1166 put_dos_date2(p,l1_fdateCreation,cdate);
1167 put_dos_date2(p,l1_fdateLastAccess,adate);
1168 put_dos_date2(p,l1_fdateLastWrite,mdate);
1169 SIVAL(p,l1_cbFile,(uint32)file_size);
1170 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
1171 SSVAL(p,l1_attrFile,mode);
1174 p += align_string(outbuf, p, 0);
1175 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1176 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1178 SCVAL(nameptr, -1, len - 2);
1180 SCVAL(nameptr, -1, 0);
1184 SCVAL(nameptr, -1, len - 1);
1186 SCVAL(nameptr, -1, 0);
1192 case SMB_FIND_EA_SIZE:
1193 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1194 if(requires_resume_key) {
1198 put_dos_date2(p,l2_fdateCreation,cdate);
1199 put_dos_date2(p,l2_fdateLastAccess,adate);
1200 put_dos_date2(p,l2_fdateLastWrite,mdate);
1201 SIVAL(p,l2_cbFile,(uint32)file_size);
1202 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1203 SSVAL(p,l2_attrFile,mode);
1205 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1206 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1210 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1211 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1224 SCVAL(nameptr,0,len);
1226 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1229 case SMB_FIND_EA_LIST:
1231 struct ea_list *file_list = NULL;
1234 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1238 if(requires_resume_key) {
1242 put_dos_date2(p,l2_fdateCreation,cdate);
1243 put_dos_date2(p,l2_fdateLastAccess,adate);
1244 put_dos_date2(p,l2_fdateLastWrite,mdate);
1245 SIVAL(p,l2_cbFile,(uint32)file_size);
1246 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1247 SSVAL(p,l2_attrFile,mode);
1248 p += l2_cbList; /* p now points to the EA area. */
1250 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1251 name_list = ea_list_union(name_list, file_list, &ea_len);
1253 /* We need to determine if this entry will fit in the space available. */
1254 /* Max string size is 255 bytes. */
1255 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1256 /* Move the dirptr back to prev_dirpos */
1257 dptr_SeekDir(conn->dirptr, prev_dirpos);
1258 *out_of_space = True;
1259 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1260 return False; /* Not finished - just out of space */
1263 /* Push the ea_data followed by the name. */
1264 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1266 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1267 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1280 SCVAL(nameptr,0,len);
1282 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1286 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1287 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1288 was_8_3 = mangle_is_8_3(fname, True);
1290 SIVAL(p,0,reskey); p += 4;
1291 put_long_date(p,cdate); p += 8;
1292 put_long_date(p,adate); p += 8;
1293 put_long_date(p,mdate); p += 8;
1294 put_long_date(p,mdate); p += 8;
1295 SOFF_T(p,0,file_size); p += 8;
1296 SOFF_T(p,0,allocation_size); p += 8;
1297 SIVAL(p,0,nt_extmode); p += 4;
1298 q = p; p += 4; /* q is placeholder for name length. */
1300 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1301 SIVAL(p,0,ea_size); /* Extended attributes */
1304 /* Clear the short name buffer. This is
1305 * IMPORTANT as not doing so will trigger
1306 * a Win2k client bug. JRA.
1309 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1310 pstring mangled_name;
1311 pstrcpy(mangled_name, fname);
1312 mangle_map(mangled_name,True,True,SNUM(conn));
1313 mangled_name[12] = 0;
1314 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1321 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1324 len = PTR_DIFF(p, pdata);
1325 len = (len + 3) & ~3;
1330 case SMB_FIND_FILE_DIRECTORY_INFO:
1331 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1333 SIVAL(p,0,reskey); p += 4;
1334 put_long_date(p,cdate); p += 8;
1335 put_long_date(p,adate); p += 8;
1336 put_long_date(p,mdate); p += 8;
1337 put_long_date(p,mdate); p += 8;
1338 SOFF_T(p,0,file_size); p += 8;
1339 SOFF_T(p,0,allocation_size); p += 8;
1340 SIVAL(p,0,nt_extmode); p += 4;
1341 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1344 len = PTR_DIFF(p, pdata);
1345 len = (len + 3) & ~3;
1350 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1351 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1353 SIVAL(p,0,reskey); p += 4;
1354 put_long_date(p,cdate); p += 8;
1355 put_long_date(p,adate); p += 8;
1356 put_long_date(p,mdate); p += 8;
1357 put_long_date(p,mdate); p += 8;
1358 SOFF_T(p,0,file_size); p += 8;
1359 SOFF_T(p,0,allocation_size); p += 8;
1360 SIVAL(p,0,nt_extmode); p += 4;
1361 q = p; p += 4; /* q is placeholder for name length. */
1363 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1364 SIVAL(p,0,ea_size); /* Extended attributes */
1367 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1371 len = PTR_DIFF(p, pdata);
1372 len = (len + 3) & ~3;
1377 case SMB_FIND_FILE_NAMES_INFO:
1378 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1380 SIVAL(p,0,reskey); p += 4;
1382 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1383 acl on a dir (tridge) */
1384 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1387 len = PTR_DIFF(p, pdata);
1388 len = (len + 3) & ~3;
1393 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1394 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1396 SIVAL(p,0,reskey); p += 4;
1397 put_long_date(p,cdate); p += 8;
1398 put_long_date(p,adate); p += 8;
1399 put_long_date(p,mdate); p += 8;
1400 put_long_date(p,mdate); p += 8;
1401 SOFF_T(p,0,file_size); p += 8;
1402 SOFF_T(p,0,allocation_size); p += 8;
1403 SIVAL(p,0,nt_extmode); p += 4;
1404 q = p; p += 4; /* q is placeholder for name length. */
1406 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1407 SIVAL(p,0,ea_size); /* Extended attributes */
1410 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1411 SIVAL(p,0,sbuf.st_dev); p += 4;
1412 SIVAL(p,0,sbuf.st_ino); p += 4;
1413 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1416 len = PTR_DIFF(p, pdata);
1417 len = (len + 3) & ~3;
1422 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1423 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1424 was_8_3 = mangle_is_8_3(fname, True);
1426 SIVAL(p,0,reskey); p += 4;
1427 put_long_date(p,cdate); p += 8;
1428 put_long_date(p,adate); p += 8;
1429 put_long_date(p,mdate); p += 8;
1430 put_long_date(p,mdate); p += 8;
1431 SOFF_T(p,0,file_size); p += 8;
1432 SOFF_T(p,0,allocation_size); p += 8;
1433 SIVAL(p,0,nt_extmode); p += 4;
1434 q = p; p += 4; /* q is placeholder for name length */
1436 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1437 SIVAL(p,0,ea_size); /* Extended attributes */
1440 /* Clear the short name buffer. This is
1441 * IMPORTANT as not doing so will trigger
1442 * a Win2k client bug. JRA.
1445 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1446 pstring mangled_name;
1447 pstrcpy(mangled_name, fname);
1448 mangle_map(mangled_name,True,True,SNUM(conn));
1449 mangled_name[12] = 0;
1450 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1457 SSVAL(p,0,0); p += 2; /* Reserved ? */
1458 SIVAL(p,0,sbuf.st_dev); p += 4;
1459 SIVAL(p,0,sbuf.st_ino); p += 4;
1460 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1463 len = PTR_DIFF(p, pdata);
1464 len = (len + 3) & ~3;
1469 /* CIFS UNIX Extension. */
1471 case SMB_FIND_FILE_UNIX:
1472 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1474 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1476 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1477 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1480 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1483 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1484 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1485 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1488 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1492 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1496 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1499 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1503 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1507 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1510 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1514 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1518 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1521 len = PTR_DIFF(p, pdata);
1522 len = (len + 3) & ~3;
1523 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1525 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1534 if (PTR_DIFF(p,pdata) > space_remaining) {
1535 /* Move the dirptr back to prev_dirpos */
1536 dptr_SeekDir(conn->dirptr, prev_dirpos);
1537 *out_of_space = True;
1538 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1539 return False; /* Not finished - just out of space */
1542 /* Setup the last entry pointer, as an offset from base_data */
1543 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1544 /* Advance the data pointer to the next slot */
1550 /****************************************************************************
1551 Reply to a TRANS2_FINDFIRST.
1552 ****************************************************************************/
1554 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1555 char **pparams, int total_params, char **ppdata, int total_data,
1556 unsigned int max_data_bytes)
1558 /* We must be careful here that we don't return more than the
1559 allowed number of data bytes. If this means returning fewer than
1560 maxentries then so be it. We assume that the redirector has
1561 enough room for the fixed number of parameter bytes it has
1563 char *params = *pparams;
1564 char *pdata = *ppdata;
1565 int dirtype = SVAL(params,0);
1566 int maxentries = SVAL(params,2);
1567 uint16 findfirst_flags = SVAL(params,4);
1568 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1569 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1570 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1571 int info_level = SVAL(params,6);
1575 int last_entry_off=0;
1579 BOOL finished = False;
1580 BOOL dont_descend = False;
1581 BOOL out_of_space = False;
1582 int space_remaining;
1583 BOOL bad_path = False;
1584 SMB_STRUCT_STAT sbuf;
1585 TALLOC_CTX *ea_ctx = NULL;
1586 struct ea_list *ea_list = NULL;
1587 NTSTATUS ntstatus = NT_STATUS_OK;
1589 if (total_params < 12) {
1590 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1593 *directory = *mask = 0;
1595 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1596 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1597 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1598 info_level, max_data_bytes));
1601 /* W2K3 seems to treat zero as 1. */
1605 switch (info_level) {
1606 case SMB_FIND_INFO_STANDARD:
1607 case SMB_FIND_EA_SIZE:
1608 case SMB_FIND_EA_LIST:
1609 case SMB_FIND_FILE_DIRECTORY_INFO:
1610 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1611 case SMB_FIND_FILE_NAMES_INFO:
1612 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1613 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1614 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1616 case SMB_FIND_FILE_UNIX:
1617 if (!lp_unix_extensions())
1618 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1621 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1624 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1625 if (!NT_STATUS_IS_OK(ntstatus)) {
1626 return ERROR_NT(ntstatus);
1629 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1631 unix_convert(directory,conn,0,&bad_path,&sbuf);
1633 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1635 if(!check_name(directory,conn)) {
1636 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1639 p = strrchr_m(directory,'/');
1641 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1642 if((directory[0] == '.') && (directory[1] == '\0'))
1645 pstrcpy(mask,directory);
1646 pstrcpy(directory,"./");
1652 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1654 if (info_level == SMB_FIND_EA_LIST) {
1657 if (total_data < 4) {
1658 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1661 ea_size = IVAL(pdata,0);
1662 if (ea_size != total_data) {
1663 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1664 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1665 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1668 if (!lp_ea_support(SNUM(conn))) {
1669 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1672 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1673 return ERROR_NT(NT_STATUS_NO_MEMORY);
1676 /* Pull out the list of names. */
1677 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1679 talloc_destroy(ea_ctx);
1680 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1684 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1685 if( pdata == NULL ) {
1686 talloc_destroy(ea_ctx);
1687 return ERROR_NT(NT_STATUS_NO_MEMORY);
1691 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1693 /* Realloc the params space */
1694 params = SMB_REALLOC(*pparams, 10);
1695 if (params == NULL) {
1696 talloc_destroy(ea_ctx);
1697 return ERROR_NT(NT_STATUS_NO_MEMORY);
1701 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1703 talloc_destroy(ea_ctx);
1704 return(UNIXERROR(ERRDOS,ERRbadfile));
1707 /* Save the wildcard match and attribs we are using on this directory -
1708 needed as lanman2 assumes these are being saved between calls */
1710 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1711 dptr_close(&dptr_num);
1712 talloc_destroy(ea_ctx);
1713 return ERROR_NT(NT_STATUS_NO_MEMORY);
1716 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1718 /* We don't need to check for VOL here as this is returned by
1719 a different TRANS2 call. */
1721 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1722 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1723 dont_descend = True;
1726 space_remaining = max_data_bytes;
1727 out_of_space = False;
1729 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1730 BOOL got_exact_match = False;
1732 /* this is a heuristic to avoid seeking the dirptr except when
1733 absolutely necessary. It allows for a filename of about 40 chars */
1734 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1735 out_of_space = True;
1738 finished = !get_lanman2_dir_entry(conn,
1740 mask,dirtype,info_level,
1741 requires_resume_key,dont_descend,
1742 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1743 &last_entry_off, ea_list, ea_ctx);
1746 if (finished && out_of_space)
1749 if (!finished && !out_of_space)
1753 * As an optimisation if we know we aren't looking
1754 * for a wildcard name (ie. the name matches the wildcard exactly)
1755 * then we can finish on any (first) match.
1756 * This speeds up large directory searches. JRA.
1762 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1765 talloc_destroy(ea_ctx);
1767 /* Check if we can close the dirptr */
1768 if(close_after_first || (finished && close_if_end)) {
1769 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1770 dptr_close(&dptr_num);
1774 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1775 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1776 * the protocol level is less than NT1. Tested with smbclient. JRA.
1777 * This should fix the OS/2 client bug #2335.
1780 if(numentries == 0) {
1781 dptr_close(&dptr_num);
1782 if (Protocol < PROTOCOL_NT1) {
1783 return ERROR_DOS(ERRDOS,ERRnofiles);
1785 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1789 /* At this point pdata points to numentries directory entries. */
1791 /* Set up the return parameter block */
1792 SSVAL(params,0,dptr_num);
1793 SSVAL(params,2,numentries);
1794 SSVAL(params,4,finished);
1795 SSVAL(params,6,0); /* Never an EA error */
1796 SSVAL(params,8,last_entry_off);
1798 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1800 if ((! *directory) && dptr_path(dptr_num))
1801 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1803 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1804 smb_fn_name(CVAL(inbuf,smb_com)),
1805 mask, directory, dirtype, numentries ) );
1808 * Force a name mangle here to ensure that the
1809 * mask as an 8.3 name is top of the mangled cache.
1810 * The reasons for this are subtle. Don't remove
1811 * this code unless you know what you are doing
1812 * (see PR#13758). JRA.
1815 if(!mangle_is_8_3_wildcards( mask, False))
1816 mangle_map(mask, True, True, SNUM(conn));
1821 /****************************************************************************
1822 Reply to a TRANS2_FINDNEXT.
1823 ****************************************************************************/
1825 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1826 char **pparams, int total_params, char **ppdata, int total_data,
1827 unsigned int max_data_bytes)
1829 /* We must be careful here that we don't return more than the
1830 allowed number of data bytes. If this means returning fewer than
1831 maxentries then so be it. We assume that the redirector has
1832 enough room for the fixed number of parameter bytes it has
1834 char *params = *pparams;
1835 char *pdata = *ppdata;
1836 int dptr_num = SVAL(params,0);
1837 int maxentries = SVAL(params,2);
1838 uint16 info_level = SVAL(params,4);
1839 uint32 resume_key = IVAL(params,6);
1840 uint16 findnext_flags = SVAL(params,10);
1841 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1842 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1843 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1844 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1845 pstring resume_name;
1851 int i, last_entry_off=0;
1852 BOOL finished = False;
1853 BOOL dont_descend = False;
1854 BOOL out_of_space = False;
1855 int space_remaining;
1856 TALLOC_CTX *ea_ctx = NULL;
1857 struct ea_list *ea_list = NULL;
1858 NTSTATUS ntstatus = NT_STATUS_OK;
1860 if (total_params < 12) {
1861 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1864 *mask = *directory = *resume_name = 0;
1866 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1867 if (!NT_STATUS_IS_OK(ntstatus)) {
1868 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1869 complain (it thinks we're asking for the directory above the shared
1870 path or an invalid name). Catch this as the resume name is only compared, never used in
1871 a file access. JRA. */
1872 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1873 pstrcpy(resume_name, "..");
1874 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1875 pstrcpy(resume_name, ".");
1877 return ERROR_NT(ntstatus);
1881 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1882 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1883 resume_key = %d resume name = %s continue=%d level = %d\n",
1884 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1885 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1888 /* W2K3 seems to treat zero as 1. */
1892 switch (info_level) {
1893 case SMB_FIND_INFO_STANDARD:
1894 case SMB_FIND_EA_SIZE:
1895 case SMB_FIND_EA_LIST:
1896 case SMB_FIND_FILE_DIRECTORY_INFO:
1897 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1898 case SMB_FIND_FILE_NAMES_INFO:
1899 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1901 case SMB_FIND_FILE_UNIX:
1902 if (!lp_unix_extensions())
1903 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1906 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1909 if (info_level == SMB_FIND_EA_LIST) {
1912 if (total_data < 4) {
1913 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1916 ea_size = IVAL(pdata,0);
1917 if (ea_size != total_data) {
1918 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1919 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1920 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1923 if (!lp_ea_support(SNUM(conn))) {
1924 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1927 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1928 return ERROR_NT(NT_STATUS_NO_MEMORY);
1931 /* Pull out the list of names. */
1932 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1934 talloc_destroy(ea_ctx);
1935 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1939 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1941 talloc_destroy(ea_ctx);
1942 return ERROR_NT(NT_STATUS_NO_MEMORY);
1946 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1948 /* Realloc the params space */
1949 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1950 if( params == NULL ) {
1951 talloc_destroy(ea_ctx);
1952 return ERROR_NT(NT_STATUS_NO_MEMORY);
1957 /* Check that the dptr is valid */
1958 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
1959 talloc_destroy(ea_ctx);
1960 return ERROR_DOS(ERRDOS,ERRnofiles);
1963 string_set(&conn->dirpath,dptr_path(dptr_num));
1965 /* Get the wildcard mask from the dptr */
1966 if((p = dptr_wcard(dptr_num))== NULL) {
1967 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1968 talloc_destroy(ea_ctx);
1969 return ERROR_DOS(ERRDOS,ERRnofiles);
1973 pstrcpy(directory,conn->dirpath);
1975 /* Get the attr mask from the dptr */
1976 dirtype = dptr_attr(dptr_num);
1978 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
1979 dptr_num, mask, dirtype,
1981 dptr_TellDir(conn->dirptr)));
1983 /* We don't need to check for VOL here as this is returned by
1984 a different TRANS2 call. */
1986 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1987 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1988 dont_descend = True;
1991 space_remaining = max_data_bytes;
1992 out_of_space = False;
1995 * Seek to the correct position. We no longer use the resume key but
1996 * depend on the last file name instead.
1999 if(*resume_name && !continue_bit) {
2002 long current_pos = 0;
2004 * Remember, mangle_map is called by
2005 * get_lanman2_dir_entry(), so the resume name
2006 * could be mangled. Ensure we check the unmangled name.
2009 if (mangle_is_mangled(resume_name)) {
2010 mangle_check_cache(resume_name, sizeof(resume_name)-1);
2014 * Fix for NT redirector problem triggered by resume key indexes
2015 * changing between directory scans. We now return a resume key of 0
2016 * and instead look for the filename to continue from (also given
2017 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2018 * findfirst/findnext (as is usual) then the directory pointer
2019 * should already be at the correct place.
2022 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2023 } /* end if resume_name && !continue_bit */
2025 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2026 BOOL got_exact_match = False;
2028 /* this is a heuristic to avoid seeking the dirptr except when
2029 absolutely necessary. It allows for a filename of about 40 chars */
2030 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2031 out_of_space = True;
2034 finished = !get_lanman2_dir_entry(conn,
2036 mask,dirtype,info_level,
2037 requires_resume_key,dont_descend,
2038 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2039 &last_entry_off, ea_list, ea_ctx);
2042 if (finished && out_of_space)
2045 if (!finished && !out_of_space)
2049 * As an optimisation if we know we aren't looking
2050 * for a wildcard name (ie. the name matches the wildcard exactly)
2051 * then we can finish on any (first) match.
2052 * This speeds up large directory searches. JRA.
2058 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2061 talloc_destroy(ea_ctx);
2063 /* Check if we can close the dirptr */
2064 if(close_after_request || (finished && close_if_end)) {
2065 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2066 dptr_close(&dptr_num); /* This frees up the saved mask */
2069 /* Set up the return parameter block */
2070 SSVAL(params,0,numentries);
2071 SSVAL(params,2,finished);
2072 SSVAL(params,4,0); /* Never an EA error */
2073 SSVAL(params,6,last_entry_off);
2075 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2077 if ((! *directory) && dptr_path(dptr_num))
2078 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2080 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2081 smb_fn_name(CVAL(inbuf,smb_com)),
2082 mask, directory, dirtype, numentries ) );
2087 /****************************************************************************
2088 Reply to a TRANS2_QFSINFO (query filesystem info).
2089 ****************************************************************************/
2091 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2092 char **pparams, int total_params, char **ppdata, int total_data,
2093 unsigned int max_data_bytes)
2095 char *pdata = *ppdata;
2096 char *params = *pparams;
2097 uint16 info_level = SVAL(params,0);
2100 char *vname = volume_label(SNUM(conn));
2101 int snum = SNUM(conn);
2102 char *fstype = lp_fstype(SNUM(conn));
2105 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2107 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2108 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2109 return ERROR_DOS(ERRSRV,ERRinvdevice);
2112 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2113 if ( pdata == NULL ) {
2114 return ERROR_NT(NT_STATUS_NO_MEMORY);
2118 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2120 switch (info_level) {
2121 case SMB_INFO_ALLOCATION:
2123 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2125 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2126 return(UNIXERROR(ERRHRD,ERRgeneral));
2129 block_size = lp_block_size(snum);
2130 if (bsize < block_size) {
2131 SMB_BIG_UINT factor = block_size/bsize;
2136 if (bsize > block_size) {
2137 SMB_BIG_UINT factor = bsize/block_size;
2142 bytes_per_sector = 512;
2143 sectors_per_unit = bsize/bytes_per_sector;
2145 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2146 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2147 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2149 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2150 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2151 SIVAL(pdata,l1_cUnit,dsize);
2152 SIVAL(pdata,l1_cUnitAvail,dfree);
2153 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2157 case SMB_INFO_VOLUME:
2158 /* Return volume name */
2160 * Add volume serial number - hash of a combination of
2161 * the called hostname and the service name.
2163 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2165 * Win2k3 and previous mess this up by sending a name length
2166 * one byte short. I believe only older clients (OS/2 Win9x) use
2167 * this call so try fixing this by adding a terminating null to
2168 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2170 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2171 SCVAL(pdata,l2_vol_cch,len);
2172 data_len = l2_vol_szVolLabel + len;
2173 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2174 (unsigned)st.st_ctime, len, vname));
2177 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2178 case SMB_FS_ATTRIBUTE_INFORMATION:
2181 #if defined(HAVE_SYS_QUOTAS)
2182 quota_flag = FILE_VOLUME_QUOTAS;
2185 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2186 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2187 quota_flag); /* FS ATTRIBUTES */
2189 SIVAL(pdata,4,255); /* Max filename component length */
2190 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2191 and will think we can't do long filenames */
2192 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2194 data_len = 12 + len;
2197 case SMB_QUERY_FS_LABEL_INFO:
2198 case SMB_FS_LABEL_INFORMATION:
2199 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2204 case SMB_QUERY_FS_VOLUME_INFO:
2205 case SMB_FS_VOLUME_INFORMATION:
2208 * Add volume serial number - hash of a combination of
2209 * the called hostname and the service name.
2211 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2212 (str_checksum(get_local_machine_name())<<16));
2214 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2215 SIVAL(pdata,12,len);
2217 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2218 (int)strlen(vname),vname, lp_servicename(snum)));
2221 case SMB_QUERY_FS_SIZE_INFO:
2222 case SMB_FS_SIZE_INFORMATION:
2224 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2226 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2227 return(UNIXERROR(ERRHRD,ERRgeneral));
2229 block_size = lp_block_size(snum);
2230 if (bsize < block_size) {
2231 SMB_BIG_UINT factor = block_size/bsize;
2236 if (bsize > block_size) {
2237 SMB_BIG_UINT factor = bsize/block_size;
2242 bytes_per_sector = 512;
2243 sectors_per_unit = bsize/bytes_per_sector;
2244 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2245 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2246 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2247 SBIG_UINT(pdata,0,dsize);
2248 SBIG_UINT(pdata,8,dfree);
2249 SIVAL(pdata,16,sectors_per_unit);
2250 SIVAL(pdata,20,bytes_per_sector);
2254 case SMB_FS_FULL_SIZE_INFORMATION:
2256 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2258 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2259 return(UNIXERROR(ERRHRD,ERRgeneral));
2261 block_size = lp_block_size(snum);
2262 if (bsize < block_size) {
2263 SMB_BIG_UINT factor = block_size/bsize;
2268 if (bsize > block_size) {
2269 SMB_BIG_UINT factor = bsize/block_size;
2274 bytes_per_sector = 512;
2275 sectors_per_unit = bsize/bytes_per_sector;
2276 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2277 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2278 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2279 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2280 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2281 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2282 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2283 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2287 case SMB_QUERY_FS_DEVICE_INFO:
2288 case SMB_FS_DEVICE_INFORMATION:
2290 SIVAL(pdata,0,0); /* dev type */
2291 SIVAL(pdata,4,0); /* characteristics */
2294 #ifdef HAVE_SYS_QUOTAS
2295 case SMB_FS_QUOTA_INFORMATION:
2297 * what we have to send --metze:
2299 * Unknown1: 24 NULL bytes
2300 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2301 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2302 * Quota Flags: 2 byte :
2303 * Unknown3: 6 NULL bytes
2307 * details for Quota Flags:
2309 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2310 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2311 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2312 * 0x0001 Enable Quotas: enable quota for this fs
2316 /* we need to fake up a fsp here,
2317 * because its not send in this call
2320 SMB_NTQUOTA_STRUCT quotas;
2323 ZERO_STRUCT(quotas);
2330 if (current_user.uid != 0) {
2331 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2332 lp_servicename(SNUM(conn)),conn->user));
2333 return ERROR_DOS(ERRDOS,ERRnoaccess);
2336 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2337 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2338 return ERROR_DOS(ERRSRV,ERRerror);
2343 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2345 /* Unknown1 24 NULL bytes*/
2346 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2347 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2348 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2350 /* Default Soft Quota 8 bytes */
2351 SBIG_UINT(pdata,24,quotas.softlim);
2353 /* Default Hard Quota 8 bytes */
2354 SBIG_UINT(pdata,32,quotas.hardlim);
2356 /* Quota flag 2 bytes */
2357 SSVAL(pdata,40,quotas.qflags);
2359 /* Unknown3 6 NULL bytes */
2365 #endif /* HAVE_SYS_QUOTAS */
2366 case SMB_FS_OBJECTID_INFORMATION:
2371 * Query the version and capabilities of the CIFS UNIX extensions
2375 case SMB_QUERY_CIFS_UNIX_INFO:
2376 if (!lp_unix_extensions())
2377 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2379 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2380 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2381 SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
2384 case SMB_MAC_QUERY_FS_INFO:
2386 * Thursby MAC extension... ONLY on NTFS filesystems
2387 * once we do streams then we don't need this
2389 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2391 SIVAL(pdata,84,0x100); /* Don't support mac... */
2396 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2400 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2402 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2407 #ifdef HAVE_SYS_QUOTAS
2408 /****************************************************************************
2409 Reply to a TRANS2_SETFSINFO (set filesystem info).
2410 ****************************************************************************/
2412 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2413 char **pparams, int total_params, char **ppdata, int total_data,
2414 unsigned int max_data_bytes)
2416 char *pdata = *ppdata;
2417 char *params = *pparams;
2418 files_struct *fsp = NULL;
2421 SMB_NTQUOTA_STRUCT quotas;
2423 ZERO_STRUCT(quotas);
2425 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2428 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2429 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2430 lp_servicename(SNUM(conn)),conn->user));
2431 return ERROR_DOS(ERRSRV,ERRaccess);
2435 if (total_params < 4) {
2436 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2438 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2441 fsp = file_fsp(params,0);
2443 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2444 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2445 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2448 info_level = SVAL(params,2);
2450 switch(info_level) {
2451 case SMB_FS_QUOTA_INFORMATION:
2452 /* note: normaly there're 48 bytes,
2453 * but we didn't use the last 6 bytes for now
2456 if (total_data < 42) {
2457 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2459 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2462 /* unknown_1 24 NULL bytes in pdata*/
2464 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2465 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2466 #ifdef LARGE_SMB_OFF_T
2467 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2468 #else /* LARGE_SMB_OFF_T */
2469 if ((IVAL(pdata,28) != 0)&&
2470 ((quotas.softlim != 0xFFFFFFFF)||
2471 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2472 /* more than 32 bits? */
2473 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2475 #endif /* LARGE_SMB_OFF_T */
2477 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2478 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2479 #ifdef LARGE_SMB_OFF_T
2480 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2481 #else /* LARGE_SMB_OFF_T */
2482 if ((IVAL(pdata,36) != 0)&&
2483 ((quotas.hardlim != 0xFFFFFFFF)||
2484 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2485 /* more than 32 bits? */
2486 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2488 #endif /* LARGE_SMB_OFF_T */
2490 /* quota_flags 2 bytes **/
2491 quotas.qflags = SVAL(pdata,40);
2493 /* unknown_2 6 NULL bytes follow*/
2495 /* now set the quotas */
2496 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2497 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2498 return ERROR_DOS(ERRSRV,ERRerror);
2503 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2505 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2510 * sending this reply works fine,
2511 * but I'm not sure it's the same
2512 * like windows do...
2515 outsize = set_message(outbuf,10,0,True);
2519 #endif /* HAVE_SYS_QUOTAS */
2521 /****************************************************************************
2522 Utility function to set bad path error.
2523 ****************************************************************************/
2525 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2527 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2528 err, (int)bad_path ));
2532 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2534 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2537 return UNIXERROR(def_class,def_code);
2540 #if defined(HAVE_POSIX_ACLS)
2541 /****************************************************************************
2542 Utility function to count the number of entries in a POSIX acl.
2543 ****************************************************************************/
2545 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2547 unsigned int ace_count = 0;
2548 int entry_id = SMB_ACL_FIRST_ENTRY;
2549 SMB_ACL_ENTRY_T entry;
2551 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2553 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2554 entry_id = SMB_ACL_NEXT_ENTRY;
2561 /****************************************************************************
2562 Utility function to marshall a POSIX acl into wire format.
2563 ****************************************************************************/
2565 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2567 int entry_id = SMB_ACL_FIRST_ENTRY;
2568 SMB_ACL_ENTRY_T entry;
2570 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2571 SMB_ACL_TAG_T tagtype;
2572 SMB_ACL_PERMSET_T permset;
2573 unsigned char perms = 0;
2574 unsigned int own_grp;
2577 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2578 entry_id = SMB_ACL_NEXT_ENTRY;
2581 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2582 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2586 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2587 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2591 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2592 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2593 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2595 SCVAL(pdata,1,perms);
2598 case SMB_ACL_USER_OBJ:
2599 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2600 own_grp = (unsigned int)pst->st_uid;
2601 SIVAL(pdata,2,own_grp);
2606 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2608 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2610 own_grp = (unsigned int)*puid;
2611 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2612 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2613 SIVAL(pdata,2,own_grp);
2617 case SMB_ACL_GROUP_OBJ:
2618 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2619 own_grp = (unsigned int)pst->st_gid;
2620 SIVAL(pdata,2,own_grp);
2625 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2627 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2629 own_grp = (unsigned int)*pgid;
2630 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2631 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2632 SIVAL(pdata,2,own_grp);
2637 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2638 SIVAL(pdata,2,0xFFFFFFFF);
2639 SIVAL(pdata,6,0xFFFFFFFF);
2642 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2643 SIVAL(pdata,2,0xFFFFFFFF);
2644 SIVAL(pdata,6,0xFFFFFFFF);
2647 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2650 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2657 /****************************************************************************
2658 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2659 file name or file id).
2660 ****************************************************************************/
2662 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2663 char **pparams, int total_params, char **ppdata, int total_data,
2664 unsigned int max_data_bytes)
2666 char *params = *pparams;
2667 char *pdata = *ppdata;
2668 uint16 tran_call = SVAL(inbuf, smb_setup0);
2671 SMB_OFF_T file_size=0;
2672 SMB_BIG_UINT allocation_size=0;
2673 unsigned int data_size = 0;
2674 unsigned int param_size = 2;
2675 SMB_STRUCT_STAT sbuf;
2676 pstring fname, dos_fname;
2681 BOOL bad_path = False;
2682 BOOL delete_pending = False;
2685 files_struct *fsp = NULL;
2686 TALLOC_CTX *ea_ctx = NULL;
2687 struct ea_list *ea_list = NULL;
2688 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2691 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2695 if (tran_call == TRANSACT2_QFILEINFO) {
2696 if (total_params < 4) {
2697 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2700 fsp = file_fsp(params,0);
2701 info_level = SVAL(params,2);
2703 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2705 if(fsp && (fsp->fake_file_handle)) {
2707 * This is actually for the QUOTA_FAKE_FILE --metze
2710 pstrcpy(fname, fsp->fsp_name);
2711 /* We know this name is ok, it's already passed the checks. */
2713 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2715 * This is actually a QFILEINFO on a directory
2716 * handle (returned from an NT SMB). NT5.0 seems
2717 * to do this call. JRA.
2719 /* We know this name is ok, it's already passed the checks. */
2720 pstrcpy(fname, fsp->fsp_name);
2722 if (INFO_LEVEL_IS_UNIX(info_level)) {
2723 /* Always do lstat for UNIX calls. */
2724 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2725 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2726 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2728 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2729 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2730 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2733 delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2736 * Original code - this is an open file.
2738 CHECK_FSP(fsp,conn);
2740 pstrcpy(fname, fsp->fsp_name);
2741 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2742 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2743 return(UNIXERROR(ERRDOS,ERRbadfid));
2745 pos = fsp->position_information;
2746 delete_pending = fsp->delete_on_close;
2747 desired_access = fsp->desired_access;
2750 NTSTATUS status = NT_STATUS_OK;
2753 if (total_params < 6) {
2754 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2757 info_level = SVAL(params,0);
2759 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2761 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2762 if (!NT_STATUS_IS_OK(status)) {
2763 return ERROR_NT(status);
2766 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2768 unix_convert(fname,conn,0,&bad_path,&sbuf);
2770 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2772 if (!check_name(fname,conn)) {
2773 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2774 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2777 if (INFO_LEVEL_IS_UNIX(info_level)) {
2778 /* Always do lstat for UNIX calls. */
2779 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2780 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2781 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2783 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2784 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2785 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2789 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2790 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2792 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2793 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2795 p = strrchr_m(fname,'/');
2801 mode = dos_mode(conn,fname,&sbuf);
2803 mode = FILE_ATTRIBUTE_NORMAL;
2805 fullpathname = fname;
2806 file_size = get_file_size(sbuf);
2808 /* This is necessary, as otherwise the desktop.ini file in
2809 * this folder is ignored */
2810 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2814 /* Pull any EA list from the data portion. */
2815 if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2818 if (total_data < 4) {
2819 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2821 ea_size = IVAL(pdata,0);
2823 if (total_data > 0 && ea_size != total_data) {
2824 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2825 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2826 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2829 if (!lp_ea_support(SNUM(conn))) {
2830 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2833 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2834 return ERROR_NT(NT_STATUS_NO_MEMORY);
2837 /* Pull out the list of names. */
2838 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2840 talloc_destroy(ea_ctx);
2841 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2845 params = SMB_REALLOC(*pparams,2);
2846 if (params == NULL) {
2847 talloc_destroy(ea_ctx);
2848 return ERROR_NT(NT_STATUS_NO_MEMORY);
2851 memset((char *)params,'\0',2);
2852 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2853 pdata = SMB_REALLOC(*ppdata, data_size);
2854 if ( pdata == NULL ) {
2855 talloc_destroy(ea_ctx);
2856 return ERROR_NT(NT_STATUS_NO_MEMORY);
2860 memset((char *)pdata,'\0',data_size);
2862 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2864 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2867 if (fsp->pending_modtime) {
2868 /* the pending modtime overrides the current modtime */
2869 sbuf.st_mtime = fsp->pending_modtime;
2872 /* Do we have this path open ? */
2873 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2874 if (fsp1 && fsp1->pending_modtime) {
2875 /* the pending modtime overrides the current modtime */
2876 sbuf.st_mtime = fsp1->pending_modtime;
2878 if (fsp1 && fsp1->initial_allocation_size) {
2879 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
2883 if (lp_dos_filetime_resolution(SNUM(conn))) {
2885 sbuf.st_atime &= ~1;
2886 sbuf.st_ctime &= ~1;
2887 sbuf.st_mtime &= ~1;
2890 /* NT expects the name to be in an exact form of the *full*
2891 filename. See the trans2 torture test */
2892 if (strequal(base_name,".")) {
2893 pstrcpy(dos_fname, "\\");
2895 pstr_sprintf(dos_fname, "\\%s", fname);
2896 string_replace(dos_fname, '/', '\\');
2899 switch (info_level) {
2900 case SMB_INFO_STANDARD:
2901 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2903 put_dos_date2(pdata,l1_fdateCreation,c_time);
2904 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2905 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2906 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2907 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2908 SSVAL(pdata,l1_attrFile,mode);
2911 case SMB_INFO_QUERY_EA_SIZE:
2913 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2914 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2916 put_dos_date2(pdata,l1_fdateCreation,c_time);
2917 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2918 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2919 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2920 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2921 SSVAL(pdata,l1_attrFile,mode);
2922 SIVAL(pdata,l1_attrFile+2,ea_size);
2926 case SMB_INFO_IS_NAME_VALID:
2927 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2928 if (tran_call == TRANSACT2_QFILEINFO) {
2929 /* os/2 needs this ? really ?*/
2930 return ERROR_DOS(ERRDOS,ERRbadfunc);
2936 case SMB_INFO_QUERY_EAS_FROM_LIST:
2938 size_t total_ea_len = 0;
2939 struct ea_list *ea_file_list = NULL;
2941 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2943 ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2944 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
2946 if (!ea_list || (total_ea_len > data_size)) {
2947 talloc_destroy(ea_ctx);
2949 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
2953 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
2954 talloc_destroy(ea_ctx);
2958 case SMB_INFO_QUERY_ALL_EAS:
2960 /* We have data_size bytes to put EA's into. */
2961 size_t total_ea_len = 0;
2963 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2965 ea_ctx = talloc_init("ea_ctx");
2967 return ERROR_NT(NT_STATUS_NO_MEMORY);
2970 ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2971 if (!ea_list || (total_ea_len > data_size)) {
2972 talloc_destroy(ea_ctx);
2974 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
2978 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
2979 talloc_destroy(ea_ctx);
2983 case SMB_FILE_BASIC_INFORMATION:
2984 case SMB_QUERY_FILE_BASIC_INFO:
2986 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2987 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2988 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2990 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2994 put_long_date(pdata,c_time);
2995 put_long_date(pdata+8,sbuf.st_atime);
2996 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2997 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2998 SIVAL(pdata,32,mode);
3000 DEBUG(5,("SMB_QFBI - "));
3002 time_t create_time = c_time;
3003 DEBUG(5,("create: %s ", ctime(&create_time)));
3005 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3006 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3007 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3008 DEBUG(5,("mode: %x\n", mode));
3012 case SMB_FILE_STANDARD_INFORMATION:
3013 case SMB_QUERY_FILE_STANDARD_INFO:
3015 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3017 SOFF_T(pdata,0,allocation_size);
3018 SOFF_T(pdata,8,file_size);
3019 if (delete_pending & sbuf.st_nlink)
3020 SIVAL(pdata,16,sbuf.st_nlink - 1);
3022 SIVAL(pdata,16,sbuf.st_nlink);
3024 SCVAL(pdata,21,(mode&aDIR)?1:0);
3027 case SMB_FILE_EA_INFORMATION:
3028 case SMB_QUERY_FILE_EA_INFO:
3030 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3031 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3033 SIVAL(pdata,0,ea_size);
3037 /* Get the 8.3 name - used if NT SMB was negotiated. */
3038 case SMB_QUERY_FILE_ALT_NAME_INFO:
3039 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3043 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3044 pstrcpy(short_name,base_name);
3045 /* Mangle if not already 8.3 */
3046 if(!mangle_is_8_3(short_name, True)) {
3047 mangle_map(short_name,True,True,SNUM(conn));
3049 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3050 data_size = 4 + len;
3055 case SMB_QUERY_FILE_NAME_INFO:
3057 this must be *exactly* right for ACLs on mapped drives to work
3059 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3060 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3061 data_size = 4 + len;
3065 case SMB_FILE_ALLOCATION_INFORMATION:
3066 case SMB_QUERY_FILE_ALLOCATION_INFO:
3067 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3069 SOFF_T(pdata,0,allocation_size);
3072 case SMB_FILE_END_OF_FILE_INFORMATION:
3073 case SMB_QUERY_FILE_END_OF_FILEINFO:
3074 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3076 SOFF_T(pdata,0,file_size);
3079 case SMB_QUERY_FILE_ALL_INFO:
3080 case SMB_FILE_ALL_INFORMATION:
3082 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3083 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3084 put_long_date(pdata,c_time);
3085 put_long_date(pdata+8,sbuf.st_atime);
3086 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3087 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3088 SIVAL(pdata,32,mode);
3090 SOFF_T(pdata,0,allocation_size);
3091 SOFF_T(pdata,8,file_size);
3092 if (delete_pending && sbuf.st_nlink)
3093 SIVAL(pdata,16,sbuf.st_nlink - 1);
3095 SIVAL(pdata,16,sbuf.st_nlink);
3096 SCVAL(pdata,20,delete_pending);
3097 SCVAL(pdata,21,(mode&aDIR)?1:0);
3099 SIVAL(pdata,0,ea_size);
3100 pdata += 4; /* EA info */
3101 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3104 data_size = PTR_DIFF(pdata,(*ppdata));
3107 case SMB_FILE_INTERNAL_INFORMATION:
3108 /* This should be an index number - looks like
3111 I think this causes us to fail the IFSKIT
3112 BasicFileInformationTest. -tpot */
3114 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3115 SIVAL(pdata,0,sbuf.st_dev);
3116 SIVAL(pdata,4,sbuf.st_ino);
3120 case SMB_FILE_ACCESS_INFORMATION:
3121 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3122 SIVAL(pdata,0,desired_access);
3126 case SMB_FILE_NAME_INFORMATION:
3127 /* Pathname with leading '\'. */
3130 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
3131 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3132 SIVAL(pdata,0,byte_len);
3133 data_size = 4 + byte_len;
3137 case SMB_FILE_DISPOSITION_INFORMATION:
3138 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3140 SCVAL(pdata,0,delete_pending);
3143 case SMB_FILE_POSITION_INFORMATION:
3144 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3146 SOFF_T(pdata,0,pos);
3149 case SMB_FILE_MODE_INFORMATION:
3150 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3151 SIVAL(pdata,0,mode);
3155 case SMB_FILE_ALIGNMENT_INFORMATION:
3156 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3157 SIVAL(pdata,0,0); /* No alignment needed. */
3163 * NT4 server just returns "invalid query" to this - if we try to answer
3164 * it then NTws gets a BSOD! (tridge).
3165 * W2K seems to want this. JRA.
3167 case SMB_QUERY_FILE_STREAM_INFO:
3169 case SMB_FILE_STREAM_INFORMATION:
3170 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3174 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
3175 SIVAL(pdata,0,0); /* ??? */
3176 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3177 SOFF_T(pdata,8,file_size);
3178 SIVAL(pdata,16,allocation_size);
3179 SIVAL(pdata,20,0); /* ??? */
3180 data_size = 24 + byte_len;
3184 case SMB_QUERY_COMPRESSION_INFO:
3185 case SMB_FILE_COMPRESSION_INFORMATION:
3186 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3187 SOFF_T(pdata,0,file_size);
3188 SIVAL(pdata,8,0); /* ??? */
3189 SIVAL(pdata,12,0); /* ??? */
3193 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3194 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3195 put_long_date(pdata,c_time);
3196 put_long_date(pdata+8,sbuf.st_atime);
3197 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3198 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3199 SIVAL(pdata,32,allocation_size);
3200 SOFF_T(pdata,40,file_size);
3201 SIVAL(pdata,48,mode);
3202 SIVAL(pdata,52,0); /* ??? */
3206 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3207 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3208 SIVAL(pdata,0,mode);
3214 * CIFS UNIX Extensions.
3217 case SMB_QUERY_FILE_UNIX_BASIC:
3219 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3220 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3222 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3225 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3228 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3229 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3230 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3233 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3237 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3241 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3244 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3248 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3252 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3255 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3259 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3262 data_size = PTR_DIFF(pdata,(*ppdata));
3266 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3268 for (i=0; i<100; i++)
3269 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3275 case SMB_QUERY_FILE_UNIX_LINK:
3279 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3281 if(!S_ISLNK(sbuf.st_mode))
3282 return(UNIXERROR(ERRSRV,ERRbadlink));
3284 return(UNIXERROR(ERRDOS,ERRbadlink));
3286 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3288 return(UNIXERROR(ERRDOS,ERRnoaccess));
3290 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3292 data_size = PTR_DIFF(pdata,(*ppdata));
3297 #if defined(HAVE_POSIX_ACLS)
3298 case SMB_QUERY_POSIX_ACL:
3300 SMB_ACL_T file_acl = NULL;
3301 SMB_ACL_T def_acl = NULL;
3302 uint16 num_file_acls = 0;
3303 uint16 num_def_acls = 0;
3305 if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
3306 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
3308 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3311 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3312 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3314 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3317 if (S_ISDIR(sbuf.st_mode)) {
3318 if (fsp && fsp->is_directory) {
3319 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3321 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3323 def_acl = free_empty_sys_acl(conn, def_acl);
3326 num_file_acls = count_acl_entries(conn, file_acl);
3327 num_def_acls = count_acl_entries(conn, def_acl);
3329 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3330 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3332 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3333 SMB_POSIX_ACL_HEADER_SIZE) ));
3335 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3338 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3340 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3343 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3344 SSVAL(pdata,2,num_file_acls);
3345 SSVAL(pdata,4,num_def_acls);
3346 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3348 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3351 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3353 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3355 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3357 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3360 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3362 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3366 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3369 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3371 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3377 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3380 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3385 /****************************************************************************
3386 Deal with the internal needs of setting the delete on close flag. Note that
3387 as the tdb locking is recursive, it is safe to call this from within
3388 open_file_shared. JRA.
3389 ****************************************************************************/
3391 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
3393 if (delete_on_close) {
3395 * Only allow delete on close for writable files.
3398 if (!lp_delete_readonly(SNUM(fsp->conn))) {
3399 if (dosmode & aRONLY) {
3400 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
3402 return NT_STATUS_CANNOT_DELETE;
3407 * Only allow delete on close for writable shares.
3410 if (!CAN_WRITE(fsp->conn)) {
3411 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
3413 return NT_STATUS_ACCESS_DENIED;
3417 * Only allow delete on close for files/directories opened with delete intent.
3420 if (!(fsp->desired_access & DELETE_ACCESS)) {
3421 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
3423 return NT_STATUS_ACCESS_DENIED;
3427 if(fsp->is_directory) {
3428 fsp->directory_delete_on_close = delete_on_close;
3429 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3430 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3432 fsp->delete_on_close = delete_on_close;
3433 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3434 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3437 return NT_STATUS_OK;
3440 /****************************************************************************
3441 Sets the delete on close flag over all share modes on this file.
3442 Modify the share mode entry for all files open
3443 on this device and inode to tell other smbds we have
3444 changed the delete on close flag. This will be noticed
3445 in the close code, the last closer will delete the file
3447 ****************************************************************************/
3449 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3451 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3452 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3454 if (fsp->is_directory || fsp->is_stat)
3455 return NT_STATUS_OK;
3457 if (lock_share_entry_fsp(fsp) == False)
3458 return NT_STATUS_ACCESS_DENIED;
3460 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3461 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3463 unlock_share_entry_fsp(fsp);
3464 return NT_STATUS_ACCESS_DENIED;
3467 unlock_share_entry_fsp(fsp);
3468 return NT_STATUS_OK;
3471 /****************************************************************************
3472 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3474 ****************************************************************************/
3476 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3478 BOOL bad_path_oldname = False;
3479 BOOL bad_path_newname = False;
3480 SMB_STRUCT_STAT sbuf1, sbuf2;
3481 pstring last_component_oldname;
3482 pstring last_component_newname;
3483 NTSTATUS status = NT_STATUS_OK;
3489 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3490 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3493 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3494 if (bad_path_oldname) {
3495 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3498 /* Quick check for "." and ".." */
3499 if (last_component_oldname[0] == '.') {
3500 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3501 return NT_STATUS_OBJECT_NAME_INVALID;
3505 /* source must already exist. */
3506 if (!VALID_STAT(sbuf1)) {
3507 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3510 if (!check_name(oldname,conn)) {
3511 return NT_STATUS_ACCESS_DENIED;
3514 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3515 if (bad_path_newname) {
3516 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3519 /* Quick check for "." and ".." */
3520 if (last_component_newname[0] == '.') {
3521 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3522 return NT_STATUS_OBJECT_NAME_INVALID;
3526 /* Disallow if newname already exists. */
3527 if (VALID_STAT(sbuf2)) {
3528 return NT_STATUS_OBJECT_NAME_COLLISION;
3531 if (!check_name(newname,conn)) {
3532 return NT_STATUS_ACCESS_DENIED;
3535 /* No links from a directory. */
3536 if (S_ISDIR(sbuf1.st_mode)) {
3537 return NT_STATUS_FILE_IS_A_DIRECTORY;
3540 /* Ensure this is within the share. */
3541 if (!reduce_name(conn, oldname) != 0)
3542 return NT_STATUS_ACCESS_DENIED;
3544 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3546 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3547 status = map_nt_error_from_unix(errno);
3548 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3549 nt_errstr(status), newname, oldname));
3555 /****************************************************************************
3556 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3557 ****************************************************************************/
3559 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3560 char **pparams, int total_params, char **ppdata, int total_data,
3561 unsigned int max_data_bytes)
3563 char *params = *pparams;
3564 char *pdata = *ppdata;
3565 uint16 tran_call = SVAL(inbuf, smb_setup0);
3570 SMB_STRUCT_STAT sbuf;
3573 BOOL bad_path = False;
3574 files_struct *fsp = NULL;
3575 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3576 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3577 mode_t unixmode = 0;
3578 NTSTATUS status = NT_STATUS_OK;
3581 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3585 if (tran_call == TRANSACT2_SETFILEINFO) {
3586 if (total_params < 4) {
3587 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3590 fsp = file_fsp(params,0);
3591 info_level = SVAL(params,2);
3593 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3595 * This is actually a SETFILEINFO on a directory
3596 * handle (returned from an NT SMB). NT5.0 seems
3597 * to do this call. JRA.
3599 pstrcpy(fname, fsp->fsp_name);
3600 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3601 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3602 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3604 } else if (fsp && fsp->print_file) {
3606 * Doing a DELETE_ON_CLOSE should cancel a print job.
3608 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3609 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3611 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3614 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3617 return (UNIXERROR(ERRDOS,ERRbadpath));
3620 * Original code - this is an open file.
3622 CHECK_FSP(fsp,conn);
3624 pstrcpy(fname, fsp->fsp_name);
3627 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3628 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3629 return(UNIXERROR(ERRDOS,ERRbadfid));
3634 if (total_params < 6) {
3635 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3638 info_level = SVAL(params,0);
3639 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3640 if (!NT_STATUS_IS_OK(status)) {
3641 return ERROR_NT(status);
3643 unix_convert(fname,conn,0,&bad_path,&sbuf);
3645 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3649 * For CIFS UNIX extensions the target name may not exist.
3652 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3653 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3654 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3657 if(!check_name(fname, conn)) {
3658 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3663 if (!CAN_WRITE(conn))
3664 return ERROR_DOS(ERRSRV,ERRaccess);
3666 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3667 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3669 if (VALID_STAT(sbuf))
3670 unixmode = sbuf.st_mode;
3672 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3673 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3675 /* Realloc the parameter size */
3676 params = SMB_REALLOC(*pparams,2);
3677 if(params == NULL) {
3678 return ERROR_NT(NT_STATUS_NO_MEMORY);
3684 if (fsp && fsp->pending_modtime) {
3685 /* the pending modtime overrides the current modtime */
3686 sbuf.st_mtime = fsp->pending_modtime;
3689 size = get_file_size(sbuf);
3690 tvs.modtime = sbuf.st_mtime;
3691 tvs.actime = sbuf.st_atime;
3692 dosmode = dos_mode(conn,fname,&sbuf);
3693 unixmode = sbuf.st_mode;
3695 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3696 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3698 switch (info_level) {
3699 case SMB_INFO_STANDARD:
3701 if (total_data < 12) {
3702 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3706 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3708 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3712 case SMB_INFO_SET_EA:
3714 struct ea_list *ea_list = NULL;
3715 TALLOC_CTX *ctx = NULL;
3717 if (total_data < 10) {
3718 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3721 if (IVAL(pdata,0) > total_data) {
3722 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3723 IVAL(pdata,0), (unsigned int)total_data));
3724 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3727 ctx = talloc_init("SMB_INFO_SET_EA");
3729 return ERROR_NT(NT_STATUS_NO_MEMORY);
3731 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3733 talloc_destroy(ctx);
3734 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3736 status = set_ea(conn, fsp, fname, ea_list);
3737 talloc_destroy(ctx);
3739 if (!NT_STATUS_IS_OK(status)) {
3740 return ERROR_NT(status);
3746 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3747 /* XXXX um, i don't think this is right.
3748 it's also not in the cifs6.txt spec.
3750 case SMB_INFO_QUERY_EAS_FROM_LIST:
3751 if (total_data < 28)
3752 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3754 tvs.actime = make_unix_date2(pdata+8);
3755 tvs.modtime = make_unix_date2(pdata+12);
3756 size = IVAL(pdata,16);
3757 dosmode = IVAL(pdata,24);
3760 /* XXXX nor this. not in cifs6.txt, either. */
3761 case SMB_INFO_QUERY_ALL_EAS:
3762 if (total_data < 28)
3763 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3765 tvs.actime = make_unix_date2(pdata+8);
3766 tvs.modtime = make_unix_date2(pdata+12);
3767 size = IVAL(pdata,16);
3768 dosmode = IVAL(pdata,24);
3772 case SMB_SET_FILE_BASIC_INFO:
3773 case SMB_FILE_BASIC_INFORMATION:
3775 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3777 time_t changed_time;
3779 if (total_data < 36) {
3780 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3783 /* Ignore create time at offset pdata. */
3786 tvs.actime = interpret_long_date(pdata+8);
3788 write_time = interpret_long_date(pdata+16);
3789 changed_time = interpret_long_date(pdata+24);
3791 tvs.modtime = MIN(write_time, changed_time);
3793 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3794 tvs.modtime = write_time;
3796 /* Prefer a defined time to an undefined one. */
3797 if (null_mtime(tvs.modtime)) {
3798 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3802 dosmode = IVAL(pdata,32);
3806 case SMB_FILE_ALLOCATION_INFORMATION:
3807 case SMB_SET_FILE_ALLOCATION_INFO:
3810 SMB_BIG_UINT allocation_size;
3812 if (total_data < 8) {
3813 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3816 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3817 #ifdef LARGE_SMB_OFF_T
3818 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3819 #else /* LARGE_SMB_OFF_T */
3820 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3821 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3822 #endif /* LARGE_SMB_OFF_T */
3823 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3824 fname, (double)allocation_size ));
3826 if (allocation_size) {
3827 allocation_size = smb_roundup(conn, allocation_size);
3830 if(allocation_size != get_file_size(sbuf)) {
3831 SMB_STRUCT_STAT new_sbuf;
3833 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3834 fname, (double)allocation_size ));
3837 files_struct *new_fsp = NULL;
3838 int access_mode = 0;
3841 if(global_oplock_break) {
3842 /* Queue this file modify as we are the process of an oplock break. */
3844 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3845 DEBUGADD(2,( "in oplock break state.\n"));
3847 push_oplock_pending_smb_message(inbuf, length);
3851 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3852 SET_OPEN_MODE(DOS_OPEN_RDWR),
3853 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3854 FILE_ATTRIBUTE_NORMAL,
3855 INTERNAL_OPEN_ONLY, &access_mode, &action);
3857 if (new_fsp == NULL)
3858 return(UNIXERROR(ERRDOS,ERRbadpath));
3859 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3860 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3861 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3862 new_fsp->fnum, strerror(errno)));
3865 close_file(new_fsp,True);
3867 ret = vfs_allocate_file_space(fsp, allocation_size);
3868 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3869 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3870 fsp->fnum, strerror(errno)));
3875 return ERROR_NT(NT_STATUS_DISK_FULL);
3877 /* Allocate can truncate size... */
3878 size = get_file_size(new_sbuf);
3884 case SMB_FILE_END_OF_FILE_INFORMATION:
3885 case SMB_SET_FILE_END_OF_FILE_INFO:
3887 if (total_data < 8) {
3888 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3891 size = IVAL(pdata,0);
3892 #ifdef LARGE_SMB_OFF_T
3893 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3894 #else /* LARGE_SMB_OFF_T */
3895 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3896 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3897 #endif /* LARGE_SMB_OFF_T */
3898 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3902 case SMB_FILE_DISPOSITION_INFORMATION:
3903 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3905 BOOL delete_on_close;
3907 if (total_data < 1) {
3908 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3911 delete_on_close = (CVAL(pdata,0) ? True : False);
3913 /* Just ignore this set on a path. */
3914 if (tran_call != TRANSACT2_SETFILEINFO)
3918 return(UNIXERROR(ERRDOS,ERRbadfid));
3920 status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3922 if (!NT_STATUS_IS_OK(status)) {
3923 return ERROR_NT(status);
3926 /* The set is across all open files on this dev/inode pair. */
3927 status =set_delete_on_close_over_all(fsp, delete_on_close);
3928 if (!NT_STATUS_IS_OK(status)) {
3929 return ERROR_NT(status);
3935 case SMB_FILE_POSITION_INFORMATION:
3937 SMB_BIG_UINT position_information;
3939 if (total_data < 8) {
3940 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3943 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3944 #ifdef LARGE_SMB_OFF_T
3945 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3946 #else /* LARGE_SMB_OFF_T */
3947 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3948 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3949 #endif /* LARGE_SMB_OFF_T */
3950 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3951 fname, (double)position_information ));
3953 fsp->position_information = position_information;
3957 /* From tridge Samba4 :
3958 * MODE_INFORMATION in setfileinfo (I have no
3959 * idea what "mode information" on a file is - it takes a value of 0,
3960 * 2, 4 or 6. What could it be?).
3963 case SMB_FILE_MODE_INFORMATION:
3967 if (total_data < 4) {
3968 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3970 mode = IVAL(pdata,0);
3971 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
3972 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3978 * CIFS UNIX extensions.
3981 case SMB_SET_FILE_UNIX_BASIC:
3983 uint32 raw_unixmode;
3985 if (total_data < 100) {
3986 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3989 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3990 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3991 size=IVAL(pdata,0); /* first 8 Bytes are size */
3992 #ifdef LARGE_SMB_OFF_T
3993 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3994 #else /* LARGE_SMB_OFF_T */
3995 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3996 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3997 #endif /* LARGE_SMB_OFF_T */
3999 pdata+=24; /* ctime & st_blocks are not changed */
4000 tvs.actime = interpret_long_date(pdata); /* access_time */
4001 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
4003 set_owner = (uid_t)IVAL(pdata,0);
4005 set_grp = (gid_t)IVAL(pdata,0);
4007 raw_unixmode = IVAL(pdata,28);
4008 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4009 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4011 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4012 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4013 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4015 if (!VALID_STAT(sbuf)) {
4018 * The only valid use of this is to create character and block
4019 * devices, and named pipes. This is deprecated (IMHO) and
4020 * a new info level should be used for mknod. JRA.
4023 uint32 file_type = IVAL(pdata,0);
4024 #if defined(HAVE_MAKEDEV)
4025 uint32 dev_major = IVAL(pdata,4);
4026 uint32 dev_minor = IVAL(pdata,12);
4029 uid_t myuid = geteuid();
4030 gid_t mygid = getegid();
4031 SMB_DEV_T dev = (SMB_DEV_T)0;
4033 if (tran_call == TRANSACT2_SETFILEINFO)
4034 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4036 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4037 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4040 #if defined(HAVE_MAKEDEV)
4041 dev = makedev(dev_major, dev_minor);
4044 /* We can only create as the owner/group we are. */
4046 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4047 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4048 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4049 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4051 switch (file_type) {
4052 #if defined(S_IFIFO)
4053 case UNIX_TYPE_FIFO:
4054 unixmode |= S_IFIFO;
4057 #if defined(S_IFSOCK)
4058 case UNIX_TYPE_SOCKET:
4059 unixmode |= S_IFSOCK;
4062 #if defined(S_IFCHR)
4063 case UNIX_TYPE_CHARDEV:
4064 unixmode |= S_IFCHR;
4067 #if defined(S_IFBLK)
4068 case UNIX_TYPE_BLKDEV:
4069 unixmode |= S_IFBLK;
4073 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4076 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4077 0%o for file %s\n", (double)dev, unixmode, fname ));
4079 /* Ok - do the mknod. */
4080 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4081 return(UNIXERROR(ERRDOS,ERRnoaccess));
4083 inherit_access_acl(conn, fname, unixmode);
4086 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4091 * Deal with the UNIX specific mode set.
4094 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4095 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4096 (unsigned int)unixmode, fname ));
4097 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4098 return(UNIXERROR(ERRDOS,ERRnoaccess));
4102 * Deal with the UNIX specific uid set.
4105 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4106 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4107 (unsigned int)set_owner, fname ));
4108 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4109 return(UNIXERROR(ERRDOS,ERRnoaccess));
4113 * Deal with the UNIX specific gid set.
4116 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4117 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4118 (unsigned int)set_owner, fname ));
4119 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4120 return(UNIXERROR(ERRDOS,ERRnoaccess));
4125 case SMB_SET_FILE_UNIX_LINK:
4127 pstring link_target;
4128 char *newname = fname;
4130 /* Set a symbolic link. */
4131 /* Don't allow this if follow links is false. */
4133 if (!lp_symlinks(SNUM(conn)))
4134 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4136 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4138 /* !widelinks forces the target path to be within the share. */
4139 /* This means we can interpret the target as a pathname. */
4140 if (!lp_widelinks(SNUM(conn))) {
4142 char *last_dirp = NULL;
4144 unix_format(link_target);
4145 if (*link_target == '/') {
4146 /* No absolute paths allowed. */
4147 return(UNIXERROR(ERRDOS,ERRnoaccess));
4149 pstrcpy(rel_name, newname);
4150 last_dirp = strrchr_m(rel_name, '/');
4152 last_dirp[1] = '\0';
4154 pstrcpy(rel_name, "./");
4156 pstrcat(rel_name, link_target);
4158 if (!check_name(rel_name, conn)) {
4159 return(UNIXERROR(ERRDOS,ERRnoaccess));
4163 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4164 fname, link_target ));
4166 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4167 return(UNIXERROR(ERRDOS,ERRnoaccess));
4169 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4173 case SMB_SET_FILE_UNIX_HLINK:
4176 char *newname = fname;
4178 /* Set a hard link. */
4179 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
4180 if (!NT_STATUS_IS_OK(status)) {
4181 return ERROR_NT(status);
4184 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4187 status = hardlink_internals(conn, oldname, newname);
4188 if (!NT_STATUS_IS_OK(status)) {
4189 return ERROR_NT(status);
4193 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4197 case SMB_FILE_RENAME_INFORMATION:
4206 if (total_data < 12) {
4207 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4210 overwrite = (CVAL(pdata,0) ? True : False);
4211 root_fid = IVAL(pdata,4);
4212 len = IVAL(pdata,8);
4213 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
4214 if (!NT_STATUS_IS_OK(status)) {
4215 return ERROR_NT(status);
4218 /* Check the new name has no '/' characters. */
4219 if (strchr_m(newname, '/'))
4220 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4222 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4224 /* Create the base directory. */
4225 pstrcpy(base_name, fname);
4226 p = strrchr_m(base_name, '/');
4229 /* Append the new name. */
4230 pstrcat(base_name, "/");
4231 pstrcat(base_name, newname);
4234 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4235 fsp->fnum, fsp->fsp_name, base_name ));
4236 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4238 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4240 status = rename_internals(conn, fname, base_name, 0, overwrite);
4242 if (!NT_STATUS_IS_OK(status)) {
4243 return ERROR_NT(status);
4245 process_pending_change_notify_queue((time_t)0);
4247 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4251 #if defined(HAVE_POSIX_ACLS)
4252 case SMB_SET_POSIX_ACL:
4254 uint16 posix_acl_version;
4255 uint16 num_file_acls;
4256 uint16 num_def_acls;
4257 BOOL valid_file_acls = True;
4258 BOOL valid_def_acls = True;
4260 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4261 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4263 posix_acl_version = SVAL(pdata,0);
4264 num_file_acls = SVAL(pdata,2);
4265 num_def_acls = SVAL(pdata,4);
4267 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4268 valid_file_acls = False;
4272 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4273 valid_def_acls = False;
4277 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4278 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4281 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4282 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4283 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4286 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4287 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4288 return(UNIXERROR(ERRDOS,ERRnoaccess));
4291 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4292 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4293 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4294 return(UNIXERROR(ERRDOS,ERRnoaccess));
4298 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4304 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4307 /* get some defaults (no modifications) if any info is zero or -1. */
4308 if (null_mtime(tvs.actime)) {
4309 tvs.actime = sbuf.st_atime;
4312 if (null_mtime(tvs.modtime)) {
4313 tvs.modtime = sbuf.st_mtime;
4316 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4317 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4318 DEBUG(6,("size: %.0f ", (double)size));
4321 if (S_ISDIR(sbuf.st_mode))
4327 DEBUG(6,("dosmode: %x\n" , dosmode));
4329 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4330 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4331 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4332 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4335 * Only do this test if we are not explicitly
4336 * changing the size of a file.
4339 size = get_file_size(sbuf);
4343 * Try and set the times, size and mode of this file -
4344 * if they are different from the current values
4347 /* check the mode isn't different, before changing it */
4348 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4350 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4352 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4353 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4354 return(UNIXERROR(ERRDOS,ERRnoaccess));
4359 if (size != get_file_size(sbuf)) {
4363 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4364 fname, (double)size ));
4367 files_struct *new_fsp = NULL;
4368 int access_mode = 0;
4371 if(global_oplock_break) {
4372 /* Queue this file modify as we are the process of an oplock break. */
4374 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
4375 DEBUGADD(2,( "in oplock break state.\n"));
4377 push_oplock_pending_smb_message(inbuf, length);
4381 new_fsp = open_file_shared(conn, fname, &sbuf,
4382 SET_OPEN_MODE(DOS_OPEN_RDWR),
4383 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
4384 FILE_ATTRIBUTE_NORMAL,
4385 INTERNAL_OPEN_ONLY, &access_mode, &action);
4387 if (new_fsp == NULL)
4388 return(UNIXERROR(ERRDOS,ERRbadpath));
4389 ret = vfs_set_filelen(new_fsp, size);
4390 close_file(new_fsp,True);
4392 ret = vfs_set_filelen(fsp, size);
4396 return (UNIXERROR(ERRHRD,ERRdiskfull));
4400 * Finally the times.
4402 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4405 * This was a setfileinfo on an open file.
4406 * NT does this a lot. We also need to
4407 * set the time here, as it can be read by
4408 * FindFirst/FindNext and with the patch for bug #2045
4409 * in smbd/fileio.c it ensures that this timestamp is
4410 * kept sticky even after a write. We save the request
4411 * away and will set it on file close and after a write. JRA.
4414 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4415 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4416 fsp_set_pending_modtime(fsp, tvs.modtime);
4420 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4422 if(file_utime(conn, fname, &tvs)!=0) {
4423 return(UNIXERROR(ERRDOS,ERRnoaccess));
4428 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4433 /****************************************************************************
4434 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4435 ****************************************************************************/
4437 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4438 char **pparams, int total_params, char **ppdata, int total_data,
4439 unsigned int max_data_bytes)
4441 char *params = *pparams;
4442 char *pdata = *ppdata;
4445 SMB_STRUCT_STAT sbuf;
4446 BOOL bad_path = False;
4447 NTSTATUS status = NT_STATUS_OK;
4448 TALLOC_CTX *ctx = NULL;
4449 struct ea_list *ea_list = NULL;
4451 if (!CAN_WRITE(conn))
4452 return ERROR_DOS(ERRSRV,ERRaccess);
4454 if (total_params < 4) {
4455 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4458 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4459 if (!NT_STATUS_IS_OK(status)) {
4460 return ERROR_NT(status);
4463 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4465 unix_convert(directory,conn,0,&bad_path,&sbuf);
4467 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4470 /* Any data in this call is an EA list. */
4471 if (total_data && !lp_ea_support(SNUM(conn))) {
4472 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4476 if (total_data < 10) {
4477 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4480 if (IVAL(pdata,0) > total_data) {
4481 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4482 IVAL(pdata,0), (unsigned int)total_data));
4483 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4486 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4488 return ERROR_NT(NT_STATUS_NO_MEMORY);
4490 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4492 talloc_destroy(ctx);
4493 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4497 if (check_name(directory,conn)) {
4498 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4502 talloc_destroy(ctx);
4503 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4504 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4507 /* Try and set any given EA. */
4509 status = set_ea(conn, NULL, directory, ea_list);
4510 talloc_destroy(ctx);
4511 if (!NT_STATUS_IS_OK(status)) {
4512 return ERROR_NT(status);
4516 /* Realloc the parameter and data sizes */
4517 params = SMB_REALLOC(*pparams,2);
4518 if(params == NULL) {
4519 return ERROR_NT(NT_STATUS_NO_MEMORY);
4525 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4530 /****************************************************************************
4531 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4532 We don't actually do this - we just send a null response.
4533 ****************************************************************************/
4535 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4536 char **pparams, int total_params, char **ppdata, int total_data,
4537 unsigned int max_data_bytes)
4539 static uint16 fnf_handle = 257;
4540 char *params = *pparams;
4543 if (total_params < 6) {
4544 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4547 info_level = SVAL(params,4);
4548 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4550 switch (info_level) {
4555 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4558 /* Realloc the parameter and data sizes */
4559 params = SMB_REALLOC(*pparams,6);
4560 if(params == NULL) {
4561 return ERROR_NT(NT_STATUS_NO_MEMORY);
4565 SSVAL(params,0,fnf_handle);
4566 SSVAL(params,2,0); /* No changes */
4567 SSVAL(params,4,0); /* No EA errors */
4574 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4579 /****************************************************************************
4580 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4581 changes). Currently this does nothing.
4582 ****************************************************************************/
4584 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4585 char **pparams, int total_params, char **ppdata, int total_data,
4586 unsigned int max_data_bytes)
4588 char *params = *pparams;
4590 DEBUG(3,("call_trans2findnotifynext\n"));
4592 /* Realloc the parameter and data sizes */
4593 params = SMB_REALLOC(*pparams,4);
4594 if(params == NULL) {
4595 return ERROR_NT(NT_STATUS_NO_MEMORY);
4599 SSVAL(params,0,0); /* No changes */
4600 SSVAL(params,2,0); /* No EA errors */
4602 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4607 /****************************************************************************
4608 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4609 ****************************************************************************/
4611 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4612 char **pparams, int total_params, char **ppdata, int total_data,
4613 unsigned int max_data_bytes)
4615 char *params = *pparams;
4618 int max_referral_level;
4620 DEBUG(10,("call_trans2getdfsreferral\n"));
4622 if (total_params < 2) {
4623 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4626 max_referral_level = SVAL(params,0);
4628 if(!lp_host_msdfs())
4629 return ERROR_DOS(ERRDOS,ERRbadfunc);
4631 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4632 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4633 return UNIXERROR(ERRDOS,ERRbadfile);
4635 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4636 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4641 #define LMCAT_SPL 0x53
4642 #define LMFUNC_GETJOBID 0x60
4644 /****************************************************************************
4645 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4646 ****************************************************************************/
4648 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4649 char **pparams, int total_params, char **ppdata, int total_data,
4650 unsigned int max_data_bytes)
4652 char *pdata = *ppdata;
4653 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4655 /* check for an invalid fid before proceeding */
4658 return(ERROR_DOS(ERRDOS,ERRbadfid));
4660 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4661 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4662 pdata = SMB_REALLOC(*ppdata, 32);
4664 return ERROR_NT(NT_STATUS_NO_MEMORY);
4668 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4669 CAN ACCEPT THIS IN UNICODE. JRA. */
4671 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4672 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4673 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4674 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4677 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4678 return ERROR_DOS(ERRSRV,ERRerror);
4682 /****************************************************************************
4683 Reply to a SMBfindclose (stop trans2 directory search).
4684 ****************************************************************************/
4686 int reply_findclose(connection_struct *conn,
4687 char *inbuf,char *outbuf,int length,int bufsize)
4690 int dptr_num=SVALS(inbuf,smb_vwv0);
4691 START_PROFILE(SMBfindclose);
4693 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4695 dptr_close(&dptr_num);
4697 outsize = set_message(outbuf,0,0,True);
4699 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4701 END_PROFILE(SMBfindclose);
4705 /****************************************************************************
4706 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4707 ****************************************************************************/
4709 int reply_findnclose(connection_struct *conn,
4710 char *inbuf,char *outbuf,int length,int bufsize)
4714 START_PROFILE(SMBfindnclose);
4716 dptr_num = SVAL(inbuf,smb_vwv0);
4718 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4720 /* We never give out valid handles for a
4721 findnotifyfirst - so any dptr_num is ok here.
4724 outsize = set_message(outbuf,0,0,True);
4726 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4728 END_PROFILE(SMBfindnclose);
4732 /****************************************************************************
4733 Reply to a SMBtranss2 - just ignore it!
4734 ****************************************************************************/
4736 int reply_transs2(connection_struct *conn,
4737 char *inbuf,char *outbuf,int length,int bufsize)
4739 START_PROFILE(SMBtranss2);
4740 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4741 END_PROFILE(SMBtranss2);
4745 /****************************************************************************
4746 Reply to a SMBtrans2.
4747 ****************************************************************************/
4749 int reply_trans2(connection_struct *conn,
4750 char *inbuf,char *outbuf,int length,int bufsize)
4753 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4754 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4755 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4757 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4758 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4759 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4760 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4761 int32 timeout = IVALS(inbuf,smb_timeout);
4763 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4764 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4765 char *params = NULL, *data = NULL;
4766 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4767 START_PROFILE(SMBtrans2);
4769 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4770 /* Queue this open message as we are the process of an
4773 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4774 DEBUGADD(2,( "in oplock break state.\n"));
4776 push_oplock_pending_smb_message(inbuf, length);
4777 END_PROFILE(SMBtrans2);
4781 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4782 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4783 END_PROFILE(SMBtrans2);
4784 return ERROR_DOS(ERRSRV,ERRaccess);
4787 outsize = set_message(outbuf,0,0,True);
4789 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4790 is so as a sanity check */
4793 * Need to have rc=0 for ioctl to get job id for OS/2.
4794 * Network printing will fail if function is not successful.
4795 * Similar function in reply.c will be used if protocol
4796 * is LANMAN1.0 instead of LM1.2X002.
4797 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4798 * outbuf doesn't have to be set(only job id is used).
4800 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4801 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4802 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4803 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4805 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4806 DEBUG(2,("Transaction is %d\n",tran_call));
4807 END_PROFILE(SMBtrans2);
4808 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4812 /* Allocate the space for the maximum needed parameters and data */
4813 if (total_params > 0)
4814 params = (char *)SMB_MALLOC(total_params);
4816 data = (char *)SMB_MALLOC(total_data);
4818 if ((total_params && !params) || (total_data && !data)) {
4819 DEBUG(2,("Out of memory in reply_trans2\n"));
4822 END_PROFILE(SMBtrans2);
4823 return ERROR_NT(NT_STATUS_NO_MEMORY);
4826 /* Copy the param and data bytes sent with this request into
4827 the params buffer */
4828 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4829 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4831 if (num_params > total_params || num_data > total_data)
4832 exit_server("invalid params in reply_trans2");
4835 unsigned int psoff = SVAL(inbuf, smb_psoff);
4836 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4838 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4839 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4841 memcpy( params, smb_base(inbuf) + psoff, num_params);
4844 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4845 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4847 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4848 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4850 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4853 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4855 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4856 /* We need to send an interim response then receive the rest
4857 of the parameter/data bytes */
4858 outsize = set_message(outbuf,0,0,True);
4859 srv_signing_trans_stop();
4860 if (!send_smb(smbd_server_fd(),outbuf))
4861 exit_server("reply_trans2: send_smb failed.");
4863 while (num_data_sofar < total_data ||
4864 num_params_sofar < total_params) {
4866 unsigned int param_disp;
4867 unsigned int param_off;
4868 unsigned int data_disp;
4869 unsigned int data_off;
4871 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4874 * The sequence number for the trans reply is always
4875 * based on the last secondary received.
4878 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4881 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4882 outsize = set_message(outbuf,0,0,True);
4884 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4886 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4887 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4891 /* Revise total_params and total_data in case
4892 they have changed downwards */
4893 if (SVAL(inbuf, smb_tpscnt) < total_params)
4894 total_params = SVAL(inbuf, smb_tpscnt);
4895 if (SVAL(inbuf, smb_tdscnt) < total_data)
4896 total_data = SVAL(inbuf, smb_tdscnt);
4898 num_params = SVAL(inbuf,smb_spscnt);
4899 param_off = SVAL(inbuf, smb_spsoff);
4900 param_disp = SVAL(inbuf, smb_spsdisp);
4901 num_params_sofar += num_params;
4903 num_data = SVAL(inbuf, smb_sdscnt);
4904 data_off = SVAL(inbuf, smb_sdsoff);
4905 data_disp = SVAL(inbuf, smb_sdsdisp);
4906 num_data_sofar += num_data;
4908 if (num_params_sofar > total_params || num_data_sofar > total_data)
4912 if (param_disp + num_params > total_params)
4914 if ((param_disp + num_params < param_disp) ||
4915 (param_disp + num_params < num_params))
4917 if (param_disp > total_params)
4919 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4920 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4922 if (params + param_disp < params)
4925 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
4928 if (data_disp + num_data > total_data)
4930 if ((data_disp + num_data < data_disp) ||
4931 (data_disp + num_data < num_data))
4933 if (data_disp > total_data)
4935 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4936 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4938 if (data + data_disp < data)
4941 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4946 if (Protocol >= PROTOCOL_NT1) {
4947 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4950 /* Now we must call the relevant TRANS2 function */
4952 case TRANSACT2_OPEN:
4953 START_PROFILE_NESTED(Trans2_open);
4954 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4955 ¶ms, total_params, &data, total_data, max_data_bytes);
4956 END_PROFILE_NESTED(Trans2_open);
4959 case TRANSACT2_FINDFIRST:
4960 START_PROFILE_NESTED(Trans2_findfirst);
4961 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4962 ¶ms, total_params, &data, total_data, max_data_bytes);
4963 END_PROFILE_NESTED(Trans2_findfirst);
4966 case TRANSACT2_FINDNEXT:
4967 START_PROFILE_NESTED(Trans2_findnext);
4968 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4969 ¶ms, total_params, &data, total_data, max_data_bytes);
4970 END_PROFILE_NESTED(Trans2_findnext);
4973 case TRANSACT2_QFSINFO:
4974 START_PROFILE_NESTED(Trans2_qfsinfo);
4975 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4976 ¶ms, total_params, &data, total_data, max_data_bytes);
4977 END_PROFILE_NESTED(Trans2_qfsinfo);
4980 #ifdef HAVE_SYS_QUOTAS
4981 case TRANSACT2_SETFSINFO:
4982 START_PROFILE_NESTED(Trans2_setfsinfo);
4983 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4984 ¶ms, total_params, &data, total_data, max_data_bytes);
4985 END_PROFILE_NESTED(Trans2_setfsinfo);
4988 case TRANSACT2_QPATHINFO:
4989 case TRANSACT2_QFILEINFO:
4990 START_PROFILE_NESTED(Trans2_qpathinfo);
4991 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4992 ¶ms, total_params, &data, total_data, max_data_bytes);
4993 END_PROFILE_NESTED(Trans2_qpathinfo);
4995 case TRANSACT2_SETPATHINFO:
4996 case TRANSACT2_SETFILEINFO:
4997 START_PROFILE_NESTED(Trans2_setpathinfo);
4998 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4999 ¶ms, total_params, &data, total_data, max_data_bytes);
5000 END_PROFILE_NESTED(Trans2_setpathinfo);
5003 case TRANSACT2_FINDNOTIFYFIRST:
5004 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5005 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
5006 ¶ms, total_params, &data, total_data, max_data_bytes);
5007 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5010 case TRANSACT2_FINDNOTIFYNEXT:
5011 START_PROFILE_NESTED(Trans2_findnotifynext);
5012 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
5013 ¶ms, total_params, &data, total_data, max_data_bytes);
5014 END_PROFILE_NESTED(Trans2_findnotifynext);
5016 case TRANSACT2_MKDIR:
5017 START_PROFILE_NESTED(Trans2_mkdir);
5018 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
5019 ¶ms, total_params, &data, total_data, max_data_bytes);
5020 END_PROFILE_NESTED(Trans2_mkdir);
5023 case TRANSACT2_GET_DFS_REFERRAL:
5024 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5025 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
5026 ¶ms, total_params, &data, total_data, max_data_bytes);
5027 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5029 case TRANSACT2_IOCTL:
5030 START_PROFILE_NESTED(Trans2_ioctl);
5031 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
5032 ¶ms, total_params, &data, total_data, max_data_bytes);
5033 END_PROFILE_NESTED(Trans2_ioctl);
5036 /* Error in request */
5037 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
5040 END_PROFILE(SMBtrans2);
5041 srv_signing_trans_stop();
5042 return ERROR_DOS(ERRSRV,ERRerror);
5045 /* As we do not know how many data packets will need to be
5046 returned here the various call_trans2xxxx calls
5047 must send their own. Thus a call_trans2xxx routine only
5048 returns a value other than -1 when it wants to send
5052 srv_signing_trans_stop();
5056 END_PROFILE(SMBtrans2);
5057 return outsize; /* If a correct response was needed the
5058 call_trans2xxx calls have already sent
5059 it. If outsize != -1 then it is returning */
5063 srv_signing_trans_stop();
5066 END_PROFILE(SMBtrans2);
5067 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);