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] != '/');
1022 BOOL check_mangled_names = lp_manglednames(SNUM(conn));
1025 *out_of_space = False;
1026 *got_exact_match = False;
1031 p = strrchr_m(path_mask,'/');
1034 pstrcpy(mask,"*.*");
1038 pstrcpy(mask, path_mask);
1043 /* Needed if we run out of space */
1044 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1045 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1048 * Due to bugs in NT client redirectors we are not using
1049 * resume keys any more - set them to zero.
1050 * Check out the related comments in findfirst/findnext.
1056 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1057 (long)conn->dirptr,curr_dirpos));
1062 pstrcpy(fname,dname);
1064 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
1065 got_match = mask_match(fname, mask, conn->case_sensitive);
1067 if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False, SNUM(conn))) {
1070 * It turns out that NT matches wildcards against
1071 * both long *and* short names. This may explain some
1072 * of the wildcard wierdness from old DOS clients
1073 * that some people have been seeing.... JRA.
1077 pstrcpy( newname, fname);
1078 mangle_map( newname, True, False, SNUM(conn));
1079 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
1080 got_match = mask_match(newname, mask, conn->case_sensitive);
1084 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1085 if (dont_descend && !isdots)
1088 pstrcpy(pathreal,conn->dirpath);
1090 pstrcat(pathreal,"/");
1091 pstrcat(pathreal,dname);
1093 if (INFO_LEVEL_IS_UNIX(info_level)) {
1094 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1095 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1096 pathreal,strerror(errno)));
1099 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1101 /* Needed to show the msdfs symlinks as
1104 if(lp_host_msdfs() &&
1105 lp_msdfs_root(SNUM(conn)) &&
1106 is_msdfs_link(conn, pathreal, NULL, NULL,
1109 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1110 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1114 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1115 pathreal,strerror(errno)));
1120 mode = dos_mode(conn,pathreal,&sbuf);
1122 if (!dir_check_ftype(conn,mode,dirtype)) {
1123 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1127 file_size = get_file_size(sbuf);
1128 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1129 mdate = sbuf.st_mtime;
1130 adate = sbuf.st_atime;
1131 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1133 if (lp_dos_filetime_resolution(SNUM(conn))) {
1140 /* This is necessary, as otherwise the
1141 * desktop.ini file in this folder is
1143 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
1147 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1153 mangle_map(fname,False,True,SNUM(conn));
1158 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1160 switch (info_level) {
1161 case SMB_FIND_INFO_STANDARD:
1162 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1163 if(requires_resume_key) {
1167 put_dos_date2(p,l1_fdateCreation,cdate);
1168 put_dos_date2(p,l1_fdateLastAccess,adate);
1169 put_dos_date2(p,l1_fdateLastWrite,mdate);
1170 SIVAL(p,l1_cbFile,(uint32)file_size);
1171 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
1172 SSVAL(p,l1_attrFile,mode);
1175 p += align_string(outbuf, p, 0);
1176 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1177 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1179 SCVAL(nameptr, -1, len - 2);
1181 SCVAL(nameptr, -1, 0);
1185 SCVAL(nameptr, -1, len - 1);
1187 SCVAL(nameptr, -1, 0);
1193 case SMB_FIND_EA_SIZE:
1194 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1195 if(requires_resume_key) {
1199 put_dos_date2(p,l2_fdateCreation,cdate);
1200 put_dos_date2(p,l2_fdateLastAccess,adate);
1201 put_dos_date2(p,l2_fdateLastWrite,mdate);
1202 SIVAL(p,l2_cbFile,(uint32)file_size);
1203 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1204 SSVAL(p,l2_attrFile,mode);
1206 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1207 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1211 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1212 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1225 SCVAL(nameptr,0,len);
1227 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1230 case SMB_FIND_EA_LIST:
1232 struct ea_list *file_list = NULL;
1235 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1239 if(requires_resume_key) {
1243 put_dos_date2(p,l2_fdateCreation,cdate);
1244 put_dos_date2(p,l2_fdateLastAccess,adate);
1245 put_dos_date2(p,l2_fdateLastWrite,mdate);
1246 SIVAL(p,l2_cbFile,(uint32)file_size);
1247 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1248 SSVAL(p,l2_attrFile,mode);
1249 p += l2_cbList; /* p now points to the EA area. */
1251 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1252 name_list = ea_list_union(name_list, file_list, &ea_len);
1254 /* We need to determine if this entry will fit in the space available. */
1255 /* Max string size is 255 bytes. */
1256 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1257 /* Move the dirptr back to prev_dirpos */
1258 dptr_SeekDir(conn->dirptr, prev_dirpos);
1259 *out_of_space = True;
1260 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1261 return False; /* Not finished - just out of space */
1264 /* Push the ea_data followed by the name. */
1265 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1267 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1268 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1281 SCVAL(nameptr,0,len);
1283 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1287 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1288 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1289 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1291 SIVAL(p,0,reskey); p += 4;
1292 put_long_date(p,cdate); p += 8;
1293 put_long_date(p,adate); p += 8;
1294 put_long_date(p,mdate); p += 8;
1295 put_long_date(p,mdate); p += 8;
1296 SOFF_T(p,0,file_size); p += 8;
1297 SOFF_T(p,0,allocation_size); p += 8;
1298 SIVAL(p,0,nt_extmode); p += 4;
1299 q = p; p += 4; /* q is placeholder for name length. */
1301 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1302 SIVAL(p,0,ea_size); /* Extended attributes */
1305 /* Clear the short name buffer. This is
1306 * IMPORTANT as not doing so will trigger
1307 * a Win2k client bug. JRA.
1310 if (!was_8_3 && check_mangled_names) {
1311 pstring mangled_name;
1312 pstrcpy(mangled_name, fname);
1313 mangle_map(mangled_name,True,True,SNUM(conn));
1314 mangled_name[12] = 0;
1315 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1319 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1322 len = PTR_DIFF(p, pdata);
1323 len = (len + 3) & ~3;
1328 case SMB_FIND_FILE_DIRECTORY_INFO:
1329 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1331 SIVAL(p,0,reskey); p += 4;
1332 put_long_date(p,cdate); p += 8;
1333 put_long_date(p,adate); p += 8;
1334 put_long_date(p,mdate); p += 8;
1335 put_long_date(p,mdate); p += 8;
1336 SOFF_T(p,0,file_size); p += 8;
1337 SOFF_T(p,0,allocation_size); p += 8;
1338 SIVAL(p,0,nt_extmode); p += 4;
1339 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1342 len = PTR_DIFF(p, pdata);
1343 len = (len + 3) & ~3;
1348 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1349 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1351 SIVAL(p,0,reskey); p += 4;
1352 put_long_date(p,cdate); p += 8;
1353 put_long_date(p,adate); p += 8;
1354 put_long_date(p,mdate); p += 8;
1355 put_long_date(p,mdate); p += 8;
1356 SOFF_T(p,0,file_size); p += 8;
1357 SOFF_T(p,0,allocation_size); p += 8;
1358 SIVAL(p,0,nt_extmode); p += 4;
1359 q = p; p += 4; /* q is placeholder for name length. */
1361 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1362 SIVAL(p,0,ea_size); /* Extended attributes */
1365 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1369 len = PTR_DIFF(p, pdata);
1370 len = (len + 3) & ~3;
1375 case SMB_FIND_FILE_NAMES_INFO:
1376 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1378 SIVAL(p,0,reskey); p += 4;
1380 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1381 acl on a dir (tridge) */
1382 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1385 len = PTR_DIFF(p, pdata);
1386 len = (len + 3) & ~3;
1391 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1392 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1394 SIVAL(p,0,reskey); p += 4;
1395 put_long_date(p,cdate); p += 8;
1396 put_long_date(p,adate); p += 8;
1397 put_long_date(p,mdate); p += 8;
1398 put_long_date(p,mdate); p += 8;
1399 SOFF_T(p,0,file_size); p += 8;
1400 SOFF_T(p,0,allocation_size); p += 8;
1401 SIVAL(p,0,nt_extmode); p += 4;
1402 q = p; p += 4; /* q is placeholder for name length. */
1404 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1405 SIVAL(p,0,ea_size); /* Extended attributes */
1408 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1409 SIVAL(p,0,sbuf.st_dev); p += 4;
1410 SIVAL(p,0,sbuf.st_ino); p += 4;
1411 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1414 len = PTR_DIFF(p, pdata);
1415 len = (len + 3) & ~3;
1420 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1421 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1422 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1424 SIVAL(p,0,reskey); p += 4;
1425 put_long_date(p,cdate); p += 8;
1426 put_long_date(p,adate); p += 8;
1427 put_long_date(p,mdate); p += 8;
1428 put_long_date(p,mdate); p += 8;
1429 SOFF_T(p,0,file_size); p += 8;
1430 SOFF_T(p,0,allocation_size); p += 8;
1431 SIVAL(p,0,nt_extmode); p += 4;
1432 q = p; p += 4; /* q is placeholder for name length */
1434 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1435 SIVAL(p,0,ea_size); /* Extended attributes */
1438 /* Clear the short name buffer. This is
1439 * IMPORTANT as not doing so will trigger
1440 * a Win2k client bug. JRA.
1443 if (!was_8_3 && check_mangled_names) {
1444 pstring mangled_name;
1445 pstrcpy(mangled_name, fname);
1446 mangle_map(mangled_name,True,True,SNUM(conn));
1447 mangled_name[12] = 0;
1448 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1452 SSVAL(p,0,0); p += 2; /* Reserved ? */
1453 SIVAL(p,0,sbuf.st_dev); p += 4;
1454 SIVAL(p,0,sbuf.st_ino); p += 4;
1455 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1458 len = PTR_DIFF(p, pdata);
1459 len = (len + 3) & ~3;
1464 /* CIFS UNIX Extension. */
1466 case SMB_FIND_FILE_UNIX:
1467 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1469 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1471 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1472 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1475 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1478 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1479 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1480 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1483 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1487 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1491 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1494 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1498 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1502 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1505 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1509 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1513 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1516 len = PTR_DIFF(p, pdata);
1517 len = (len + 3) & ~3;
1518 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1520 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1529 if (PTR_DIFF(p,pdata) > space_remaining) {
1530 /* Move the dirptr back to prev_dirpos */
1531 dptr_SeekDir(conn->dirptr, prev_dirpos);
1532 *out_of_space = True;
1533 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1534 return False; /* Not finished - just out of space */
1537 /* Setup the last entry pointer, as an offset from base_data */
1538 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1539 /* Advance the data pointer to the next slot */
1545 /****************************************************************************
1546 Reply to a TRANS2_FINDFIRST.
1547 ****************************************************************************/
1549 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1550 char **pparams, int total_params, char **ppdata, int total_data,
1551 unsigned int max_data_bytes)
1553 /* We must be careful here that we don't return more than the
1554 allowed number of data bytes. If this means returning fewer than
1555 maxentries then so be it. We assume that the redirector has
1556 enough room for the fixed number of parameter bytes it has
1558 char *params = *pparams;
1559 char *pdata = *ppdata;
1560 int dirtype = SVAL(params,0);
1561 int maxentries = SVAL(params,2);
1562 uint16 findfirst_flags = SVAL(params,4);
1563 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1564 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1565 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1566 int info_level = SVAL(params,6);
1570 int last_entry_off=0;
1574 BOOL finished = False;
1575 BOOL dont_descend = False;
1576 BOOL out_of_space = False;
1577 int space_remaining;
1578 BOOL bad_path = False;
1579 SMB_STRUCT_STAT sbuf;
1580 TALLOC_CTX *ea_ctx = NULL;
1581 struct ea_list *ea_list = NULL;
1582 NTSTATUS ntstatus = NT_STATUS_OK;
1584 if (total_params < 12) {
1585 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1588 *directory = *mask = 0;
1590 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1591 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1592 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1593 info_level, max_data_bytes));
1596 /* W2K3 seems to treat zero as 1. */
1600 switch (info_level) {
1601 case SMB_FIND_INFO_STANDARD:
1602 case SMB_FIND_EA_SIZE:
1603 case SMB_FIND_EA_LIST:
1604 case SMB_FIND_FILE_DIRECTORY_INFO:
1605 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1606 case SMB_FIND_FILE_NAMES_INFO:
1607 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1608 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1609 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1611 case SMB_FIND_FILE_UNIX:
1612 if (!lp_unix_extensions())
1613 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1616 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1619 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1620 if (!NT_STATUS_IS_OK(ntstatus)) {
1621 return ERROR_NT(ntstatus);
1624 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1626 unix_convert(directory,conn,0,&bad_path,&sbuf);
1628 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1630 if(!check_name(directory,conn)) {
1631 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1634 p = strrchr_m(directory,'/');
1636 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1637 if((directory[0] == '.') && (directory[1] == '\0'))
1640 pstrcpy(mask,directory);
1641 pstrcpy(directory,"./");
1647 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1649 if (info_level == SMB_FIND_EA_LIST) {
1652 if (total_data < 4) {
1653 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1656 ea_size = IVAL(pdata,0);
1657 if (ea_size != total_data) {
1658 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1659 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1660 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1663 if (!lp_ea_support(SNUM(conn))) {
1664 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1667 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1668 return ERROR_NT(NT_STATUS_NO_MEMORY);
1671 /* Pull out the list of names. */
1672 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1674 talloc_destroy(ea_ctx);
1675 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1679 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1680 if( pdata == NULL ) {
1681 talloc_destroy(ea_ctx);
1682 return ERROR_NT(NT_STATUS_NO_MEMORY);
1686 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1688 /* Realloc the params space */
1689 params = SMB_REALLOC(*pparams, 10);
1690 if (params == NULL) {
1691 talloc_destroy(ea_ctx);
1692 return ERROR_NT(NT_STATUS_NO_MEMORY);
1696 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1698 talloc_destroy(ea_ctx);
1699 return(UNIXERROR(ERRDOS,ERRbadfile));
1702 /* Save the wildcard match and attribs we are using on this directory -
1703 needed as lanman2 assumes these are being saved between calls */
1705 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1706 dptr_close(&dptr_num);
1707 talloc_destroy(ea_ctx);
1708 return ERROR_NT(NT_STATUS_NO_MEMORY);
1711 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1713 /* We don't need to check for VOL here as this is returned by
1714 a different TRANS2 call. */
1716 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1717 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1718 dont_descend = True;
1721 space_remaining = max_data_bytes;
1722 out_of_space = False;
1724 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1725 BOOL got_exact_match = False;
1727 /* this is a heuristic to avoid seeking the dirptr except when
1728 absolutely necessary. It allows for a filename of about 40 chars */
1729 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1730 out_of_space = True;
1733 finished = !get_lanman2_dir_entry(conn,
1735 mask,dirtype,info_level,
1736 requires_resume_key,dont_descend,
1737 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1738 &last_entry_off, ea_list, ea_ctx);
1741 if (finished && out_of_space)
1744 if (!finished && !out_of_space)
1748 * As an optimisation if we know we aren't looking
1749 * for a wildcard name (ie. the name matches the wildcard exactly)
1750 * then we can finish on any (first) match.
1751 * This speeds up large directory searches. JRA.
1757 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1760 talloc_destroy(ea_ctx);
1762 /* Check if we can close the dirptr */
1763 if(close_after_first || (finished && close_if_end)) {
1764 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1765 dptr_close(&dptr_num);
1769 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1770 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1771 * the protocol level is less than NT1. Tested with smbclient. JRA.
1772 * This should fix the OS/2 client bug #2335.
1775 if(numentries == 0) {
1776 dptr_close(&dptr_num);
1777 if (Protocol < PROTOCOL_NT1) {
1778 return ERROR_DOS(ERRDOS,ERRnofiles);
1780 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1784 /* At this point pdata points to numentries directory entries. */
1786 /* Set up the return parameter block */
1787 SSVAL(params,0,dptr_num);
1788 SSVAL(params,2,numentries);
1789 SSVAL(params,4,finished);
1790 SSVAL(params,6,0); /* Never an EA error */
1791 SSVAL(params,8,last_entry_off);
1793 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1795 if ((! *directory) && dptr_path(dptr_num))
1796 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1798 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1799 smb_fn_name(CVAL(inbuf,smb_com)),
1800 mask, directory, dirtype, numentries ) );
1803 * Force a name mangle here to ensure that the
1804 * mask as an 8.3 name is top of the mangled cache.
1805 * The reasons for this are subtle. Don't remove
1806 * this code unless you know what you are doing
1807 * (see PR#13758). JRA.
1810 if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn)))
1811 mangle_map(mask, True, True, SNUM(conn));
1816 /****************************************************************************
1817 Reply to a TRANS2_FINDNEXT.
1818 ****************************************************************************/
1820 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1821 char **pparams, int total_params, char **ppdata, int total_data,
1822 unsigned int max_data_bytes)
1824 /* We must be careful here that we don't return more than the
1825 allowed number of data bytes. If this means returning fewer than
1826 maxentries then so be it. We assume that the redirector has
1827 enough room for the fixed number of parameter bytes it has
1829 char *params = *pparams;
1830 char *pdata = *ppdata;
1831 int dptr_num = SVAL(params,0);
1832 int maxentries = SVAL(params,2);
1833 uint16 info_level = SVAL(params,4);
1834 uint32 resume_key = IVAL(params,6);
1835 uint16 findnext_flags = SVAL(params,10);
1836 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1837 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1838 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1839 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1840 pstring resume_name;
1846 int i, last_entry_off=0;
1847 BOOL finished = False;
1848 BOOL dont_descend = False;
1849 BOOL out_of_space = False;
1850 int space_remaining;
1851 TALLOC_CTX *ea_ctx = NULL;
1852 struct ea_list *ea_list = NULL;
1853 NTSTATUS ntstatus = NT_STATUS_OK;
1855 if (total_params < 12) {
1856 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1859 *mask = *directory = *resume_name = 0;
1861 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1862 if (!NT_STATUS_IS_OK(ntstatus)) {
1863 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1864 complain (it thinks we're asking for the directory above the shared
1865 path or an invalid name). Catch this as the resume name is only compared, never used in
1866 a file access. JRA. */
1867 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1868 pstrcpy(resume_name, "..");
1869 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1870 pstrcpy(resume_name, ".");
1872 return ERROR_NT(ntstatus);
1876 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1877 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1878 resume_key = %d resume name = %s continue=%d level = %d\n",
1879 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1880 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1883 /* W2K3 seems to treat zero as 1. */
1887 switch (info_level) {
1888 case SMB_FIND_INFO_STANDARD:
1889 case SMB_FIND_EA_SIZE:
1890 case SMB_FIND_EA_LIST:
1891 case SMB_FIND_FILE_DIRECTORY_INFO:
1892 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1893 case SMB_FIND_FILE_NAMES_INFO:
1894 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1896 case SMB_FIND_FILE_UNIX:
1897 if (!lp_unix_extensions())
1898 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1901 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1904 if (info_level == SMB_FIND_EA_LIST) {
1907 if (total_data < 4) {
1908 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1911 ea_size = IVAL(pdata,0);
1912 if (ea_size != total_data) {
1913 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1914 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1915 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1918 if (!lp_ea_support(SNUM(conn))) {
1919 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1922 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1923 return ERROR_NT(NT_STATUS_NO_MEMORY);
1926 /* Pull out the list of names. */
1927 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1929 talloc_destroy(ea_ctx);
1930 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1934 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1936 talloc_destroy(ea_ctx);
1937 return ERROR_NT(NT_STATUS_NO_MEMORY);
1941 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1943 /* Realloc the params space */
1944 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1945 if( params == NULL ) {
1946 talloc_destroy(ea_ctx);
1947 return ERROR_NT(NT_STATUS_NO_MEMORY);
1952 /* Check that the dptr is valid */
1953 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
1954 talloc_destroy(ea_ctx);
1955 return ERROR_DOS(ERRDOS,ERRnofiles);
1958 string_set(&conn->dirpath,dptr_path(dptr_num));
1960 /* Get the wildcard mask from the dptr */
1961 if((p = dptr_wcard(dptr_num))== NULL) {
1962 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1963 talloc_destroy(ea_ctx);
1964 return ERROR_DOS(ERRDOS,ERRnofiles);
1968 pstrcpy(directory,conn->dirpath);
1970 /* Get the attr mask from the dptr */
1971 dirtype = dptr_attr(dptr_num);
1973 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
1974 dptr_num, mask, dirtype,
1976 dptr_TellDir(conn->dirptr)));
1978 /* We don't need to check for VOL here as this is returned by
1979 a different TRANS2 call. */
1981 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1982 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1983 dont_descend = True;
1986 space_remaining = max_data_bytes;
1987 out_of_space = False;
1990 * Seek to the correct position. We no longer use the resume key but
1991 * depend on the last file name instead.
1994 if(*resume_name && !continue_bit) {
1997 long current_pos = 0;
1999 * Remember, mangle_map is called by
2000 * get_lanman2_dir_entry(), so the resume name
2001 * could be mangled. Ensure we check the unmangled name.
2004 if (mangle_is_mangled(resume_name, SNUM(conn))) {
2005 mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn));
2009 * Fix for NT redirector problem triggered by resume key indexes
2010 * changing between directory scans. We now return a resume key of 0
2011 * and instead look for the filename to continue from (also given
2012 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2013 * findfirst/findnext (as is usual) then the directory pointer
2014 * should already be at the correct place.
2017 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2018 } /* end if resume_name && !continue_bit */
2020 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2021 BOOL got_exact_match = False;
2023 /* this is a heuristic to avoid seeking the dirptr except when
2024 absolutely necessary. It allows for a filename of about 40 chars */
2025 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2026 out_of_space = True;
2029 finished = !get_lanman2_dir_entry(conn,
2031 mask,dirtype,info_level,
2032 requires_resume_key,dont_descend,
2033 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2034 &last_entry_off, ea_list, ea_ctx);
2037 if (finished && out_of_space)
2040 if (!finished && !out_of_space)
2044 * As an optimisation if we know we aren't looking
2045 * for a wildcard name (ie. the name matches the wildcard exactly)
2046 * then we can finish on any (first) match.
2047 * This speeds up large directory searches. JRA.
2053 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2056 talloc_destroy(ea_ctx);
2058 /* Check if we can close the dirptr */
2059 if(close_after_request || (finished && close_if_end)) {
2060 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2061 dptr_close(&dptr_num); /* This frees up the saved mask */
2064 /* Set up the return parameter block */
2065 SSVAL(params,0,numentries);
2066 SSVAL(params,2,finished);
2067 SSVAL(params,4,0); /* Never an EA error */
2068 SSVAL(params,6,last_entry_off);
2070 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2072 if ((! *directory) && dptr_path(dptr_num))
2073 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2075 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2076 smb_fn_name(CVAL(inbuf,smb_com)),
2077 mask, directory, dirtype, numentries ) );
2082 /****************************************************************************
2083 Reply to a TRANS2_QFSINFO (query filesystem info).
2084 ****************************************************************************/
2086 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2087 char **pparams, int total_params, char **ppdata, int total_data,
2088 unsigned int max_data_bytes)
2090 char *pdata = *ppdata;
2091 char *params = *pparams;
2092 uint16 info_level = SVAL(params,0);
2095 char *vname = volume_label(SNUM(conn));
2096 int snum = SNUM(conn);
2097 char *fstype = lp_fstype(SNUM(conn));
2100 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2102 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2103 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2104 return ERROR_DOS(ERRSRV,ERRinvdevice);
2107 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2108 if ( pdata == NULL ) {
2109 return ERROR_NT(NT_STATUS_NO_MEMORY);
2113 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2115 switch (info_level) {
2116 case SMB_INFO_ALLOCATION:
2118 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2120 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2121 return(UNIXERROR(ERRHRD,ERRgeneral));
2124 block_size = lp_block_size(snum);
2125 if (bsize < block_size) {
2126 SMB_BIG_UINT factor = block_size/bsize;
2131 if (bsize > block_size) {
2132 SMB_BIG_UINT factor = bsize/block_size;
2137 bytes_per_sector = 512;
2138 sectors_per_unit = bsize/bytes_per_sector;
2140 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2141 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2142 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2144 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2145 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2146 SIVAL(pdata,l1_cUnit,dsize);
2147 SIVAL(pdata,l1_cUnitAvail,dfree);
2148 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2152 case SMB_INFO_VOLUME:
2153 /* Return volume name */
2155 * Add volume serial number - hash of a combination of
2156 * the called hostname and the service name.
2158 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2160 * Win2k3 and previous mess this up by sending a name length
2161 * one byte short. I believe only older clients (OS/2 Win9x) use
2162 * this call so try fixing this by adding a terminating null to
2163 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2165 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2166 SCVAL(pdata,l2_vol_cch,len);
2167 data_len = l2_vol_szVolLabel + len;
2168 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2169 (unsigned)st.st_ctime, len, vname));
2172 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2173 case SMB_FS_ATTRIBUTE_INFORMATION:
2176 #if defined(HAVE_SYS_QUOTAS)
2177 quota_flag = FILE_VOLUME_QUOTAS;
2180 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2181 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2182 quota_flag); /* FS ATTRIBUTES */
2184 SIVAL(pdata,4,255); /* Max filename component length */
2185 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2186 and will think we can't do long filenames */
2187 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2189 data_len = 12 + len;
2192 case SMB_QUERY_FS_LABEL_INFO:
2193 case SMB_FS_LABEL_INFORMATION:
2194 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2199 case SMB_QUERY_FS_VOLUME_INFO:
2200 case SMB_FS_VOLUME_INFORMATION:
2203 * Add volume serial number - hash of a combination of
2204 * the called hostname and the service name.
2206 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2207 (str_checksum(get_local_machine_name())<<16));
2209 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2210 SIVAL(pdata,12,len);
2212 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2213 (int)strlen(vname),vname, lp_servicename(snum)));
2216 case SMB_QUERY_FS_SIZE_INFO:
2217 case SMB_FS_SIZE_INFORMATION:
2219 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2221 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2222 return(UNIXERROR(ERRHRD,ERRgeneral));
2224 block_size = lp_block_size(snum);
2225 if (bsize < block_size) {
2226 SMB_BIG_UINT factor = block_size/bsize;
2231 if (bsize > block_size) {
2232 SMB_BIG_UINT factor = bsize/block_size;
2237 bytes_per_sector = 512;
2238 sectors_per_unit = bsize/bytes_per_sector;
2239 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2240 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2241 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2242 SBIG_UINT(pdata,0,dsize);
2243 SBIG_UINT(pdata,8,dfree);
2244 SIVAL(pdata,16,sectors_per_unit);
2245 SIVAL(pdata,20,bytes_per_sector);
2249 case SMB_FS_FULL_SIZE_INFORMATION:
2251 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2253 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2254 return(UNIXERROR(ERRHRD,ERRgeneral));
2256 block_size = lp_block_size(snum);
2257 if (bsize < block_size) {
2258 SMB_BIG_UINT factor = block_size/bsize;
2263 if (bsize > block_size) {
2264 SMB_BIG_UINT factor = bsize/block_size;
2269 bytes_per_sector = 512;
2270 sectors_per_unit = bsize/bytes_per_sector;
2271 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2272 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2273 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2274 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2275 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2276 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2277 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2278 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2282 case SMB_QUERY_FS_DEVICE_INFO:
2283 case SMB_FS_DEVICE_INFORMATION:
2285 SIVAL(pdata,0,0); /* dev type */
2286 SIVAL(pdata,4,0); /* characteristics */
2289 #ifdef HAVE_SYS_QUOTAS
2290 case SMB_FS_QUOTA_INFORMATION:
2292 * what we have to send --metze:
2294 * Unknown1: 24 NULL bytes
2295 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2296 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2297 * Quota Flags: 2 byte :
2298 * Unknown3: 6 NULL bytes
2302 * details for Quota Flags:
2304 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2305 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2306 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2307 * 0x0001 Enable Quotas: enable quota for this fs
2311 /* we need to fake up a fsp here,
2312 * because its not send in this call
2315 SMB_NTQUOTA_STRUCT quotas;
2318 ZERO_STRUCT(quotas);
2325 if (current_user.uid != 0) {
2326 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2327 lp_servicename(SNUM(conn)),conn->user));
2328 return ERROR_DOS(ERRDOS,ERRnoaccess);
2331 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2332 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2333 return ERROR_DOS(ERRSRV,ERRerror);
2338 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2340 /* Unknown1 24 NULL bytes*/
2341 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2342 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2343 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2345 /* Default Soft Quota 8 bytes */
2346 SBIG_UINT(pdata,24,quotas.softlim);
2348 /* Default Hard Quota 8 bytes */
2349 SBIG_UINT(pdata,32,quotas.hardlim);
2351 /* Quota flag 2 bytes */
2352 SSVAL(pdata,40,quotas.qflags);
2354 /* Unknown3 6 NULL bytes */
2360 #endif /* HAVE_SYS_QUOTAS */
2361 case SMB_FS_OBJECTID_INFORMATION:
2366 * Query the version and capabilities of the CIFS UNIX extensions
2370 case SMB_QUERY_CIFS_UNIX_INFO:
2371 if (!lp_unix_extensions())
2372 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2374 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2375 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2376 SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
2379 case SMB_MAC_QUERY_FS_INFO:
2381 * Thursby MAC extension... ONLY on NTFS filesystems
2382 * once we do streams then we don't need this
2384 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2386 SIVAL(pdata,84,0x100); /* Don't support mac... */
2391 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2395 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2397 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2402 /****************************************************************************
2403 Reply to a TRANS2_SETFSINFO (set filesystem info).
2404 ****************************************************************************/
2406 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2407 char **pparams, int total_params, char **ppdata, int total_data,
2408 unsigned int max_data_bytes)
2410 char *pdata = *ppdata;
2411 char *params = *pparams;
2412 files_struct *fsp = NULL;
2415 SMB_NTQUOTA_STRUCT quotas;
2417 ZERO_STRUCT(quotas);
2419 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2422 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2423 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2424 lp_servicename(SNUM(conn)),conn->user));
2425 return ERROR_DOS(ERRSRV,ERRaccess);
2429 if (total_params < 4) {
2430 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2432 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2435 fsp = file_fsp(params,0);
2437 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2438 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2439 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2442 info_level = SVAL(params,2);
2444 switch(info_level) {
2445 case SMB_FS_QUOTA_INFORMATION:
2446 /* note: normaly there're 48 bytes,
2447 * but we didn't use the last 6 bytes for now
2450 if (total_data < 42) {
2451 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2453 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2456 /* unknown_1 24 NULL bytes in pdata*/
2458 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2459 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2460 #ifdef LARGE_SMB_OFF_T
2461 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2462 #else /* LARGE_SMB_OFF_T */
2463 if ((IVAL(pdata,28) != 0)&&
2464 ((quotas.softlim != 0xFFFFFFFF)||
2465 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2466 /* more than 32 bits? */
2467 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2469 #endif /* LARGE_SMB_OFF_T */
2471 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2472 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2473 #ifdef LARGE_SMB_OFF_T
2474 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2475 #else /* LARGE_SMB_OFF_T */
2476 if ((IVAL(pdata,36) != 0)&&
2477 ((quotas.hardlim != 0xFFFFFFFF)||
2478 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2479 /* more than 32 bits? */
2480 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2482 #endif /* LARGE_SMB_OFF_T */
2484 /* quota_flags 2 bytes **/
2485 quotas.qflags = SVAL(pdata,40);
2487 /* unknown_2 6 NULL bytes follow*/
2489 /* now set the quotas */
2490 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2491 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2492 return ERROR_DOS(ERRSRV,ERRerror);
2497 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2499 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2504 * sending this reply works fine,
2505 * but I'm not sure it's the same
2506 * like windows do...
2509 outsize = set_message(outbuf,10,0,True);
2514 /****************************************************************************
2515 Utility function to set bad path error.
2516 ****************************************************************************/
2518 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2520 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2521 err, (int)bad_path ));
2525 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2527 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2530 return UNIXERROR(def_class,def_code);
2533 #if defined(HAVE_POSIX_ACLS)
2534 /****************************************************************************
2535 Utility function to count the number of entries in a POSIX acl.
2536 ****************************************************************************/
2538 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2540 unsigned int ace_count = 0;
2541 int entry_id = SMB_ACL_FIRST_ENTRY;
2542 SMB_ACL_ENTRY_T entry;
2544 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2546 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2547 entry_id = SMB_ACL_NEXT_ENTRY;
2554 /****************************************************************************
2555 Utility function to marshall a POSIX acl into wire format.
2556 ****************************************************************************/
2558 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2560 int entry_id = SMB_ACL_FIRST_ENTRY;
2561 SMB_ACL_ENTRY_T entry;
2563 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2564 SMB_ACL_TAG_T tagtype;
2565 SMB_ACL_PERMSET_T permset;
2566 unsigned char perms = 0;
2567 unsigned int own_grp;
2570 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2571 entry_id = SMB_ACL_NEXT_ENTRY;
2574 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2575 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2579 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2580 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2584 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2585 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2586 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2588 SCVAL(pdata,1,perms);
2591 case SMB_ACL_USER_OBJ:
2592 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2593 own_grp = (unsigned int)pst->st_uid;
2594 SIVAL(pdata,2,own_grp);
2599 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2601 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2603 own_grp = (unsigned int)*puid;
2604 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2605 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2606 SIVAL(pdata,2,own_grp);
2610 case SMB_ACL_GROUP_OBJ:
2611 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2612 own_grp = (unsigned int)pst->st_gid;
2613 SIVAL(pdata,2,own_grp);
2618 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2620 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2622 own_grp = (unsigned int)*pgid;
2623 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2624 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2625 SIVAL(pdata,2,own_grp);
2630 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2631 SIVAL(pdata,2,0xFFFFFFFF);
2632 SIVAL(pdata,6,0xFFFFFFFF);
2635 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2636 SIVAL(pdata,2,0xFFFFFFFF);
2637 SIVAL(pdata,6,0xFFFFFFFF);
2640 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2643 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2650 /****************************************************************************
2651 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2652 file name or file id).
2653 ****************************************************************************/
2655 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2656 unsigned int tran_call,
2657 char **pparams, int total_params, char **ppdata, int total_data,
2658 unsigned int max_data_bytes)
2660 char *params = *pparams;
2661 char *pdata = *ppdata;
2664 SMB_OFF_T file_size=0;
2665 SMB_BIG_UINT allocation_size=0;
2666 unsigned int data_size = 0;
2667 unsigned int param_size = 2;
2668 SMB_STRUCT_STAT sbuf;
2669 pstring fname, dos_fname;
2674 BOOL bad_path = False;
2675 BOOL delete_pending = False;
2678 files_struct *fsp = NULL;
2679 TALLOC_CTX *ea_ctx = NULL;
2680 struct ea_list *ea_list = NULL;
2681 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2684 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2688 if (tran_call == TRANSACT2_QFILEINFO) {
2689 if (total_params < 4) {
2690 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2693 fsp = file_fsp(params,0);
2694 info_level = SVAL(params,2);
2696 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2698 if(fsp && (fsp->fake_file_handle)) {
2700 * This is actually for the QUOTA_FAKE_FILE --metze
2703 pstrcpy(fname, fsp->fsp_name);
2704 /* We know this name is ok, it's already passed the checks. */
2706 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2708 * This is actually a QFILEINFO on a directory
2709 * handle (returned from an NT SMB). NT5.0 seems
2710 * to do this call. JRA.
2712 /* We know this name is ok, it's already passed the checks. */
2713 pstrcpy(fname, fsp->fsp_name);
2715 if (INFO_LEVEL_IS_UNIX(info_level)) {
2716 /* Always do lstat for UNIX calls. */
2717 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2718 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2719 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2721 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2722 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2723 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2726 delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2729 * Original code - this is an open file.
2731 CHECK_FSP(fsp,conn);
2733 pstrcpy(fname, fsp->fsp_name);
2734 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2735 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2736 return(UNIXERROR(ERRDOS,ERRbadfid));
2738 pos = fsp->position_information;
2739 delete_pending = fsp->delete_on_close;
2740 desired_access = fsp->desired_access;
2743 NTSTATUS status = NT_STATUS_OK;
2746 if (total_params < 6) {
2747 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2750 info_level = SVAL(params,0);
2752 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2754 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2755 if (!NT_STATUS_IS_OK(status)) {
2756 return ERROR_NT(status);
2759 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2761 unix_convert(fname,conn,0,&bad_path,&sbuf);
2763 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2765 if (!check_name(fname,conn)) {
2766 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2767 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2770 if (INFO_LEVEL_IS_UNIX(info_level)) {
2771 /* Always do lstat for UNIX calls. */
2772 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2773 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2774 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2776 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2777 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2778 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2782 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2783 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2785 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2786 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2788 p = strrchr_m(fname,'/');
2794 mode = dos_mode(conn,fname,&sbuf);
2796 mode = FILE_ATTRIBUTE_NORMAL;
2798 fullpathname = fname;
2799 file_size = get_file_size(sbuf);
2801 /* This is necessary, as otherwise the desktop.ini file in
2802 * this folder is ignored */
2803 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2807 /* Pull any EA list from the data portion. */
2808 if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2811 if (total_data < 4) {
2812 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2814 ea_size = IVAL(pdata,0);
2816 if (total_data > 0 && ea_size != total_data) {
2817 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2818 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2819 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2822 if (!lp_ea_support(SNUM(conn))) {
2823 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2826 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2827 return ERROR_NT(NT_STATUS_NO_MEMORY);
2830 /* Pull out the list of names. */
2831 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2833 talloc_destroy(ea_ctx);
2834 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2838 params = SMB_REALLOC(*pparams,2);
2839 if (params == NULL) {
2840 talloc_destroy(ea_ctx);
2841 return ERROR_NT(NT_STATUS_NO_MEMORY);
2844 memset((char *)params,'\0',2);
2845 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2846 pdata = SMB_REALLOC(*ppdata, data_size);
2847 if ( pdata == NULL ) {
2848 talloc_destroy(ea_ctx);
2849 return ERROR_NT(NT_STATUS_NO_MEMORY);
2853 memset((char *)pdata,'\0',data_size);
2855 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2857 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2860 if (fsp->pending_modtime) {
2861 /* the pending modtime overrides the current modtime */
2862 sbuf.st_mtime = fsp->pending_modtime;
2865 /* Do we have this path open ? */
2866 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2867 if (fsp1 && fsp1->pending_modtime) {
2868 /* the pending modtime overrides the current modtime */
2869 sbuf.st_mtime = fsp1->pending_modtime;
2871 if (fsp1 && fsp1->initial_allocation_size) {
2872 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
2876 if (lp_dos_filetime_resolution(SNUM(conn))) {
2878 sbuf.st_atime &= ~1;
2879 sbuf.st_ctime &= ~1;
2880 sbuf.st_mtime &= ~1;
2883 /* NT expects the name to be in an exact form of the *full*
2884 filename. See the trans2 torture test */
2885 if (strequal(base_name,".")) {
2886 pstrcpy(dos_fname, "\\");
2888 pstr_sprintf(dos_fname, "\\%s", fname);
2889 string_replace(dos_fname, '/', '\\');
2892 switch (info_level) {
2893 case SMB_INFO_STANDARD:
2894 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2896 put_dos_date2(pdata,l1_fdateCreation,c_time);
2897 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2898 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2899 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2900 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2901 SSVAL(pdata,l1_attrFile,mode);
2904 case SMB_INFO_QUERY_EA_SIZE:
2906 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2907 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2909 put_dos_date2(pdata,l1_fdateCreation,c_time);
2910 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2911 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2912 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2913 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2914 SSVAL(pdata,l1_attrFile,mode);
2915 SIVAL(pdata,l1_attrFile+2,ea_size);
2919 case SMB_INFO_IS_NAME_VALID:
2920 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2921 if (tran_call == TRANSACT2_QFILEINFO) {
2922 /* os/2 needs this ? really ?*/
2923 return ERROR_DOS(ERRDOS,ERRbadfunc);
2929 case SMB_INFO_QUERY_EAS_FROM_LIST:
2931 size_t total_ea_len = 0;
2932 struct ea_list *ea_file_list = NULL;
2934 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2936 ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2937 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
2939 if (!ea_list || (total_ea_len > data_size)) {
2940 talloc_destroy(ea_ctx);
2942 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
2946 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
2947 talloc_destroy(ea_ctx);
2951 case SMB_INFO_QUERY_ALL_EAS:
2953 /* We have data_size bytes to put EA's into. */
2954 size_t total_ea_len = 0;
2956 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2958 ea_ctx = talloc_init("ea_ctx");
2960 return ERROR_NT(NT_STATUS_NO_MEMORY);
2963 ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2964 if (!ea_list || (total_ea_len > data_size)) {
2965 talloc_destroy(ea_ctx);
2967 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
2971 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
2972 talloc_destroy(ea_ctx);
2976 case SMB_FILE_BASIC_INFORMATION:
2977 case SMB_QUERY_FILE_BASIC_INFO:
2979 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2980 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2981 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2983 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2987 put_long_date(pdata,c_time);
2988 put_long_date(pdata+8,sbuf.st_atime);
2989 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2990 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2991 SIVAL(pdata,32,mode);
2993 DEBUG(5,("SMB_QFBI - "));
2995 time_t create_time = c_time;
2996 DEBUG(5,("create: %s ", ctime(&create_time)));
2998 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2999 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3000 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3001 DEBUG(5,("mode: %x\n", mode));
3005 case SMB_FILE_STANDARD_INFORMATION:
3006 case SMB_QUERY_FILE_STANDARD_INFO:
3008 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3010 SOFF_T(pdata,0,allocation_size);
3011 SOFF_T(pdata,8,file_size);
3012 if (delete_pending & sbuf.st_nlink)
3013 SIVAL(pdata,16,sbuf.st_nlink - 1);
3015 SIVAL(pdata,16,sbuf.st_nlink);
3017 SCVAL(pdata,21,(mode&aDIR)?1:0);
3020 case SMB_FILE_EA_INFORMATION:
3021 case SMB_QUERY_FILE_EA_INFO:
3023 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3024 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3026 SIVAL(pdata,0,ea_size);
3030 /* Get the 8.3 name - used if NT SMB was negotiated. */
3031 case SMB_QUERY_FILE_ALT_NAME_INFO:
3032 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3036 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3037 pstrcpy(short_name,base_name);
3038 /* Mangle if not already 8.3 */
3039 if(!mangle_is_8_3(short_name, True, SNUM(conn))) {
3040 mangle_map(short_name,True,True,SNUM(conn));
3042 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3043 data_size = 4 + len;
3048 case SMB_QUERY_FILE_NAME_INFO:
3050 this must be *exactly* right for ACLs on mapped drives to work
3052 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3053 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3054 data_size = 4 + len;
3058 case SMB_FILE_ALLOCATION_INFORMATION:
3059 case SMB_QUERY_FILE_ALLOCATION_INFO:
3060 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3062 SOFF_T(pdata,0,allocation_size);
3065 case SMB_FILE_END_OF_FILE_INFORMATION:
3066 case SMB_QUERY_FILE_END_OF_FILEINFO:
3067 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3069 SOFF_T(pdata,0,file_size);
3072 case SMB_QUERY_FILE_ALL_INFO:
3073 case SMB_FILE_ALL_INFORMATION:
3075 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3076 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3077 put_long_date(pdata,c_time);
3078 put_long_date(pdata+8,sbuf.st_atime);
3079 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3080 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3081 SIVAL(pdata,32,mode);
3083 SOFF_T(pdata,0,allocation_size);
3084 SOFF_T(pdata,8,file_size);
3085 if (delete_pending && sbuf.st_nlink)
3086 SIVAL(pdata,16,sbuf.st_nlink - 1);
3088 SIVAL(pdata,16,sbuf.st_nlink);
3089 SCVAL(pdata,20,delete_pending);
3090 SCVAL(pdata,21,(mode&aDIR)?1:0);
3092 SIVAL(pdata,0,ea_size);
3093 pdata += 4; /* EA info */
3094 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3097 data_size = PTR_DIFF(pdata,(*ppdata));
3100 case SMB_FILE_INTERNAL_INFORMATION:
3101 /* This should be an index number - looks like
3104 I think this causes us to fail the IFSKIT
3105 BasicFileInformationTest. -tpot */
3107 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3108 SIVAL(pdata,0,sbuf.st_dev);
3109 SIVAL(pdata,4,sbuf.st_ino);
3113 case SMB_FILE_ACCESS_INFORMATION:
3114 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3115 SIVAL(pdata,0,desired_access);
3119 case SMB_FILE_NAME_INFORMATION:
3120 /* Pathname with leading '\'. */
3123 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
3124 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3125 SIVAL(pdata,0,byte_len);
3126 data_size = 4 + byte_len;
3130 case SMB_FILE_DISPOSITION_INFORMATION:
3131 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3133 SCVAL(pdata,0,delete_pending);
3136 case SMB_FILE_POSITION_INFORMATION:
3137 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3139 SOFF_T(pdata,0,pos);
3142 case SMB_FILE_MODE_INFORMATION:
3143 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3144 SIVAL(pdata,0,mode);
3148 case SMB_FILE_ALIGNMENT_INFORMATION:
3149 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3150 SIVAL(pdata,0,0); /* No alignment needed. */
3156 * NT4 server just returns "invalid query" to this - if we try to answer
3157 * it then NTws gets a BSOD! (tridge).
3158 * W2K seems to want this. JRA.
3160 case SMB_QUERY_FILE_STREAM_INFO:
3162 case SMB_FILE_STREAM_INFORMATION:
3163 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3167 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
3168 SIVAL(pdata,0,0); /* ??? */
3169 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3170 SOFF_T(pdata,8,file_size);
3171 SIVAL(pdata,16,allocation_size);
3172 SIVAL(pdata,20,0); /* ??? */
3173 data_size = 24 + byte_len;
3177 case SMB_QUERY_COMPRESSION_INFO:
3178 case SMB_FILE_COMPRESSION_INFORMATION:
3179 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3180 SOFF_T(pdata,0,file_size);
3181 SIVAL(pdata,8,0); /* ??? */
3182 SIVAL(pdata,12,0); /* ??? */
3186 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3187 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3188 put_long_date(pdata,c_time);
3189 put_long_date(pdata+8,sbuf.st_atime);
3190 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3191 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3192 SIVAL(pdata,32,allocation_size);
3193 SOFF_T(pdata,40,file_size);
3194 SIVAL(pdata,48,mode);
3195 SIVAL(pdata,52,0); /* ??? */
3199 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3200 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3201 SIVAL(pdata,0,mode);
3207 * CIFS UNIX Extensions.
3210 case SMB_QUERY_FILE_UNIX_BASIC:
3212 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3213 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3215 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3218 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3221 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3222 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3223 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3226 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3230 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3234 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3237 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3241 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3245 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3248 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3252 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3255 data_size = PTR_DIFF(pdata,(*ppdata));
3259 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3261 for (i=0; i<100; i++)
3262 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3268 case SMB_QUERY_FILE_UNIX_LINK:
3272 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3274 if(!S_ISLNK(sbuf.st_mode))
3275 return(UNIXERROR(ERRSRV,ERRbadlink));
3277 return(UNIXERROR(ERRDOS,ERRbadlink));
3279 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3281 return(UNIXERROR(ERRDOS,ERRnoaccess));
3283 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3285 data_size = PTR_DIFF(pdata,(*ppdata));
3290 #if defined(HAVE_POSIX_ACLS)
3291 case SMB_QUERY_POSIX_ACL:
3293 SMB_ACL_T file_acl = NULL;
3294 SMB_ACL_T def_acl = NULL;
3295 uint16 num_file_acls = 0;
3296 uint16 num_def_acls = 0;
3298 if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
3299 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
3301 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3304 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3305 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3307 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3310 if (S_ISDIR(sbuf.st_mode)) {
3311 if (fsp && fsp->is_directory) {
3312 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3314 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3316 def_acl = free_empty_sys_acl(conn, def_acl);
3319 num_file_acls = count_acl_entries(conn, file_acl);
3320 num_def_acls = count_acl_entries(conn, def_acl);
3322 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3323 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3325 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3326 SMB_POSIX_ACL_HEADER_SIZE) ));
3328 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3331 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3333 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3336 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3337 SSVAL(pdata,2,num_file_acls);
3338 SSVAL(pdata,4,num_def_acls);
3339 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3341 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3344 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3346 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3348 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3350 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3353 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3355 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3359 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3362 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3364 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3370 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3373 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3378 /****************************************************************************
3379 Deal with the internal needs of setting the delete on close flag. Note that
3380 as the tdb locking is recursive, it is safe to call this from within
3381 open_file_shared. JRA.
3382 ****************************************************************************/
3384 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
3386 if (delete_on_close) {
3388 * Only allow delete on close for writable files.
3391 if (!lp_delete_readonly(SNUM(fsp->conn))) {
3392 if (dosmode & aRONLY) {
3393 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
3395 return NT_STATUS_CANNOT_DELETE;
3400 * Only allow delete on close for writable shares.
3403 if (!CAN_WRITE(fsp->conn)) {
3404 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
3406 return NT_STATUS_ACCESS_DENIED;
3410 * Only allow delete on close for files/directories opened with delete intent.
3413 if (!(fsp->desired_access & DELETE_ACCESS)) {
3414 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
3416 return NT_STATUS_ACCESS_DENIED;
3420 if(fsp->is_directory) {
3421 fsp->directory_delete_on_close = delete_on_close;
3422 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3423 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3425 fsp->delete_on_close = delete_on_close;
3426 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3427 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3430 return NT_STATUS_OK;
3433 /****************************************************************************
3434 Sets the delete on close flag over all share modes on this file.
3435 Modify the share mode entry for all files open
3436 on this device and inode to tell other smbds we have
3437 changed the delete on close flag. This will be noticed
3438 in the close code, the last closer will delete the file
3440 ****************************************************************************/
3442 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3444 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3445 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3447 if (fsp->is_directory || fsp->is_stat)
3448 return NT_STATUS_OK;
3450 if (lock_share_entry_fsp(fsp) == False)
3451 return NT_STATUS_ACCESS_DENIED;
3453 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3454 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3456 unlock_share_entry_fsp(fsp);
3457 return NT_STATUS_ACCESS_DENIED;
3460 unlock_share_entry_fsp(fsp);
3461 return NT_STATUS_OK;
3464 /****************************************************************************
3465 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3467 ****************************************************************************/
3469 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3471 BOOL bad_path_oldname = False;
3472 BOOL bad_path_newname = False;
3473 SMB_STRUCT_STAT sbuf1, sbuf2;
3474 pstring last_component_oldname;
3475 pstring last_component_newname;
3476 NTSTATUS status = NT_STATUS_OK;
3482 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3483 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3486 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3487 if (bad_path_oldname) {
3488 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3491 /* Quick check for "." and ".." */
3492 if (last_component_oldname[0] == '.') {
3493 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3494 return NT_STATUS_OBJECT_NAME_INVALID;
3498 /* source must already exist. */
3499 if (!VALID_STAT(sbuf1)) {
3500 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3503 if (!check_name(oldname,conn)) {
3504 return NT_STATUS_ACCESS_DENIED;
3507 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3508 if (bad_path_newname) {
3509 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3512 /* Quick check for "." and ".." */
3513 if (last_component_newname[0] == '.') {
3514 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3515 return NT_STATUS_OBJECT_NAME_INVALID;
3519 /* Disallow if newname already exists. */
3520 if (VALID_STAT(sbuf2)) {
3521 return NT_STATUS_OBJECT_NAME_COLLISION;
3524 if (!check_name(newname,conn)) {
3525 return NT_STATUS_ACCESS_DENIED;
3528 /* No links from a directory. */
3529 if (S_ISDIR(sbuf1.st_mode)) {
3530 return NT_STATUS_FILE_IS_A_DIRECTORY;
3533 /* Ensure this is within the share. */
3534 if (!reduce_name(conn, oldname) != 0)
3535 return NT_STATUS_ACCESS_DENIED;
3537 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3539 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3540 status = map_nt_error_from_unix(errno);
3541 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3542 nt_errstr(status), newname, oldname));
3548 /****************************************************************************
3549 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3550 ****************************************************************************/
3552 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3553 unsigned int tran_call,
3554 char **pparams, int total_params, char **ppdata, int total_data,
3555 unsigned int max_data_bytes)
3557 char *params = *pparams;
3558 char *pdata = *ppdata;
3563 SMB_STRUCT_STAT sbuf;
3566 BOOL bad_path = False;
3567 files_struct *fsp = NULL;
3568 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3569 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3570 mode_t unixmode = 0;
3571 NTSTATUS status = NT_STATUS_OK;
3574 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3579 if (tran_call == TRANSACT2_SETFILEINFO) {
3580 if (total_params < 4) {
3581 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3584 fsp = file_fsp(params,0);
3585 info_level = SVAL(params,2);
3587 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3589 * This is actually a SETFILEINFO on a directory
3590 * handle (returned from an NT SMB). NT5.0 seems
3591 * to do this call. JRA.
3593 pstrcpy(fname, fsp->fsp_name);
3594 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3595 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3596 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3598 } else if (fsp && fsp->print_file) {
3600 * Doing a DELETE_ON_CLOSE should cancel a print job.
3602 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3603 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3605 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3608 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3611 return (UNIXERROR(ERRDOS,ERRbadpath));
3614 * Original code - this is an open file.
3616 CHECK_FSP(fsp,conn);
3618 pstrcpy(fname, fsp->fsp_name);
3621 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3622 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3623 return(UNIXERROR(ERRDOS,ERRbadfid));
3628 if (total_params < 6) {
3629 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3632 info_level = SVAL(params,0);
3633 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3634 if (!NT_STATUS_IS_OK(status)) {
3635 return ERROR_NT(status);
3637 unix_convert(fname,conn,0,&bad_path,&sbuf);
3639 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3643 * For CIFS UNIX extensions the target name may not exist.
3646 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3647 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3648 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3651 if(!check_name(fname, conn)) {
3652 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3657 if (!CAN_WRITE(conn))
3658 return ERROR_DOS(ERRSRV,ERRaccess);
3660 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3661 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3663 if (VALID_STAT(sbuf))
3664 unixmode = sbuf.st_mode;
3666 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3667 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3669 /* Realloc the parameter size */
3670 params = SMB_REALLOC(*pparams,2);
3671 if(params == NULL) {
3672 return ERROR_NT(NT_STATUS_NO_MEMORY);
3678 if (fsp && fsp->pending_modtime) {
3679 /* the pending modtime overrides the current modtime */
3680 sbuf.st_mtime = fsp->pending_modtime;
3683 size = get_file_size(sbuf);
3684 tvs.modtime = sbuf.st_mtime;
3685 tvs.actime = sbuf.st_atime;
3686 dosmode = dos_mode(conn,fname,&sbuf);
3687 unixmode = sbuf.st_mode;
3689 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3690 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3692 switch (info_level) {
3693 case SMB_INFO_STANDARD:
3695 if (total_data < 12) {
3696 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3700 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3702 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3706 case SMB_INFO_SET_EA:
3708 struct ea_list *ea_list = NULL;
3709 TALLOC_CTX *ctx = NULL;
3711 if (total_data < 10) {
3712 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3715 if (IVAL(pdata,0) > total_data) {
3716 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3717 IVAL(pdata,0), (unsigned int)total_data));
3718 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3721 ctx = talloc_init("SMB_INFO_SET_EA");
3723 return ERROR_NT(NT_STATUS_NO_MEMORY);
3725 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3727 talloc_destroy(ctx);
3728 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3730 status = set_ea(conn, fsp, fname, ea_list);
3731 talloc_destroy(ctx);
3733 if (!NT_STATUS_IS_OK(status)) {
3734 return ERROR_NT(status);
3737 /* We're done. We only get EA info in this call. */
3739 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3744 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3745 /* XXXX um, i don't think this is right.
3746 it's also not in the cifs6.txt spec.
3748 case SMB_INFO_QUERY_EAS_FROM_LIST:
3749 if (total_data < 28)
3750 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3752 tvs.actime = make_unix_date2(pdata+8);
3753 tvs.modtime = make_unix_date2(pdata+12);
3754 size = IVAL(pdata,16);
3755 dosmode = IVAL(pdata,24);
3758 /* XXXX nor this. not in cifs6.txt, either. */
3759 case SMB_INFO_QUERY_ALL_EAS:
3760 if (total_data < 28)
3761 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3763 tvs.actime = make_unix_date2(pdata+8);
3764 tvs.modtime = make_unix_date2(pdata+12);
3765 size = IVAL(pdata,16);
3766 dosmode = IVAL(pdata,24);
3770 case SMB_SET_FILE_BASIC_INFO:
3771 case SMB_FILE_BASIC_INFORMATION:
3773 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3775 time_t changed_time;
3777 if (total_data < 36) {
3778 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3781 /* Ignore create time at offset pdata. */
3784 tvs.actime = interpret_long_date(pdata+8);
3786 write_time = interpret_long_date(pdata+16);
3787 changed_time = interpret_long_date(pdata+24);
3789 tvs.modtime = MIN(write_time, changed_time);
3791 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3792 tvs.modtime = write_time;
3794 /* Prefer a defined time to an undefined one. */
3795 if (null_mtime(tvs.modtime)) {
3796 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3800 dosmode = IVAL(pdata,32);
3804 case SMB_FILE_ALLOCATION_INFORMATION:
3805 case SMB_SET_FILE_ALLOCATION_INFO:
3808 SMB_BIG_UINT allocation_size;
3810 if (total_data < 8) {
3811 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3814 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3815 #ifdef LARGE_SMB_OFF_T
3816 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3817 #else /* LARGE_SMB_OFF_T */
3818 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3819 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3820 #endif /* LARGE_SMB_OFF_T */
3821 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3822 fname, (double)allocation_size ));
3824 if (allocation_size) {
3825 allocation_size = smb_roundup(conn, allocation_size);
3828 if(allocation_size != get_file_size(sbuf)) {
3829 SMB_STRUCT_STAT new_sbuf;
3831 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3832 fname, (double)allocation_size ));
3835 files_struct *new_fsp = NULL;
3836 int access_mode = 0;
3839 if(global_oplock_break) {
3840 /* Queue this file modify as we are the process of an oplock break. */
3842 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3843 DEBUGADD(2,( "in oplock break state.\n"));
3845 push_oplock_pending_smb_message(inbuf, length);
3849 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3850 SET_OPEN_MODE(DOS_OPEN_RDWR),
3851 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3852 FILE_ATTRIBUTE_NORMAL,
3853 INTERNAL_OPEN_ONLY, &access_mode, &action);
3855 if (new_fsp == NULL)
3856 return(UNIXERROR(ERRDOS,ERRbadpath));
3857 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3858 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3859 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3860 new_fsp->fnum, strerror(errno)));
3863 close_file(new_fsp,True);
3865 ret = vfs_allocate_file_space(fsp, allocation_size);
3866 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3867 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3868 fsp->fnum, strerror(errno)));
3873 return ERROR_NT(NT_STATUS_DISK_FULL);
3875 /* Allocate can truncate size... */
3876 size = get_file_size(new_sbuf);
3882 case SMB_FILE_END_OF_FILE_INFORMATION:
3883 case SMB_SET_FILE_END_OF_FILE_INFO:
3885 if (total_data < 8) {
3886 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3889 size = IVAL(pdata,0);
3890 #ifdef LARGE_SMB_OFF_T
3891 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3892 #else /* LARGE_SMB_OFF_T */
3893 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3894 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3895 #endif /* LARGE_SMB_OFF_T */
3896 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3900 case SMB_FILE_DISPOSITION_INFORMATION:
3901 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3903 BOOL delete_on_close;
3905 if (total_data < 1) {
3906 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3909 delete_on_close = (CVAL(pdata,0) ? True : False);
3911 /* Just ignore this set on a path. */
3912 if (tran_call != TRANSACT2_SETFILEINFO)
3916 return(UNIXERROR(ERRDOS,ERRbadfid));
3918 status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3920 if (!NT_STATUS_IS_OK(status)) {
3921 return ERROR_NT(status);
3924 /* The set is across all open files on this dev/inode pair. */
3925 status =set_delete_on_close_over_all(fsp, delete_on_close);
3926 if (!NT_STATUS_IS_OK(status)) {
3927 return ERROR_NT(status);
3931 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
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;
3956 /* We're done. We only get position info in this call. */
3958 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3962 /* From tridge Samba4 :
3963 * MODE_INFORMATION in setfileinfo (I have no
3964 * idea what "mode information" on a file is - it takes a value of 0,
3965 * 2, 4 or 6. What could it be?).
3968 case SMB_FILE_MODE_INFORMATION:
3972 if (total_data < 4) {
3973 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3975 mode = IVAL(pdata,0);
3976 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
3977 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3980 /* We're done. We only get mode info in this call. */
3982 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3987 * CIFS UNIX extensions.
3990 case SMB_SET_FILE_UNIX_BASIC:
3992 uint32 raw_unixmode;
3994 if (total_data < 100) {
3995 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3998 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3999 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4000 size=IVAL(pdata,0); /* first 8 Bytes are size */
4001 #ifdef LARGE_SMB_OFF_T
4002 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4003 #else /* LARGE_SMB_OFF_T */
4004 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
4005 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4006 #endif /* LARGE_SMB_OFF_T */
4008 pdata+=24; /* ctime & st_blocks are not changed */
4009 tvs.actime = interpret_long_date(pdata); /* access_time */
4010 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
4012 set_owner = (uid_t)IVAL(pdata,0);
4014 set_grp = (gid_t)IVAL(pdata,0);
4016 raw_unixmode = IVAL(pdata,28);
4017 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4018 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4020 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4021 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4022 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4024 if (!VALID_STAT(sbuf)) {
4027 * The only valid use of this is to create character and block
4028 * devices, and named pipes. This is deprecated (IMHO) and
4029 * a new info level should be used for mknod. JRA.
4032 uint32 file_type = IVAL(pdata,0);
4033 #if defined(HAVE_MAKEDEV)
4034 uint32 dev_major = IVAL(pdata,4);
4035 uint32 dev_minor = IVAL(pdata,12);
4038 uid_t myuid = geteuid();
4039 gid_t mygid = getegid();
4040 SMB_DEV_T dev = (SMB_DEV_T)0;
4042 if (tran_call == TRANSACT2_SETFILEINFO)
4043 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4045 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4046 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4049 #if defined(HAVE_MAKEDEV)
4050 dev = makedev(dev_major, dev_minor);
4053 /* We can only create as the owner/group we are. */
4055 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4056 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4057 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4058 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4060 switch (file_type) {
4061 #if defined(S_IFIFO)
4062 case UNIX_TYPE_FIFO:
4063 unixmode |= S_IFIFO;
4066 #if defined(S_IFSOCK)
4067 case UNIX_TYPE_SOCKET:
4068 unixmode |= S_IFSOCK;
4071 #if defined(S_IFCHR)
4072 case UNIX_TYPE_CHARDEV:
4073 unixmode |= S_IFCHR;
4076 #if defined(S_IFBLK)
4077 case UNIX_TYPE_BLKDEV:
4078 unixmode |= S_IFBLK;
4082 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4085 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4086 0%o for file %s\n", (double)dev, unixmode, fname ));
4088 /* Ok - do the mknod. */
4089 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4090 return(UNIXERROR(ERRDOS,ERRnoaccess));
4092 inherit_access_acl(conn, fname, unixmode);
4095 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4100 * Deal with the UNIX specific mode set.
4103 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4104 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4105 (unsigned int)unixmode, fname ));
4106 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4107 return(UNIXERROR(ERRDOS,ERRnoaccess));
4111 * Deal with the UNIX specific uid set.
4114 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4115 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4116 (unsigned int)set_owner, fname ));
4117 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4118 return(UNIXERROR(ERRDOS,ERRnoaccess));
4122 * Deal with the UNIX specific gid set.
4125 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4126 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4127 (unsigned int)set_owner, fname ));
4128 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4129 return(UNIXERROR(ERRDOS,ERRnoaccess));
4134 case SMB_SET_FILE_UNIX_LINK:
4136 pstring link_target;
4137 char *newname = fname;
4139 /* Set a symbolic link. */
4140 /* Don't allow this if follow links is false. */
4142 if (!lp_symlinks(SNUM(conn)))
4143 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4145 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4147 /* !widelinks forces the target path to be within the share. */
4148 /* This means we can interpret the target as a pathname. */
4149 if (!lp_widelinks(SNUM(conn))) {
4151 char *last_dirp = NULL;
4153 unix_format(link_target);
4154 if (*link_target == '/') {
4155 /* No absolute paths allowed. */
4156 return(UNIXERROR(ERRDOS,ERRnoaccess));
4158 pstrcpy(rel_name, newname);
4159 last_dirp = strrchr_m(rel_name, '/');
4161 last_dirp[1] = '\0';
4163 pstrcpy(rel_name, "./");
4165 pstrcat(rel_name, link_target);
4167 if (!check_name(rel_name, conn)) {
4168 return(UNIXERROR(ERRDOS,ERRnoaccess));
4172 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4173 fname, link_target ));
4175 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4176 return(UNIXERROR(ERRDOS,ERRnoaccess));
4178 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4182 case SMB_SET_FILE_UNIX_HLINK:
4185 char *newname = fname;
4187 /* Set a hard link. */
4188 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
4189 if (!NT_STATUS_IS_OK(status)) {
4190 return ERROR_NT(status);
4193 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4196 status = hardlink_internals(conn, oldname, newname);
4197 if (!NT_STATUS_IS_OK(status)) {
4198 return ERROR_NT(status);
4202 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4206 case SMB_FILE_RENAME_INFORMATION:
4215 if (total_data < 12) {
4216 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4219 overwrite = (CVAL(pdata,0) ? True : False);
4220 root_fid = IVAL(pdata,4);
4221 len = IVAL(pdata,8);
4222 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
4223 if (!NT_STATUS_IS_OK(status)) {
4224 return ERROR_NT(status);
4227 /* Check the new name has no '/' characters. */
4228 if (strchr_m(newname, '/'))
4229 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4231 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4233 /* Create the base directory. */
4234 pstrcpy(base_name, fname);
4235 p = strrchr_m(base_name, '/');
4238 /* Append the new name. */
4239 pstrcat(base_name, "/");
4240 pstrcat(base_name, newname);
4243 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4244 fsp->fnum, fsp->fsp_name, base_name ));
4245 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4247 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4249 status = rename_internals(conn, fname, base_name, 0, overwrite);
4251 if (!NT_STATUS_IS_OK(status)) {
4252 return ERROR_NT(status);
4254 process_pending_change_notify_queue((time_t)0);
4256 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4260 #if defined(HAVE_POSIX_ACLS)
4261 case SMB_SET_POSIX_ACL:
4263 uint16 posix_acl_version;
4264 uint16 num_file_acls;
4265 uint16 num_def_acls;
4266 BOOL valid_file_acls = True;
4267 BOOL valid_def_acls = True;
4269 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4270 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4272 posix_acl_version = SVAL(pdata,0);
4273 num_file_acls = SVAL(pdata,2);
4274 num_def_acls = SVAL(pdata,4);
4276 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4277 valid_file_acls = False;
4281 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4282 valid_def_acls = False;
4286 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4287 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4290 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4291 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4292 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4295 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4296 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4297 return(UNIXERROR(ERRDOS,ERRnoaccess));
4300 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4301 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4302 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4303 return(UNIXERROR(ERRDOS,ERRnoaccess));
4307 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4313 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4316 /* get some defaults (no modifications) if any info is zero or -1. */
4317 if (null_mtime(tvs.actime)) {
4318 tvs.actime = sbuf.st_atime;
4321 if (null_mtime(tvs.modtime)) {
4322 tvs.modtime = sbuf.st_mtime;
4325 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4326 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4327 DEBUG(6,("size: %.0f ", (double)size));
4330 if (S_ISDIR(sbuf.st_mode))
4336 DEBUG(6,("dosmode: %x\n" , dosmode));
4338 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4339 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4340 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4341 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4344 * Only do this test if we are not explicitly
4345 * changing the size of a file.
4348 size = get_file_size(sbuf);
4352 * Try and set the times, size and mode of this file -
4353 * if they are different from the current values
4356 /* check the mode isn't different, before changing it */
4357 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4359 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4361 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4362 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4363 return(UNIXERROR(ERRDOS,ERRnoaccess));
4368 if (size != get_file_size(sbuf)) {
4372 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4373 fname, (double)size ));
4376 files_struct *new_fsp = NULL;
4377 int access_mode = 0;
4380 if(global_oplock_break) {
4381 /* Queue this file modify as we are the process of an oplock break. */
4383 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
4384 DEBUGADD(2,( "in oplock break state.\n"));
4386 push_oplock_pending_smb_message(inbuf, length);
4390 new_fsp = open_file_shared(conn, fname, &sbuf,
4391 SET_OPEN_MODE(DOS_OPEN_RDWR),
4392 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
4393 FILE_ATTRIBUTE_NORMAL,
4394 INTERNAL_OPEN_ONLY, &access_mode, &action);
4396 if (new_fsp == NULL)
4397 return(UNIXERROR(ERRDOS,ERRbadpath));
4398 ret = vfs_set_filelen(new_fsp, size);
4399 close_file(new_fsp,True);
4401 ret = vfs_set_filelen(fsp, size);
4405 return (UNIXERROR(ERRHRD,ERRdiskfull));
4409 * Finally the times.
4411 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4414 * This was a setfileinfo on an open file.
4415 * NT does this a lot. We also need to
4416 * set the time here, as it can be read by
4417 * FindFirst/FindNext and with the patch for bug #2045
4418 * in smbd/fileio.c it ensures that this timestamp is
4419 * kept sticky even after a write. We save the request
4420 * away and will set it on file close and after a write. JRA.
4423 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4424 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4425 fsp_set_pending_modtime(fsp, tvs.modtime);
4429 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4431 if(file_utime(conn, fname, &tvs)!=0) {
4432 return(UNIXERROR(ERRDOS,ERRnoaccess));
4437 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4442 /****************************************************************************
4443 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4444 ****************************************************************************/
4446 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4447 char **pparams, int total_params, char **ppdata, int total_data,
4448 unsigned int max_data_bytes)
4450 char *params = *pparams;
4451 char *pdata = *ppdata;
4454 SMB_STRUCT_STAT sbuf;
4455 BOOL bad_path = False;
4456 NTSTATUS status = NT_STATUS_OK;
4457 TALLOC_CTX *ctx = NULL;
4458 struct ea_list *ea_list = NULL;
4460 if (!CAN_WRITE(conn))
4461 return ERROR_DOS(ERRSRV,ERRaccess);
4463 if (total_params < 4) {
4464 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4467 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4468 if (!NT_STATUS_IS_OK(status)) {
4469 return ERROR_NT(status);
4472 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4474 unix_convert(directory,conn,0,&bad_path,&sbuf);
4476 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4479 /* Any data in this call is an EA list. */
4480 if (total_data && !lp_ea_support(SNUM(conn))) {
4481 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4485 if (total_data < 10) {
4486 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4489 if (IVAL(pdata,0) > total_data) {
4490 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4491 IVAL(pdata,0), (unsigned int)total_data));
4492 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4495 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4497 return ERROR_NT(NT_STATUS_NO_MEMORY);
4499 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4501 talloc_destroy(ctx);
4502 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4506 if (check_name(directory,conn)) {
4507 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4511 talloc_destroy(ctx);
4512 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4513 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4516 /* Try and set any given EA. */
4518 status = set_ea(conn, NULL, directory, ea_list);
4519 talloc_destroy(ctx);
4520 if (!NT_STATUS_IS_OK(status)) {
4521 return ERROR_NT(status);
4525 /* Realloc the parameter and data sizes */
4526 params = SMB_REALLOC(*pparams,2);
4527 if(params == NULL) {
4528 return ERROR_NT(NT_STATUS_NO_MEMORY);
4534 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4539 /****************************************************************************
4540 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4541 We don't actually do this - we just send a null response.
4542 ****************************************************************************/
4544 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4545 char **pparams, int total_params, char **ppdata, int total_data,
4546 unsigned int max_data_bytes)
4548 static uint16 fnf_handle = 257;
4549 char *params = *pparams;
4552 if (total_params < 6) {
4553 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4556 info_level = SVAL(params,4);
4557 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4559 switch (info_level) {
4564 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4567 /* Realloc the parameter and data sizes */
4568 params = SMB_REALLOC(*pparams,6);
4569 if(params == NULL) {
4570 return ERROR_NT(NT_STATUS_NO_MEMORY);
4574 SSVAL(params,0,fnf_handle);
4575 SSVAL(params,2,0); /* No changes */
4576 SSVAL(params,4,0); /* No EA errors */
4583 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4588 /****************************************************************************
4589 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4590 changes). Currently this does nothing.
4591 ****************************************************************************/
4593 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4594 char **pparams, int total_params, char **ppdata, int total_data,
4595 unsigned int max_data_bytes)
4597 char *params = *pparams;
4599 DEBUG(3,("call_trans2findnotifynext\n"));
4601 /* Realloc the parameter and data sizes */
4602 params = SMB_REALLOC(*pparams,4);
4603 if(params == NULL) {
4604 return ERROR_NT(NT_STATUS_NO_MEMORY);
4608 SSVAL(params,0,0); /* No changes */
4609 SSVAL(params,2,0); /* No EA errors */
4611 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4616 /****************************************************************************
4617 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4618 ****************************************************************************/
4620 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4621 char **pparams, int total_params, char **ppdata, int total_data,
4622 unsigned int max_data_bytes)
4624 char *params = *pparams;
4627 int max_referral_level;
4629 DEBUG(10,("call_trans2getdfsreferral\n"));
4631 if (total_params < 2) {
4632 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4635 max_referral_level = SVAL(params,0);
4637 if(!lp_host_msdfs())
4638 return ERROR_DOS(ERRDOS,ERRbadfunc);
4640 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4641 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4642 return UNIXERROR(ERRDOS,ERRbadfile);
4644 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4645 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4650 #define LMCAT_SPL 0x53
4651 #define LMFUNC_GETJOBID 0x60
4653 /****************************************************************************
4654 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4655 ****************************************************************************/
4657 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4658 char **pparams, int total_params, char **ppdata, int total_data,
4659 unsigned int max_data_bytes)
4661 char *pdata = *ppdata;
4662 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4664 /* check for an invalid fid before proceeding */
4667 return(ERROR_DOS(ERRDOS,ERRbadfid));
4669 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4670 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4671 pdata = SMB_REALLOC(*ppdata, 32);
4673 return ERROR_NT(NT_STATUS_NO_MEMORY);
4677 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4678 CAN ACCEPT THIS IN UNICODE. JRA. */
4680 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4681 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4682 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4683 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4686 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4687 return ERROR_DOS(ERRSRV,ERRerror);
4691 /****************************************************************************
4692 Reply to a SMBfindclose (stop trans2 directory search).
4693 ****************************************************************************/
4695 int reply_findclose(connection_struct *conn,
4696 char *inbuf,char *outbuf,int length,int bufsize)
4699 int dptr_num=SVALS(inbuf,smb_vwv0);
4700 START_PROFILE(SMBfindclose);
4702 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4704 dptr_close(&dptr_num);
4706 outsize = set_message(outbuf,0,0,True);
4708 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4710 END_PROFILE(SMBfindclose);
4714 /****************************************************************************
4715 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4716 ****************************************************************************/
4718 int reply_findnclose(connection_struct *conn,
4719 char *inbuf,char *outbuf,int length,int bufsize)
4723 START_PROFILE(SMBfindnclose);
4725 dptr_num = SVAL(inbuf,smb_vwv0);
4727 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4729 /* We never give out valid handles for a
4730 findnotifyfirst - so any dptr_num is ok here.
4733 outsize = set_message(outbuf,0,0,True);
4735 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4737 END_PROFILE(SMBfindnclose);
4741 /****************************************************************************
4742 Reply to a SMBtranss2 - just ignore it!
4743 ****************************************************************************/
4745 int reply_transs2(connection_struct *conn,
4746 char *inbuf,char *outbuf,int length,int bufsize)
4748 START_PROFILE(SMBtranss2);
4749 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4750 END_PROFILE(SMBtranss2);
4754 /****************************************************************************
4755 Reply to a SMBtrans2.
4756 ****************************************************************************/
4758 int reply_trans2(connection_struct *conn,
4759 char *inbuf,char *outbuf,int length,int bufsize)
4762 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4763 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4764 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4766 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4767 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4768 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4769 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4770 int32 timeout = IVALS(inbuf,smb_timeout);
4772 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4773 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4774 char *params = NULL, *data = NULL;
4775 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4776 START_PROFILE(SMBtrans2);
4778 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4779 /* Queue this open message as we are the process of an
4782 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4783 DEBUGADD(2,( "in oplock break state.\n"));
4785 push_oplock_pending_smb_message(inbuf, length);
4786 END_PROFILE(SMBtrans2);
4790 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4791 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4792 END_PROFILE(SMBtrans2);
4793 return ERROR_DOS(ERRSRV,ERRaccess);
4796 outsize = set_message(outbuf,0,0,True);
4798 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4799 is so as a sanity check */
4802 * Need to have rc=0 for ioctl to get job id for OS/2.
4803 * Network printing will fail if function is not successful.
4804 * Similar function in reply.c will be used if protocol
4805 * is LANMAN1.0 instead of LM1.2X002.
4806 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4807 * outbuf doesn't have to be set(only job id is used).
4809 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4810 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4811 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4812 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4814 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4815 DEBUG(2,("Transaction is %d\n",tran_call));
4816 END_PROFILE(SMBtrans2);
4817 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4821 /* Allocate the space for the maximum needed parameters and data */
4822 if (total_params > 0)
4823 params = (char *)SMB_MALLOC(total_params);
4825 data = (char *)SMB_MALLOC(total_data);
4827 if ((total_params && !params) || (total_data && !data)) {
4828 DEBUG(2,("Out of memory in reply_trans2\n"));
4831 END_PROFILE(SMBtrans2);
4832 return ERROR_NT(NT_STATUS_NO_MEMORY);
4835 /* Copy the param and data bytes sent with this request into
4836 the params buffer */
4837 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4838 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4840 if (num_params > total_params || num_data > total_data)
4841 exit_server("invalid params in reply_trans2");
4844 unsigned int psoff = SVAL(inbuf, smb_psoff);
4845 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4847 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4848 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4850 memcpy( params, smb_base(inbuf) + psoff, num_params);
4853 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4854 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4856 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4857 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4859 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4862 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4864 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4865 /* We need to send an interim response then receive the rest
4866 of the parameter/data bytes */
4867 outsize = set_message(outbuf,0,0,True);
4868 srv_signing_trans_stop();
4869 if (!send_smb(smbd_server_fd(),outbuf))
4870 exit_server("reply_trans2: send_smb failed.");
4872 while (num_data_sofar < total_data ||
4873 num_params_sofar < total_params) {
4875 unsigned int param_disp;
4876 unsigned int param_off;
4877 unsigned int data_disp;
4878 unsigned int data_off;
4880 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4882 /* We need to re-calcuate the new length after we've read the secondary packet. */
4883 length = smb_len(inbuf) + 4;
4886 * The sequence number for the trans reply is always
4887 * based on the last secondary received.
4890 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4893 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4894 outsize = set_message(outbuf,0,0,True);
4896 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4898 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4899 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4903 /* Revise total_params and total_data in case
4904 they have changed downwards */
4905 if (SVAL(inbuf, smb_tpscnt) < total_params)
4906 total_params = SVAL(inbuf, smb_tpscnt);
4907 if (SVAL(inbuf, smb_tdscnt) < total_data)
4908 total_data = SVAL(inbuf, smb_tdscnt);
4910 num_params = SVAL(inbuf,smb_spscnt);
4911 param_off = SVAL(inbuf, smb_spsoff);
4912 param_disp = SVAL(inbuf, smb_spsdisp);
4913 num_params_sofar += num_params;
4915 num_data = SVAL(inbuf, smb_sdscnt);
4916 data_off = SVAL(inbuf, smb_sdsoff);
4917 data_disp = SVAL(inbuf, smb_sdsdisp);
4918 num_data_sofar += num_data;
4920 if (num_params_sofar > total_params || num_data_sofar > total_data)
4924 if (param_disp + num_params > total_params)
4926 if ((param_disp + num_params < param_disp) ||
4927 (param_disp + num_params < num_params))
4929 if (param_disp > total_params)
4931 if ((smb_base(inbuf) + param_off + num_params > inbuf + length) ||
4932 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4934 if (params + param_disp < params)
4937 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
4940 if (data_disp + num_data > total_data)
4942 if ((data_disp + num_data < data_disp) ||
4943 (data_disp + num_data < num_data))
4945 if (data_disp > total_data)
4947 if ((smb_base(inbuf) + data_off + num_data > inbuf + length) ||
4948 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4950 if (data + data_disp < data)
4953 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4958 if (Protocol >= PROTOCOL_NT1) {
4959 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4962 /* Now we must call the relevant TRANS2 function */
4964 case TRANSACT2_OPEN:
4965 START_PROFILE_NESTED(Trans2_open);
4966 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4967 ¶ms, total_params, &data, total_data, max_data_bytes);
4968 END_PROFILE_NESTED(Trans2_open);
4971 case TRANSACT2_FINDFIRST:
4972 START_PROFILE_NESTED(Trans2_findfirst);
4973 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4974 ¶ms, total_params, &data, total_data, max_data_bytes);
4975 END_PROFILE_NESTED(Trans2_findfirst);
4978 case TRANSACT2_FINDNEXT:
4979 START_PROFILE_NESTED(Trans2_findnext);
4980 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4981 ¶ms, total_params, &data, total_data, max_data_bytes);
4982 END_PROFILE_NESTED(Trans2_findnext);
4985 case TRANSACT2_QFSINFO:
4986 START_PROFILE_NESTED(Trans2_qfsinfo);
4987 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4988 ¶ms, total_params, &data, total_data, max_data_bytes);
4989 END_PROFILE_NESTED(Trans2_qfsinfo);
4992 case TRANSACT2_SETFSINFO:
4993 START_PROFILE_NESTED(Trans2_setfsinfo);
4994 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4995 ¶ms, total_params, &data, total_data, max_data_bytes);
4996 END_PROFILE_NESTED(Trans2_setfsinfo);
4999 case TRANSACT2_QPATHINFO:
5000 case TRANSACT2_QFILEINFO:
5001 START_PROFILE_NESTED(Trans2_qpathinfo);
5002 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5003 ¶ms, total_params, &data, total_data, max_data_bytes);
5004 END_PROFILE_NESTED(Trans2_qpathinfo);
5006 case TRANSACT2_SETPATHINFO:
5007 case TRANSACT2_SETFILEINFO:
5008 START_PROFILE_NESTED(Trans2_setpathinfo);
5009 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5010 ¶ms, total_params, &data, total_data, max_data_bytes);
5011 END_PROFILE_NESTED(Trans2_setpathinfo);
5014 case TRANSACT2_FINDNOTIFYFIRST:
5015 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5016 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
5017 ¶ms, total_params, &data, total_data, max_data_bytes);
5018 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5021 case TRANSACT2_FINDNOTIFYNEXT:
5022 START_PROFILE_NESTED(Trans2_findnotifynext);
5023 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
5024 ¶ms, total_params, &data, total_data, max_data_bytes);
5025 END_PROFILE_NESTED(Trans2_findnotifynext);
5027 case TRANSACT2_MKDIR:
5028 START_PROFILE_NESTED(Trans2_mkdir);
5029 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
5030 ¶ms, total_params, &data, total_data, max_data_bytes);
5031 END_PROFILE_NESTED(Trans2_mkdir);
5034 case TRANSACT2_GET_DFS_REFERRAL:
5035 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5036 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
5037 ¶ms, total_params, &data, total_data, max_data_bytes);
5038 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5040 case TRANSACT2_IOCTL:
5041 START_PROFILE_NESTED(Trans2_ioctl);
5042 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
5043 ¶ms, total_params, &data, total_data, max_data_bytes);
5044 END_PROFILE_NESTED(Trans2_ioctl);
5047 /* Error in request */
5048 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
5051 END_PROFILE(SMBtrans2);
5052 srv_signing_trans_stop();
5053 return ERROR_DOS(ERRSRV,ERRerror);
5056 /* As we do not know how many data packets will need to be
5057 returned here the various call_trans2xxxx calls
5058 must send their own. Thus a call_trans2xxx routine only
5059 returns a value other than -1 when it wants to send
5063 srv_signing_trans_stop();
5067 END_PROFILE(SMBtrans2);
5068 return outsize; /* If a correct response was needed the
5069 call_trans2xxx calls have already sent
5070 it. If outsize != -1 then it is returning */
5074 srv_signing_trans_stop();
5077 END_PROFILE(SMBtrans2);
5078 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);