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 SSVAL(params,0,fsp->fnum);
862 SSVAL(params,2,fmode);
863 put_dos_date2(params,4, mtime);
864 SIVAL(params,8, (uint32)size);
865 SSVAL(params,12,rmode);
866 SSVAL(params,16,0); /* Padding. */
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);
878 SSVAL(params,24,0); /* Padding. */
880 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
881 SIVAL(params, 26, ea_size);
883 SIVAL(params, 26, 0);
886 /* Send the required number of replies */
887 send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0);
892 /*********************************************************
893 Routine to check if a given string matches exactly.
894 as a special case a mask of "." does NOT match. That
895 is required for correct wildcard semantics
896 Case can be significant or not.
897 **********************************************************/
899 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
901 if (mask[0] == '.' && mask[1] == 0)
904 return strcmp(str,mask)==0;
905 if (StrCaseCmp(str,mask) != 0) {
908 if (ms_has_wild(str)) {
914 /****************************************************************************
915 Return the filetype for UNIX extensions.
916 ****************************************************************************/
918 static uint32 unix_filetype(mode_t mode)
921 return UNIX_TYPE_FILE;
922 else if(S_ISDIR(mode))
923 return UNIX_TYPE_DIR;
925 else if(S_ISLNK(mode))
926 return UNIX_TYPE_SYMLINK;
929 else if(S_ISCHR(mode))
930 return UNIX_TYPE_CHARDEV;
933 else if(S_ISBLK(mode))
934 return UNIX_TYPE_BLKDEV;
937 else if(S_ISFIFO(mode))
938 return UNIX_TYPE_FIFO;
941 else if(S_ISSOCK(mode))
942 return UNIX_TYPE_SOCKET;
945 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
946 return UNIX_TYPE_UNKNOWN;
949 /****************************************************************************
950 Map wire perms onto standard UNIX permissions. Obey share restrictions.
951 ****************************************************************************/
953 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
957 if (perms == SMB_MODE_NO_CHANGE)
960 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
961 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
962 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
963 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
964 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
965 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
966 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
967 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
968 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
970 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
973 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
976 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
979 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
980 ret &= lp_dir_mask(SNUM(conn));
981 /* Add in force bits */
982 ret |= lp_force_dir_mode(SNUM(conn));
984 /* Apply mode mask */
985 ret &= lp_create_mask(SNUM(conn));
986 /* Add in force bits */
987 ret |= lp_force_create_mode(SNUM(conn));
993 /****************************************************************************
994 Get a level dependent lanman2 dir entry.
995 ****************************************************************************/
997 static BOOL get_lanman2_dir_entry(connection_struct *conn,
998 void *inbuf, void *outbuf,
999 char *path_mask,int dirtype,int info_level,
1000 int requires_resume_key,
1001 BOOL dont_descend,char **ppdata,
1002 char *base_data, int space_remaining,
1003 BOOL *out_of_space, BOOL *got_exact_match,
1004 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1008 SMB_STRUCT_STAT sbuf;
1012 char *p, *q, *pdata = *ppdata;
1016 SMB_OFF_T file_size = 0;
1017 SMB_BIG_UINT allocation_size = 0;
1019 time_t mdate=0, adate=0, cdate=0;
1021 char *last_entry_ptr;
1023 int nt_extmode; /* Used for NT connections instead of mode */
1024 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1025 BOOL check_mangled_names = lp_manglednames(SNUM(conn));
1028 *out_of_space = False;
1029 *got_exact_match = False;
1034 p = strrchr_m(path_mask,'/');
1037 pstrcpy(mask,"*.*");
1041 pstrcpy(mask, path_mask);
1046 /* Needed if we run out of space */
1047 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1048 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1051 * Due to bugs in NT client redirectors we are not using
1052 * resume keys any more - set them to zero.
1053 * Check out the related comments in findfirst/findnext.
1059 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1060 (long)conn->dirptr,curr_dirpos));
1065 pstrcpy(fname,dname);
1067 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
1068 got_match = mask_match(fname, mask, conn->case_sensitive);
1070 if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False, SNUM(conn))) {
1073 * It turns out that NT matches wildcards against
1074 * both long *and* short names. This may explain some
1075 * of the wildcard wierdness from old DOS clients
1076 * that some people have been seeing.... JRA.
1080 pstrcpy( newname, fname);
1081 mangle_map( newname, True, False, SNUM(conn));
1082 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
1083 got_match = mask_match(newname, mask, conn->case_sensitive);
1087 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1088 if (dont_descend && !isdots)
1091 pstrcpy(pathreal,conn->dirpath);
1093 pstrcat(pathreal,"/");
1094 pstrcat(pathreal,dname);
1096 if (INFO_LEVEL_IS_UNIX(info_level)) {
1097 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1098 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1099 pathreal,strerror(errno)));
1102 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1104 /* Needed to show the msdfs symlinks as
1107 if(lp_host_msdfs() &&
1108 lp_msdfs_root(SNUM(conn)) &&
1109 is_msdfs_link(conn, pathreal, NULL, NULL,
1112 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1113 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1117 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1118 pathreal,strerror(errno)));
1123 mode = dos_mode(conn,pathreal,&sbuf);
1125 if (!dir_check_ftype(conn,mode,dirtype)) {
1126 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1130 file_size = get_file_size(sbuf);
1131 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1132 mdate = sbuf.st_mtime;
1133 adate = sbuf.st_atime;
1134 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1136 if (lp_dos_filetime_resolution(SNUM(conn))) {
1143 /* This is necessary, as otherwise the
1144 * desktop.ini file in this folder is
1146 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
1150 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1156 mangle_map(fname,False,True,SNUM(conn));
1161 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1163 switch (info_level) {
1164 case SMB_FIND_INFO_STANDARD:
1165 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1166 if(requires_resume_key) {
1170 put_dos_date2(p,0,cdate);
1171 put_dos_date2(p,4,adate);
1172 put_dos_date2(p,8,mdate);
1173 SIVAL(p,12,(uint32)file_size);
1174 SIVAL(p,16,(uint32)allocation_size);
1178 p += align_string(outbuf, p, 0);
1179 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1180 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1182 SCVAL(nameptr, -1, len - 2);
1184 SCVAL(nameptr, -1, 0);
1188 SCVAL(nameptr, -1, len - 1);
1190 SCVAL(nameptr, -1, 0);
1196 case SMB_FIND_EA_SIZE:
1197 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1198 if(requires_resume_key) {
1202 put_dos_date2(p,0,cdate);
1203 put_dos_date2(p,4,adate);
1204 put_dos_date2(p,8,mdate);
1205 SIVAL(p,12,(uint32)file_size);
1206 SIVAL(p,16,(uint32)allocation_size);
1209 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1210 SIVAL(p,22,ea_size); /* Extended attributes */
1214 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1215 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1228 SCVAL(nameptr,0,len);
1230 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1233 case SMB_FIND_EA_LIST:
1235 struct ea_list *file_list = NULL;
1238 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1242 if(requires_resume_key) {
1246 put_dos_date2(p,0,cdate);
1247 put_dos_date2(p,4,adate);
1248 put_dos_date2(p,8,mdate);
1249 SIVAL(p,12,(uint32)file_size);
1250 SIVAL(p,16,(uint32)allocation_size);
1252 p += 22; /* p now points to the EA area. */
1254 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1255 name_list = ea_list_union(name_list, file_list, &ea_len);
1257 /* We need to determine if this entry will fit in the space available. */
1258 /* Max string size is 255 bytes. */
1259 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1260 /* Move the dirptr back to prev_dirpos */
1261 dptr_SeekDir(conn->dirptr, prev_dirpos);
1262 *out_of_space = True;
1263 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1264 return False; /* Not finished - just out of space */
1267 /* Push the ea_data followed by the name. */
1268 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1270 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1271 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1284 SCVAL(nameptr,0,len);
1286 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1290 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1291 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1292 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1294 SIVAL(p,0,reskey); p += 4;
1295 put_long_date(p,cdate); p += 8;
1296 put_long_date(p,adate); p += 8;
1297 put_long_date(p,mdate); p += 8;
1298 put_long_date(p,mdate); p += 8;
1299 SOFF_T(p,0,file_size); p += 8;
1300 SOFF_T(p,0,allocation_size); p += 8;
1301 SIVAL(p,0,nt_extmode); p += 4;
1302 q = p; p += 4; /* q is placeholder for name length. */
1304 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1305 SIVAL(p,0,ea_size); /* Extended attributes */
1308 /* Clear the short name buffer. This is
1309 * IMPORTANT as not doing so will trigger
1310 * a Win2k client bug. JRA.
1312 if (!was_8_3 && check_mangled_names) {
1313 pstring mangled_name;
1314 pstrcpy(mangled_name, fname);
1315 mangle_map(mangled_name,True,True,SNUM(conn));
1316 mangled_name[12] = 0;
1317 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1319 memset(p + 2 + len,'\0',24 - len);
1326 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1329 SIVAL(p,0,0); /* Ensure any padding is null. */
1330 len = PTR_DIFF(p, pdata);
1331 len = (len + 3) & ~3;
1336 case SMB_FIND_FILE_DIRECTORY_INFO:
1337 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1339 SIVAL(p,0,reskey); p += 4;
1340 put_long_date(p,cdate); p += 8;
1341 put_long_date(p,adate); p += 8;
1342 put_long_date(p,mdate); p += 8;
1343 put_long_date(p,mdate); p += 8;
1344 SOFF_T(p,0,file_size); p += 8;
1345 SOFF_T(p,0,allocation_size); p += 8;
1346 SIVAL(p,0,nt_extmode); p += 4;
1347 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1350 SIVAL(p,0,0); /* Ensure any padding is null. */
1351 len = PTR_DIFF(p, pdata);
1352 len = (len + 3) & ~3;
1357 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1358 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1360 SIVAL(p,0,reskey); p += 4;
1361 put_long_date(p,cdate); p += 8;
1362 put_long_date(p,adate); p += 8;
1363 put_long_date(p,mdate); p += 8;
1364 put_long_date(p,mdate); p += 8;
1365 SOFF_T(p,0,file_size); p += 8;
1366 SOFF_T(p,0,allocation_size); p += 8;
1367 SIVAL(p,0,nt_extmode); p += 4;
1368 q = p; p += 4; /* q is placeholder for name length. */
1370 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1371 SIVAL(p,0,ea_size); /* Extended attributes */
1374 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1378 SIVAL(p,0,0); /* Ensure any padding is null. */
1379 len = PTR_DIFF(p, pdata);
1380 len = (len + 3) & ~3;
1385 case SMB_FIND_FILE_NAMES_INFO:
1386 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1388 SIVAL(p,0,reskey); p += 4;
1390 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1391 acl on a dir (tridge) */
1392 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1395 SIVAL(p,0,0); /* Ensure any padding is null. */
1396 len = PTR_DIFF(p, pdata);
1397 len = (len + 3) & ~3;
1402 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1403 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1405 SIVAL(p,0,reskey); p += 4;
1406 put_long_date(p,cdate); p += 8;
1407 put_long_date(p,adate); p += 8;
1408 put_long_date(p,mdate); p += 8;
1409 put_long_date(p,mdate); p += 8;
1410 SOFF_T(p,0,file_size); p += 8;
1411 SOFF_T(p,0,allocation_size); p += 8;
1412 SIVAL(p,0,nt_extmode); p += 4;
1413 q = p; p += 4; /* q is placeholder for name length. */
1415 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1416 SIVAL(p,0,ea_size); /* Extended attributes */
1419 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1420 SIVAL(p,0,sbuf.st_dev); p += 4;
1421 SIVAL(p,0,sbuf.st_ino); p += 4;
1422 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1425 SIVAL(p,0,0); /* Ensure any padding is null. */
1426 len = PTR_DIFF(p, pdata);
1427 len = (len + 3) & ~3;
1432 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1433 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1434 was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1436 SIVAL(p,0,reskey); p += 4;
1437 put_long_date(p,cdate); p += 8;
1438 put_long_date(p,adate); p += 8;
1439 put_long_date(p,mdate); p += 8;
1440 put_long_date(p,mdate); p += 8;
1441 SOFF_T(p,0,file_size); p += 8;
1442 SOFF_T(p,0,allocation_size); p += 8;
1443 SIVAL(p,0,nt_extmode); p += 4;
1444 q = p; p += 4; /* q is placeholder for name length */
1446 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1447 SIVAL(p,0,ea_size); /* Extended attributes */
1450 /* Clear the short name buffer. This is
1451 * IMPORTANT as not doing so will trigger
1452 * a Win2k client bug. JRA.
1454 if (!was_8_3 && check_mangled_names) {
1455 pstring mangled_name;
1456 pstrcpy(mangled_name, fname);
1457 mangle_map(mangled_name,True,True,SNUM(conn));
1458 mangled_name[12] = 0;
1459 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1462 memset(p + 2 + len,'\0',24 - len);
1469 SSVAL(p,0,0); p += 2; /* Reserved ? */
1470 SIVAL(p,0,sbuf.st_dev); p += 4;
1471 SIVAL(p,0,sbuf.st_ino); p += 4;
1472 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1475 SIVAL(p,0,0); /* Ensure any padding is null. */
1476 len = PTR_DIFF(p, pdata);
1477 len = (len + 3) & ~3;
1482 /* CIFS UNIX Extension. */
1484 case SMB_FIND_FILE_UNIX:
1485 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1487 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1489 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1490 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1493 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1496 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1497 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1498 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1501 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1505 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1509 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1512 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1516 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1520 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1523 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1527 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1531 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1533 SIVAL(p,0,0); /* Ensure any padding is null. */
1535 len = PTR_DIFF(p, pdata);
1536 len = (len + 3) & ~3;
1537 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1539 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1548 if (PTR_DIFF(p,pdata) > space_remaining) {
1549 /* Move the dirptr back to prev_dirpos */
1550 dptr_SeekDir(conn->dirptr, prev_dirpos);
1551 *out_of_space = True;
1552 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1553 return False; /* Not finished - just out of space */
1556 /* Setup the last entry pointer, as an offset from base_data */
1557 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1558 /* Advance the data pointer to the next slot */
1564 /****************************************************************************
1565 Reply to a TRANS2_FINDFIRST.
1566 ****************************************************************************/
1568 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1569 char **pparams, int total_params, char **ppdata, int total_data,
1570 unsigned int max_data_bytes)
1572 /* We must be careful here that we don't return more than the
1573 allowed number of data bytes. If this means returning fewer than
1574 maxentries then so be it. We assume that the redirector has
1575 enough room for the fixed number of parameter bytes it has
1577 char *params = *pparams;
1578 char *pdata = *ppdata;
1579 int dirtype = SVAL(params,0);
1580 int maxentries = SVAL(params,2);
1581 uint16 findfirst_flags = SVAL(params,4);
1582 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1583 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1584 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1585 int info_level = SVAL(params,6);
1589 int last_entry_off=0;
1593 BOOL finished = False;
1594 BOOL dont_descend = False;
1595 BOOL out_of_space = False;
1596 int space_remaining;
1597 BOOL bad_path = False;
1598 SMB_STRUCT_STAT sbuf;
1599 TALLOC_CTX *ea_ctx = NULL;
1600 struct ea_list *ea_list = NULL;
1601 NTSTATUS ntstatus = NT_STATUS_OK;
1603 if (total_params < 12) {
1604 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1607 *directory = *mask = 0;
1609 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1610 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1611 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1612 info_level, max_data_bytes));
1615 /* W2K3 seems to treat zero as 1. */
1619 switch (info_level) {
1620 case SMB_FIND_INFO_STANDARD:
1621 case SMB_FIND_EA_SIZE:
1622 case SMB_FIND_EA_LIST:
1623 case SMB_FIND_FILE_DIRECTORY_INFO:
1624 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1625 case SMB_FIND_FILE_NAMES_INFO:
1626 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1627 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1628 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1630 case SMB_FIND_FILE_UNIX:
1631 if (!lp_unix_extensions())
1632 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1635 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1638 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1639 if (!NT_STATUS_IS_OK(ntstatus)) {
1640 return ERROR_NT(ntstatus);
1643 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1645 unix_convert(directory,conn,0,&bad_path,&sbuf);
1647 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1649 if(!check_name(directory,conn)) {
1650 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1653 p = strrchr_m(directory,'/');
1655 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1656 if((directory[0] == '.') && (directory[1] == '\0'))
1659 pstrcpy(mask,directory);
1660 pstrcpy(directory,"./");
1666 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1668 if (info_level == SMB_FIND_EA_LIST) {
1671 if (total_data < 4) {
1672 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1675 ea_size = IVAL(pdata,0);
1676 if (ea_size != total_data) {
1677 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1678 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1679 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1682 if (!lp_ea_support(SNUM(conn))) {
1683 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1686 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1687 return ERROR_NT(NT_STATUS_NO_MEMORY);
1690 /* Pull out the list of names. */
1691 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1693 talloc_destroy(ea_ctx);
1694 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1698 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1699 if( pdata == NULL ) {
1700 talloc_destroy(ea_ctx);
1701 return ERROR_NT(NT_STATUS_NO_MEMORY);
1706 /* Realloc the params space */
1707 params = SMB_REALLOC(*pparams, 10);
1708 if (params == NULL) {
1709 talloc_destroy(ea_ctx);
1710 return ERROR_NT(NT_STATUS_NO_MEMORY);
1714 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1716 talloc_destroy(ea_ctx);
1717 return(UNIXERROR(ERRDOS,ERRbadfile));
1720 /* Save the wildcard match and attribs we are using on this directory -
1721 needed as lanman2 assumes these are being saved between calls */
1723 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1724 dptr_close(&dptr_num);
1725 talloc_destroy(ea_ctx);
1726 return ERROR_NT(NT_STATUS_NO_MEMORY);
1729 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1731 /* We don't need to check for VOL here as this is returned by
1732 a different TRANS2 call. */
1734 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1735 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1736 dont_descend = True;
1739 space_remaining = max_data_bytes;
1740 out_of_space = False;
1742 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1743 BOOL got_exact_match = False;
1745 /* this is a heuristic to avoid seeking the dirptr except when
1746 absolutely necessary. It allows for a filename of about 40 chars */
1747 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1748 out_of_space = True;
1751 finished = !get_lanman2_dir_entry(conn,
1753 mask,dirtype,info_level,
1754 requires_resume_key,dont_descend,
1755 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1756 &last_entry_off, ea_list, ea_ctx);
1759 if (finished && out_of_space)
1762 if (!finished && !out_of_space)
1766 * As an optimisation if we know we aren't looking
1767 * for a wildcard name (ie. the name matches the wildcard exactly)
1768 * then we can finish on any (first) match.
1769 * This speeds up large directory searches. JRA.
1775 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1778 talloc_destroy(ea_ctx);
1780 /* Check if we can close the dirptr */
1781 if(close_after_first || (finished && close_if_end)) {
1782 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1783 dptr_close(&dptr_num);
1787 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1788 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1789 * the protocol level is less than NT1. Tested with smbclient. JRA.
1790 * This should fix the OS/2 client bug #2335.
1793 if(numentries == 0) {
1794 dptr_close(&dptr_num);
1795 if (Protocol < PROTOCOL_NT1) {
1796 return ERROR_DOS(ERRDOS,ERRnofiles);
1798 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1802 /* At this point pdata points to numentries directory entries. */
1804 /* Set up the return parameter block */
1805 SSVAL(params,0,dptr_num);
1806 SSVAL(params,2,numentries);
1807 SSVAL(params,4,finished);
1808 SSVAL(params,6,0); /* Never an EA error */
1809 SSVAL(params,8,last_entry_off);
1811 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1813 if ((! *directory) && dptr_path(dptr_num))
1814 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1816 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1817 smb_fn_name(CVAL(inbuf,smb_com)),
1818 mask, directory, dirtype, numentries ) );
1821 * Force a name mangle here to ensure that the
1822 * mask as an 8.3 name is top of the mangled cache.
1823 * The reasons for this are subtle. Don't remove
1824 * this code unless you know what you are doing
1825 * (see PR#13758). JRA.
1828 if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn)))
1829 mangle_map(mask, True, True, SNUM(conn));
1834 /****************************************************************************
1835 Reply to a TRANS2_FINDNEXT.
1836 ****************************************************************************/
1838 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1839 char **pparams, int total_params, char **ppdata, int total_data,
1840 unsigned int max_data_bytes)
1842 /* We must be careful here that we don't return more than the
1843 allowed number of data bytes. If this means returning fewer than
1844 maxentries then so be it. We assume that the redirector has
1845 enough room for the fixed number of parameter bytes it has
1847 char *params = *pparams;
1848 char *pdata = *ppdata;
1849 int dptr_num = SVAL(params,0);
1850 int maxentries = SVAL(params,2);
1851 uint16 info_level = SVAL(params,4);
1852 uint32 resume_key = IVAL(params,6);
1853 uint16 findnext_flags = SVAL(params,10);
1854 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1855 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1856 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1857 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1858 pstring resume_name;
1864 int i, last_entry_off=0;
1865 BOOL finished = False;
1866 BOOL dont_descend = False;
1867 BOOL out_of_space = False;
1868 int space_remaining;
1869 TALLOC_CTX *ea_ctx = NULL;
1870 struct ea_list *ea_list = NULL;
1871 NTSTATUS ntstatus = NT_STATUS_OK;
1873 if (total_params < 12) {
1874 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1877 *mask = *directory = *resume_name = 0;
1879 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1880 if (!NT_STATUS_IS_OK(ntstatus)) {
1881 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1882 complain (it thinks we're asking for the directory above the shared
1883 path or an invalid name). Catch this as the resume name is only compared, never used in
1884 a file access. JRA. */
1885 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1886 pstrcpy(resume_name, "..");
1887 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1888 pstrcpy(resume_name, ".");
1890 return ERROR_NT(ntstatus);
1894 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1895 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1896 resume_key = %d resume name = %s continue=%d level = %d\n",
1897 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1898 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1901 /* W2K3 seems to treat zero as 1. */
1905 switch (info_level) {
1906 case SMB_FIND_INFO_STANDARD:
1907 case SMB_FIND_EA_SIZE:
1908 case SMB_FIND_EA_LIST:
1909 case SMB_FIND_FILE_DIRECTORY_INFO:
1910 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1911 case SMB_FIND_FILE_NAMES_INFO:
1912 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1914 case SMB_FIND_FILE_UNIX:
1915 if (!lp_unix_extensions())
1916 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1919 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1922 if (info_level == SMB_FIND_EA_LIST) {
1925 if (total_data < 4) {
1926 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1929 ea_size = IVAL(pdata,0);
1930 if (ea_size != total_data) {
1931 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1932 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1933 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1936 if (!lp_ea_support(SNUM(conn))) {
1937 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1940 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1941 return ERROR_NT(NT_STATUS_NO_MEMORY);
1944 /* Pull out the list of names. */
1945 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1947 talloc_destroy(ea_ctx);
1948 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1952 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1954 talloc_destroy(ea_ctx);
1955 return ERROR_NT(NT_STATUS_NO_MEMORY);
1960 /* Realloc the params space */
1961 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1962 if( params == NULL ) {
1963 talloc_destroy(ea_ctx);
1964 return ERROR_NT(NT_STATUS_NO_MEMORY);
1969 /* Check that the dptr is valid */
1970 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
1971 talloc_destroy(ea_ctx);
1972 return ERROR_DOS(ERRDOS,ERRnofiles);
1975 string_set(&conn->dirpath,dptr_path(dptr_num));
1977 /* Get the wildcard mask from the dptr */
1978 if((p = dptr_wcard(dptr_num))== NULL) {
1979 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1980 talloc_destroy(ea_ctx);
1981 return ERROR_DOS(ERRDOS,ERRnofiles);
1985 pstrcpy(directory,conn->dirpath);
1987 /* Get the attr mask from the dptr */
1988 dirtype = dptr_attr(dptr_num);
1990 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
1991 dptr_num, mask, dirtype,
1993 dptr_TellDir(conn->dirptr)));
1995 /* We don't need to check for VOL here as this is returned by
1996 a different TRANS2 call. */
1998 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1999 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2000 dont_descend = True;
2003 space_remaining = max_data_bytes;
2004 out_of_space = False;
2007 * Seek to the correct position. We no longer use the resume key but
2008 * depend on the last file name instead.
2011 if(*resume_name && !continue_bit) {
2014 long current_pos = 0;
2016 * Remember, mangle_map is called by
2017 * get_lanman2_dir_entry(), so the resume name
2018 * could be mangled. Ensure we check the unmangled name.
2021 if (mangle_is_mangled(resume_name, SNUM(conn))) {
2022 mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn));
2026 * Fix for NT redirector problem triggered by resume key indexes
2027 * changing between directory scans. We now return a resume key of 0
2028 * and instead look for the filename to continue from (also given
2029 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2030 * findfirst/findnext (as is usual) then the directory pointer
2031 * should already be at the correct place.
2034 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2035 } /* end if resume_name && !continue_bit */
2037 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2038 BOOL got_exact_match = False;
2040 /* this is a heuristic to avoid seeking the dirptr except when
2041 absolutely necessary. It allows for a filename of about 40 chars */
2042 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2043 out_of_space = True;
2046 finished = !get_lanman2_dir_entry(conn,
2048 mask,dirtype,info_level,
2049 requires_resume_key,dont_descend,
2050 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2051 &last_entry_off, ea_list, ea_ctx);
2054 if (finished && out_of_space)
2057 if (!finished && !out_of_space)
2061 * As an optimisation if we know we aren't looking
2062 * for a wildcard name (ie. the name matches the wildcard exactly)
2063 * then we can finish on any (first) match.
2064 * This speeds up large directory searches. JRA.
2070 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2073 talloc_destroy(ea_ctx);
2075 /* Check if we can close the dirptr */
2076 if(close_after_request || (finished && close_if_end)) {
2077 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2078 dptr_close(&dptr_num); /* This frees up the saved mask */
2081 /* Set up the return parameter block */
2082 SSVAL(params,0,numentries);
2083 SSVAL(params,2,finished);
2084 SSVAL(params,4,0); /* Never an EA error */
2085 SSVAL(params,6,last_entry_off);
2087 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2089 if ((! *directory) && dptr_path(dptr_num))
2090 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2092 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2093 smb_fn_name(CVAL(inbuf,smb_com)),
2094 mask, directory, dirtype, numentries ) );
2099 /****************************************************************************
2100 Reply to a TRANS2_QFSINFO (query filesystem info).
2101 ****************************************************************************/
2103 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2104 char **pparams, int total_params, char **ppdata, int total_data,
2105 unsigned int max_data_bytes)
2107 char *pdata = *ppdata;
2108 char *params = *pparams;
2109 uint16 info_level = SVAL(params,0);
2112 char *vname = volume_label(SNUM(conn));
2113 int snum = SNUM(conn);
2114 char *fstype = lp_fstype(SNUM(conn));
2117 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2119 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2120 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2121 return ERROR_DOS(ERRSRV,ERRinvdevice);
2124 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2125 if ( pdata == NULL ) {
2126 return ERROR_NT(NT_STATUS_NO_MEMORY);
2130 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2132 switch (info_level) {
2133 case SMB_INFO_ALLOCATION:
2135 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2137 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2138 return(UNIXERROR(ERRHRD,ERRgeneral));
2141 block_size = lp_block_size(snum);
2142 if (bsize < block_size) {
2143 SMB_BIG_UINT factor = block_size/bsize;
2148 if (bsize > block_size) {
2149 SMB_BIG_UINT factor = bsize/block_size;
2154 bytes_per_sector = 512;
2155 sectors_per_unit = bsize/bytes_per_sector;
2157 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2158 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2159 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2161 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2162 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2163 SIVAL(pdata,l1_cUnit,dsize);
2164 SIVAL(pdata,l1_cUnitAvail,dfree);
2165 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2169 case SMB_INFO_VOLUME:
2170 /* Return volume name */
2172 * Add volume serial number - hash of a combination of
2173 * the called hostname and the service name.
2175 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2177 * Win2k3 and previous mess this up by sending a name length
2178 * one byte short. I believe only older clients (OS/2 Win9x) use
2179 * this call so try fixing this by adding a terminating null to
2180 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2182 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2183 SCVAL(pdata,l2_vol_cch,len);
2184 data_len = l2_vol_szVolLabel + len;
2185 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2186 (unsigned)st.st_ctime, len, vname));
2189 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2190 case SMB_FS_ATTRIBUTE_INFORMATION:
2193 #if defined(HAVE_SYS_QUOTAS)
2194 quota_flag = FILE_VOLUME_QUOTAS;
2197 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2198 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2199 quota_flag); /* FS ATTRIBUTES */
2201 SIVAL(pdata,4,255); /* Max filename component length */
2202 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2203 and will think we can't do long filenames */
2204 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2206 data_len = 12 + len;
2209 case SMB_QUERY_FS_LABEL_INFO:
2210 case SMB_FS_LABEL_INFORMATION:
2211 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2216 case SMB_QUERY_FS_VOLUME_INFO:
2217 case SMB_FS_VOLUME_INFORMATION:
2220 * Add volume serial number - hash of a combination of
2221 * the called hostname and the service name.
2223 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2224 (str_checksum(get_local_machine_name())<<16));
2226 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2227 SIVAL(pdata,12,len);
2229 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2230 (int)strlen(vname),vname, lp_servicename(snum)));
2233 case SMB_QUERY_FS_SIZE_INFO:
2234 case SMB_FS_SIZE_INFORMATION:
2236 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2238 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2239 return(UNIXERROR(ERRHRD,ERRgeneral));
2241 block_size = lp_block_size(snum);
2242 if (bsize < block_size) {
2243 SMB_BIG_UINT factor = block_size/bsize;
2248 if (bsize > block_size) {
2249 SMB_BIG_UINT factor = bsize/block_size;
2254 bytes_per_sector = 512;
2255 sectors_per_unit = bsize/bytes_per_sector;
2256 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2257 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2258 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2259 SBIG_UINT(pdata,0,dsize);
2260 SBIG_UINT(pdata,8,dfree);
2261 SIVAL(pdata,16,sectors_per_unit);
2262 SIVAL(pdata,20,bytes_per_sector);
2266 case SMB_FS_FULL_SIZE_INFORMATION:
2268 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2270 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2271 return(UNIXERROR(ERRHRD,ERRgeneral));
2273 block_size = lp_block_size(snum);
2274 if (bsize < block_size) {
2275 SMB_BIG_UINT factor = block_size/bsize;
2280 if (bsize > block_size) {
2281 SMB_BIG_UINT factor = bsize/block_size;
2286 bytes_per_sector = 512;
2287 sectors_per_unit = bsize/bytes_per_sector;
2288 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2289 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2290 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2291 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2292 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2293 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2294 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2295 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2299 case SMB_QUERY_FS_DEVICE_INFO:
2300 case SMB_FS_DEVICE_INFORMATION:
2302 SIVAL(pdata,0,0); /* dev type */
2303 SIVAL(pdata,4,0); /* characteristics */
2306 #ifdef HAVE_SYS_QUOTAS
2307 case SMB_FS_QUOTA_INFORMATION:
2309 * what we have to send --metze:
2311 * Unknown1: 24 NULL bytes
2312 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2313 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2314 * Quota Flags: 2 byte :
2315 * Unknown3: 6 NULL bytes
2319 * details for Quota Flags:
2321 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2322 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2323 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2324 * 0x0001 Enable Quotas: enable quota for this fs
2328 /* we need to fake up a fsp here,
2329 * because its not send in this call
2332 SMB_NTQUOTA_STRUCT quotas;
2335 ZERO_STRUCT(quotas);
2342 if (current_user.uid != 0) {
2343 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2344 lp_servicename(SNUM(conn)),conn->user));
2345 return ERROR_DOS(ERRDOS,ERRnoaccess);
2348 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2349 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2350 return ERROR_DOS(ERRSRV,ERRerror);
2355 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2357 /* Unknown1 24 NULL bytes*/
2358 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2359 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2360 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2362 /* Default Soft Quota 8 bytes */
2363 SBIG_UINT(pdata,24,quotas.softlim);
2365 /* Default Hard Quota 8 bytes */
2366 SBIG_UINT(pdata,32,quotas.hardlim);
2368 /* Quota flag 2 bytes */
2369 SSVAL(pdata,40,quotas.qflags);
2371 /* Unknown3 6 NULL bytes */
2377 #endif /* HAVE_SYS_QUOTAS */
2378 case SMB_FS_OBJECTID_INFORMATION:
2383 * Query the version and capabilities of the CIFS UNIX extensions
2387 case SMB_QUERY_CIFS_UNIX_INFO:
2388 if (!lp_unix_extensions())
2389 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2391 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2392 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2393 SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
2396 case SMB_MAC_QUERY_FS_INFO:
2398 * Thursby MAC extension... ONLY on NTFS filesystems
2399 * once we do streams then we don't need this
2401 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2403 SIVAL(pdata,84,0x100); /* Don't support mac... */
2408 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2412 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2414 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2419 /****************************************************************************
2420 Reply to a TRANS2_SETFSINFO (set filesystem info).
2421 ****************************************************************************/
2423 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2424 char **pparams, int total_params, char **ppdata, int total_data,
2425 unsigned int max_data_bytes)
2427 char *pdata = *ppdata;
2428 char *params = *pparams;
2429 files_struct *fsp = NULL;
2432 SMB_NTQUOTA_STRUCT quotas;
2434 ZERO_STRUCT(quotas);
2436 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2439 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2440 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2441 lp_servicename(SNUM(conn)),conn->user));
2442 return ERROR_DOS(ERRSRV,ERRaccess);
2446 if (total_params < 4) {
2447 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2449 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2452 info_level = SVAL(params,2);
2454 switch(info_level) {
2455 case SMB_SET_CIFS_UNIX_INFO:
2457 uint16 client_unix_major;
2458 uint16 client_unix_minor;
2459 uint32 client_unix_cap_low;
2460 uint32 client_unix_cap_high;
2462 if (!lp_unix_extensions()) {
2463 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2466 /* There should be 12 bytes of capabilities set. */
2467 if (total_data < 8) {
2468 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2470 client_unix_major = SVAL(pdata,0);
2471 client_unix_minor = SVAL(pdata,2);
2472 client_unix_cap_low = IVAL(pdata,4);
2473 client_unix_cap_high = IVAL(pdata,8);
2474 /* Just print these values for now. */
2475 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u\
2476 cap_low = 0x%x, cap_high = 0x%x\n",
2477 (unsigned int)client_unix_major,
2478 (unsigned int)client_unix_minor,
2479 (unsigned int)client_unix_cap_low,
2480 (unsigned int)client_unix_cap_high ));
2484 case SMB_FS_QUOTA_INFORMATION:
2485 /* note: normaly there're 48 bytes,
2486 * but we didn't use the last 6 bytes for now
2489 fsp = file_fsp(params,0);
2490 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2491 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2492 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2495 if (total_data < 42) {
2496 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2498 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2501 /* unknown_1 24 NULL bytes in pdata*/
2503 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2504 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2505 #ifdef LARGE_SMB_OFF_T
2506 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2507 #else /* LARGE_SMB_OFF_T */
2508 if ((IVAL(pdata,28) != 0)&&
2509 ((quotas.softlim != 0xFFFFFFFF)||
2510 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2511 /* more than 32 bits? */
2512 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2514 #endif /* LARGE_SMB_OFF_T */
2516 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2517 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2518 #ifdef LARGE_SMB_OFF_T
2519 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2520 #else /* LARGE_SMB_OFF_T */
2521 if ((IVAL(pdata,36) != 0)&&
2522 ((quotas.hardlim != 0xFFFFFFFF)||
2523 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2524 /* more than 32 bits? */
2525 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2527 #endif /* LARGE_SMB_OFF_T */
2529 /* quota_flags 2 bytes **/
2530 quotas.qflags = SVAL(pdata,40);
2532 /* unknown_2 6 NULL bytes follow*/
2534 /* now set the quotas */
2535 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2536 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2537 return ERROR_DOS(ERRSRV,ERRerror);
2542 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2544 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2549 * sending this reply works fine,
2550 * but I'm not sure it's the same
2551 * like windows do...
2554 outsize = set_message(outbuf,10,0,True);
2559 /****************************************************************************
2560 Utility function to set bad path error.
2561 ****************************************************************************/
2563 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2565 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2566 err, (int)bad_path ));
2570 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2572 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2575 return UNIXERROR(def_class,def_code);
2578 #if defined(HAVE_POSIX_ACLS)
2579 /****************************************************************************
2580 Utility function to count the number of entries in a POSIX acl.
2581 ****************************************************************************/
2583 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2585 unsigned int ace_count = 0;
2586 int entry_id = SMB_ACL_FIRST_ENTRY;
2587 SMB_ACL_ENTRY_T entry;
2589 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2591 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2592 entry_id = SMB_ACL_NEXT_ENTRY;
2599 /****************************************************************************
2600 Utility function to marshall a POSIX acl into wire format.
2601 ****************************************************************************/
2603 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2605 int entry_id = SMB_ACL_FIRST_ENTRY;
2606 SMB_ACL_ENTRY_T entry;
2608 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2609 SMB_ACL_TAG_T tagtype;
2610 SMB_ACL_PERMSET_T permset;
2611 unsigned char perms = 0;
2612 unsigned int own_grp;
2615 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2616 entry_id = SMB_ACL_NEXT_ENTRY;
2619 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2620 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2624 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2625 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2629 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2630 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2631 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2633 SCVAL(pdata,1,perms);
2636 case SMB_ACL_USER_OBJ:
2637 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2638 own_grp = (unsigned int)pst->st_uid;
2639 SIVAL(pdata,2,own_grp);
2644 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2646 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2648 own_grp = (unsigned int)*puid;
2649 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2650 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2651 SIVAL(pdata,2,own_grp);
2655 case SMB_ACL_GROUP_OBJ:
2656 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2657 own_grp = (unsigned int)pst->st_gid;
2658 SIVAL(pdata,2,own_grp);
2663 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2665 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2667 own_grp = (unsigned int)*pgid;
2668 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2669 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2670 SIVAL(pdata,2,own_grp);
2675 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2676 SIVAL(pdata,2,0xFFFFFFFF);
2677 SIVAL(pdata,6,0xFFFFFFFF);
2680 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2681 SIVAL(pdata,2,0xFFFFFFFF);
2682 SIVAL(pdata,6,0xFFFFFFFF);
2685 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2688 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2695 /****************************************************************************
2696 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2697 file name or file id).
2698 ****************************************************************************/
2700 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2701 unsigned int tran_call,
2702 char **pparams, int total_params, char **ppdata, int total_data,
2703 unsigned int max_data_bytes)
2705 char *params = *pparams;
2706 char *pdata = *ppdata;
2709 SMB_OFF_T file_size=0;
2710 SMB_BIG_UINT allocation_size=0;
2711 unsigned int data_size = 0;
2712 unsigned int param_size = 2;
2713 SMB_STRUCT_STAT sbuf;
2714 pstring fname, dos_fname;
2719 BOOL bad_path = False;
2720 BOOL delete_pending = False;
2723 files_struct *fsp = NULL;
2724 TALLOC_CTX *ea_ctx = NULL;
2725 struct ea_list *ea_list = NULL;
2726 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2729 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2733 if (tran_call == TRANSACT2_QFILEINFO) {
2734 if (total_params < 4) {
2735 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2738 fsp = file_fsp(params,0);
2739 info_level = SVAL(params,2);
2741 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2743 if(fsp && (fsp->fake_file_handle)) {
2745 * This is actually for the QUOTA_FAKE_FILE --metze
2748 pstrcpy(fname, fsp->fsp_name);
2749 /* We know this name is ok, it's already passed the checks. */
2751 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2753 * This is actually a QFILEINFO on a directory
2754 * handle (returned from an NT SMB). NT5.0 seems
2755 * to do this call. JRA.
2757 /* We know this name is ok, it's already passed the checks. */
2758 pstrcpy(fname, fsp->fsp_name);
2760 if (INFO_LEVEL_IS_UNIX(info_level)) {
2761 /* Always do lstat for UNIX calls. */
2762 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2763 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2764 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2766 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2767 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2768 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2771 delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2774 * Original code - this is an open file.
2776 CHECK_FSP(fsp,conn);
2778 pstrcpy(fname, fsp->fsp_name);
2779 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2780 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2781 return(UNIXERROR(ERRDOS,ERRbadfid));
2783 pos = fsp->position_information;
2784 delete_pending = fsp->delete_on_close;
2785 desired_access = fsp->desired_access;
2788 NTSTATUS status = NT_STATUS_OK;
2791 if (total_params < 6) {
2792 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2795 info_level = SVAL(params,0);
2797 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2799 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2800 if (!NT_STATUS_IS_OK(status)) {
2801 return ERROR_NT(status);
2804 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2806 unix_convert(fname,conn,0,&bad_path,&sbuf);
2808 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2810 if (!check_name(fname,conn)) {
2811 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2812 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2815 if (INFO_LEVEL_IS_UNIX(info_level)) {
2816 /* Always do lstat for UNIX calls. */
2817 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2818 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2819 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2821 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2822 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2823 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2827 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2828 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2830 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2831 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2833 p = strrchr_m(fname,'/');
2839 mode = dos_mode(conn,fname,&sbuf);
2841 mode = FILE_ATTRIBUTE_NORMAL;
2843 fullpathname = fname;
2844 file_size = get_file_size(sbuf);
2846 /* This is necessary, as otherwise the desktop.ini file in
2847 * this folder is ignored */
2848 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2852 /* Pull any EA list from the data portion. */
2853 if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2856 if (total_data < 4) {
2857 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2859 ea_size = IVAL(pdata,0);
2861 if (total_data > 0 && ea_size != total_data) {
2862 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2863 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2864 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2867 if (!lp_ea_support(SNUM(conn))) {
2868 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2871 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2872 return ERROR_NT(NT_STATUS_NO_MEMORY);
2875 /* Pull out the list of names. */
2876 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2878 talloc_destroy(ea_ctx);
2879 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2883 params = SMB_REALLOC(*pparams,2);
2884 if (params == NULL) {
2885 talloc_destroy(ea_ctx);
2886 return ERROR_NT(NT_STATUS_NO_MEMORY);
2890 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2891 pdata = SMB_REALLOC(*ppdata, data_size);
2892 if ( pdata == NULL ) {
2893 talloc_destroy(ea_ctx);
2894 return ERROR_NT(NT_STATUS_NO_MEMORY);
2898 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2900 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2903 if (fsp->pending_modtime) {
2904 /* the pending modtime overrides the current modtime */
2905 sbuf.st_mtime = fsp->pending_modtime;
2908 /* Do we have this path open ? */
2909 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2910 if (fsp1 && fsp1->pending_modtime) {
2911 /* the pending modtime overrides the current modtime */
2912 sbuf.st_mtime = fsp1->pending_modtime;
2914 if (fsp1 && fsp1->initial_allocation_size) {
2915 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
2919 if (lp_dos_filetime_resolution(SNUM(conn))) {
2921 sbuf.st_atime &= ~1;
2922 sbuf.st_ctime &= ~1;
2923 sbuf.st_mtime &= ~1;
2926 /* NT expects the name to be in an exact form of the *full*
2927 filename. See the trans2 torture test */
2928 if (strequal(base_name,".")) {
2929 pstrcpy(dos_fname, "\\");
2931 pstr_sprintf(dos_fname, "\\%s", fname);
2932 string_replace(dos_fname, '/', '\\');
2935 switch (info_level) {
2936 case SMB_INFO_STANDARD:
2937 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2939 put_dos_date2(pdata,l1_fdateCreation,c_time);
2940 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2941 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2942 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2943 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2944 SSVAL(pdata,l1_attrFile,mode);
2947 case SMB_INFO_QUERY_EA_SIZE:
2949 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2950 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2952 put_dos_date2(pdata,0,c_time);
2953 put_dos_date2(pdata,4,sbuf.st_atime);
2954 put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */
2955 SIVAL(pdata,12,(uint32)file_size);
2956 SIVAL(pdata,16,(uint32)allocation_size);
2957 SSVAL(pdata,20,mode);
2958 SIVAL(pdata,22,ea_size);
2962 case SMB_INFO_IS_NAME_VALID:
2963 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2964 if (tran_call == TRANSACT2_QFILEINFO) {
2965 /* os/2 needs this ? really ?*/
2966 return ERROR_DOS(ERRDOS,ERRbadfunc);
2972 case SMB_INFO_QUERY_EAS_FROM_LIST:
2974 size_t total_ea_len = 0;
2975 struct ea_list *ea_file_list = NULL;
2977 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2979 ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2980 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
2982 if (!ea_list || (total_ea_len > data_size)) {
2983 talloc_destroy(ea_ctx);
2985 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
2989 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
2990 talloc_destroy(ea_ctx);
2994 case SMB_INFO_QUERY_ALL_EAS:
2996 /* We have data_size bytes to put EA's into. */
2997 size_t total_ea_len = 0;
2999 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3001 ea_ctx = talloc_init("ea_ctx");
3003 return ERROR_NT(NT_STATUS_NO_MEMORY);
3006 ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3007 if (!ea_list || (total_ea_len > data_size)) {
3008 talloc_destroy(ea_ctx);
3010 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3014 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3015 talloc_destroy(ea_ctx);
3019 case SMB_FILE_BASIC_INFORMATION:
3020 case SMB_QUERY_FILE_BASIC_INFO:
3022 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3023 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3024 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3026 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3030 put_long_date(pdata,c_time);
3031 put_long_date(pdata+8,sbuf.st_atime);
3032 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3033 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3034 SIVAL(pdata,32,mode);
3036 DEBUG(5,("SMB_QFBI - "));
3038 time_t create_time = c_time;
3039 DEBUG(5,("create: %s ", ctime(&create_time)));
3041 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3042 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3043 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3044 DEBUG(5,("mode: %x\n", mode));
3047 case SMB_FILE_STANDARD_INFORMATION:
3048 case SMB_QUERY_FILE_STANDARD_INFO:
3050 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3052 SOFF_T(pdata,0,allocation_size);
3053 SOFF_T(pdata,8,file_size);
3054 if (delete_pending & sbuf.st_nlink)
3055 SIVAL(pdata,16,sbuf.st_nlink - 1);
3057 SIVAL(pdata,16,sbuf.st_nlink);
3059 SCVAL(pdata,21,(mode&aDIR)?1:0);
3060 SSVAL(pdata,22,0); /* Padding. */
3063 case SMB_FILE_EA_INFORMATION:
3064 case SMB_QUERY_FILE_EA_INFO:
3066 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3067 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3069 SIVAL(pdata,0,ea_size);
3073 /* Get the 8.3 name - used if NT SMB was negotiated. */
3074 case SMB_QUERY_FILE_ALT_NAME_INFO:
3075 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3079 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3080 pstrcpy(short_name,base_name);
3081 /* Mangle if not already 8.3 */
3082 if(!mangle_is_8_3(short_name, True, SNUM(conn))) {
3083 mangle_map(short_name,True,True,SNUM(conn));
3085 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3086 data_size = 4 + len;
3091 case SMB_QUERY_FILE_NAME_INFO:
3093 this must be *exactly* right for ACLs on mapped drives to work
3095 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3096 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3097 data_size = 4 + len;
3101 case SMB_FILE_ALLOCATION_INFORMATION:
3102 case SMB_QUERY_FILE_ALLOCATION_INFO:
3103 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3105 SOFF_T(pdata,0,allocation_size);
3108 case SMB_FILE_END_OF_FILE_INFORMATION:
3109 case SMB_QUERY_FILE_END_OF_FILEINFO:
3110 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3112 SOFF_T(pdata,0,file_size);
3115 case SMB_QUERY_FILE_ALL_INFO:
3116 case SMB_FILE_ALL_INFORMATION:
3118 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3119 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3120 put_long_date(pdata,c_time);
3121 put_long_date(pdata+8,sbuf.st_atime);
3122 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3123 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3124 SIVAL(pdata,32,mode);
3125 SIVAL(pdata,36,0); /* padding. */
3127 SOFF_T(pdata,0,allocation_size);
3128 SOFF_T(pdata,8,file_size);
3129 if (delete_pending && sbuf.st_nlink)
3130 SIVAL(pdata,16,sbuf.st_nlink - 1);
3132 SIVAL(pdata,16,sbuf.st_nlink);
3133 SCVAL(pdata,20,delete_pending);
3134 SCVAL(pdata,21,(mode&aDIR)?1:0);
3137 SIVAL(pdata,0,ea_size);
3138 pdata += 4; /* EA info */
3139 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3142 data_size = PTR_DIFF(pdata,(*ppdata));
3145 case SMB_FILE_INTERNAL_INFORMATION:
3146 /* This should be an index number - looks like
3149 I think this causes us to fail the IFSKIT
3150 BasicFileInformationTest. -tpot */
3152 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3153 SIVAL(pdata,0,sbuf.st_dev);
3154 SIVAL(pdata,4,sbuf.st_ino);
3158 case SMB_FILE_ACCESS_INFORMATION:
3159 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3160 SIVAL(pdata,0,desired_access);
3164 case SMB_FILE_NAME_INFORMATION:
3165 /* Pathname with leading '\'. */
3168 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
3169 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3170 SIVAL(pdata,0,byte_len);
3171 data_size = 4 + byte_len;
3175 case SMB_FILE_DISPOSITION_INFORMATION:
3176 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3178 SCVAL(pdata,0,delete_pending);
3181 case SMB_FILE_POSITION_INFORMATION:
3182 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3184 SOFF_T(pdata,0,pos);
3187 case SMB_FILE_MODE_INFORMATION:
3188 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3189 SIVAL(pdata,0,mode);
3193 case SMB_FILE_ALIGNMENT_INFORMATION:
3194 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3195 SIVAL(pdata,0,0); /* No alignment needed. */
3201 * NT4 server just returns "invalid query" to this - if we try to answer
3202 * it then NTws gets a BSOD! (tridge).
3203 * W2K seems to want this. JRA.
3205 case SMB_QUERY_FILE_STREAM_INFO:
3207 case SMB_FILE_STREAM_INFORMATION:
3208 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3212 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
3213 SIVAL(pdata,0,0); /* ??? */
3214 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3215 SOFF_T(pdata,8,file_size);
3216 SIVAL(pdata,16,allocation_size);
3217 SIVAL(pdata,20,0); /* ??? */
3218 data_size = 24 + byte_len;
3222 case SMB_QUERY_COMPRESSION_INFO:
3223 case SMB_FILE_COMPRESSION_INFORMATION:
3224 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3225 SOFF_T(pdata,0,file_size);
3226 SIVAL(pdata,8,0); /* ??? */
3227 SIVAL(pdata,12,0); /* ??? */
3231 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3232 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3233 put_long_date(pdata,c_time);
3234 put_long_date(pdata+8,sbuf.st_atime);
3235 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3236 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3237 SIVAL(pdata,32,allocation_size);
3238 SOFF_T(pdata,40,file_size);
3239 SIVAL(pdata,48,mode);
3240 SIVAL(pdata,52,0); /* ??? */
3244 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3245 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3246 SIVAL(pdata,0,mode);
3252 * CIFS UNIX Extensions.
3255 case SMB_QUERY_FILE_UNIX_BASIC:
3257 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3258 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3260 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3263 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3266 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3267 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3268 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3271 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3275 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3279 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3282 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3286 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3290 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3293 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3297 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3300 data_size = PTR_DIFF(pdata,(*ppdata));
3304 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3306 for (i=0; i<100; i++)
3307 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3313 case SMB_QUERY_FILE_UNIX_LINK:
3317 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3319 if(!S_ISLNK(sbuf.st_mode))
3320 return(UNIXERROR(ERRSRV,ERRbadlink));
3322 return(UNIXERROR(ERRDOS,ERRbadlink));
3324 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3326 return(UNIXERROR(ERRDOS,ERRnoaccess));
3328 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3330 data_size = PTR_DIFF(pdata,(*ppdata));
3335 #if defined(HAVE_POSIX_ACLS)
3336 case SMB_QUERY_POSIX_ACL:
3338 SMB_ACL_T file_acl = NULL;
3339 SMB_ACL_T def_acl = NULL;
3340 uint16 num_file_acls = 0;
3341 uint16 num_def_acls = 0;
3343 if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
3344 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
3346 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3349 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3350 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3352 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3355 if (S_ISDIR(sbuf.st_mode)) {
3356 if (fsp && fsp->is_directory) {
3357 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3359 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3361 def_acl = free_empty_sys_acl(conn, def_acl);
3364 num_file_acls = count_acl_entries(conn, file_acl);
3365 num_def_acls = count_acl_entries(conn, def_acl);
3367 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3368 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3370 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3371 SMB_POSIX_ACL_HEADER_SIZE) ));
3373 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3376 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3378 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3381 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3382 SSVAL(pdata,2,num_file_acls);
3383 SSVAL(pdata,4,num_def_acls);
3384 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3386 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3389 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3391 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3393 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3395 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3398 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3400 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3404 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3407 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3409 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3415 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3418 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3423 /****************************************************************************
3424 Deal with the internal needs of setting the delete on close flag. Note that
3425 as the tdb locking is recursive, it is safe to call this from within
3426 open_file_shared. JRA.
3427 ****************************************************************************/
3429 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
3431 if (delete_on_close) {
3433 * Only allow delete on close for writable files.
3436 if (!lp_delete_readonly(SNUM(fsp->conn))) {
3437 if (dosmode & aRONLY) {
3438 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
3440 return NT_STATUS_CANNOT_DELETE;
3445 * Only allow delete on close for writable shares.
3448 if (!CAN_WRITE(fsp->conn)) {
3449 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
3451 return NT_STATUS_ACCESS_DENIED;
3455 * Only allow delete on close for files/directories opened with delete intent.
3458 if (!(fsp->desired_access & DELETE_ACCESS)) {
3459 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
3461 return NT_STATUS_ACCESS_DENIED;
3465 if(fsp->is_directory) {
3466 fsp->directory_delete_on_close = delete_on_close;
3467 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3468 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3470 fsp->delete_on_close = delete_on_close;
3471 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3472 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3475 return NT_STATUS_OK;
3478 /****************************************************************************
3479 Sets the delete on close flag over all share modes on this file.
3480 Modify the share mode entry for all files open
3481 on this device and inode to tell other smbds we have
3482 changed the delete on close flag. This will be noticed
3483 in the close code, the last closer will delete the file
3485 ****************************************************************************/
3487 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3489 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3490 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3492 if (fsp->is_directory || fsp->is_stat)
3493 return NT_STATUS_OK;
3495 if (lock_share_entry_fsp(fsp) == False)
3496 return NT_STATUS_ACCESS_DENIED;
3498 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3499 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3501 unlock_share_entry_fsp(fsp);
3502 return NT_STATUS_ACCESS_DENIED;
3505 unlock_share_entry_fsp(fsp);
3506 return NT_STATUS_OK;
3509 /****************************************************************************
3510 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3512 ****************************************************************************/
3514 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3516 BOOL bad_path_oldname = False;
3517 BOOL bad_path_newname = False;
3518 SMB_STRUCT_STAT sbuf1, sbuf2;
3519 pstring last_component_oldname;
3520 pstring last_component_newname;
3521 NTSTATUS status = NT_STATUS_OK;
3527 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3528 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3531 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3532 if (bad_path_oldname) {
3533 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3536 /* Quick check for "." and ".." */
3537 if (last_component_oldname[0] == '.') {
3538 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3539 return NT_STATUS_OBJECT_NAME_INVALID;
3543 /* source must already exist. */
3544 if (!VALID_STAT(sbuf1)) {
3545 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3548 if (!check_name(oldname,conn)) {
3549 return NT_STATUS_ACCESS_DENIED;
3552 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3553 if (bad_path_newname) {
3554 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3557 /* Quick check for "." and ".." */
3558 if (last_component_newname[0] == '.') {
3559 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3560 return NT_STATUS_OBJECT_NAME_INVALID;
3564 /* Disallow if newname already exists. */
3565 if (VALID_STAT(sbuf2)) {
3566 return NT_STATUS_OBJECT_NAME_COLLISION;
3569 if (!check_name(newname,conn)) {
3570 return NT_STATUS_ACCESS_DENIED;
3573 /* No links from a directory. */
3574 if (S_ISDIR(sbuf1.st_mode)) {
3575 return NT_STATUS_FILE_IS_A_DIRECTORY;
3578 /* Ensure this is within the share. */
3579 if (!reduce_name(conn, oldname) != 0)
3580 return NT_STATUS_ACCESS_DENIED;
3582 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3584 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3585 status = map_nt_error_from_unix(errno);
3586 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3587 nt_errstr(status), newname, oldname));
3593 /****************************************************************************
3594 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3595 ****************************************************************************/
3597 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3598 unsigned int tran_call,
3599 char **pparams, int total_params, char **ppdata, int total_data,
3600 unsigned int max_data_bytes)
3602 char *params = *pparams;
3603 char *pdata = *ppdata;
3608 SMB_STRUCT_STAT sbuf;
3611 BOOL bad_path = False;
3612 files_struct *fsp = NULL;
3613 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3614 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3615 mode_t unixmode = 0;
3616 NTSTATUS status = NT_STATUS_OK;
3619 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3624 if (tran_call == TRANSACT2_SETFILEINFO) {
3625 if (total_params < 4) {
3626 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3629 fsp = file_fsp(params,0);
3630 info_level = SVAL(params,2);
3632 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3634 * This is actually a SETFILEINFO on a directory
3635 * handle (returned from an NT SMB). NT5.0 seems
3636 * to do this call. JRA.
3638 pstrcpy(fname, fsp->fsp_name);
3639 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3640 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3641 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3643 } else if (fsp && fsp->print_file) {
3645 * Doing a DELETE_ON_CLOSE should cancel a print job.
3647 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3648 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3650 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3653 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3656 return (UNIXERROR(ERRDOS,ERRbadpath));
3659 * Original code - this is an open file.
3661 CHECK_FSP(fsp,conn);
3663 pstrcpy(fname, fsp->fsp_name);
3666 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3667 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3668 return(UNIXERROR(ERRDOS,ERRbadfid));
3673 if (total_params < 6) {
3674 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3677 info_level = SVAL(params,0);
3678 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3679 if (!NT_STATUS_IS_OK(status)) {
3680 return ERROR_NT(status);
3682 unix_convert(fname,conn,0,&bad_path,&sbuf);
3684 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3688 * For CIFS UNIX extensions the target name may not exist.
3691 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3692 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3693 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3696 if(!check_name(fname, conn)) {
3697 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3702 if (!CAN_WRITE(conn))
3703 return ERROR_DOS(ERRSRV,ERRaccess);
3705 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3706 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3708 if (VALID_STAT(sbuf))
3709 unixmode = sbuf.st_mode;
3711 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3712 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3714 /* Realloc the parameter size */
3715 params = SMB_REALLOC(*pparams,2);
3716 if(params == NULL) {
3717 return ERROR_NT(NT_STATUS_NO_MEMORY);
3723 if (fsp && fsp->pending_modtime) {
3724 /* the pending modtime overrides the current modtime */
3725 sbuf.st_mtime = fsp->pending_modtime;
3728 size = get_file_size(sbuf);
3729 tvs.modtime = sbuf.st_mtime;
3730 tvs.actime = sbuf.st_atime;
3731 dosmode = dos_mode(conn,fname,&sbuf);
3732 unixmode = sbuf.st_mode;
3734 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3735 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3737 switch (info_level) {
3738 case SMB_INFO_STANDARD:
3740 if (total_data < 12) {
3741 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3745 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3747 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3751 case SMB_INFO_SET_EA:
3753 struct ea_list *ea_list = NULL;
3754 TALLOC_CTX *ctx = NULL;
3756 if (total_data < 10) {
3757 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3760 if (IVAL(pdata,0) > total_data) {
3761 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3762 IVAL(pdata,0), (unsigned int)total_data));
3763 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3766 ctx = talloc_init("SMB_INFO_SET_EA");
3768 return ERROR_NT(NT_STATUS_NO_MEMORY);
3770 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3772 talloc_destroy(ctx);
3773 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3775 status = set_ea(conn, fsp, fname, ea_list);
3776 talloc_destroy(ctx);
3778 if (!NT_STATUS_IS_OK(status)) {
3779 return ERROR_NT(status);
3782 /* We're done. We only get EA info in this call. */
3784 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3789 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3790 /* XXXX um, i don't think this is right.
3791 it's also not in the cifs6.txt spec.
3793 case SMB_INFO_QUERY_EAS_FROM_LIST:
3794 if (total_data < 28)
3795 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3797 tvs.actime = make_unix_date2(pdata+8);
3798 tvs.modtime = make_unix_date2(pdata+12);
3799 size = IVAL(pdata,16);
3800 dosmode = IVAL(pdata,24);
3803 /* XXXX nor this. not in cifs6.txt, either. */
3804 case SMB_INFO_QUERY_ALL_EAS:
3805 if (total_data < 28)
3806 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3808 tvs.actime = make_unix_date2(pdata+8);
3809 tvs.modtime = make_unix_date2(pdata+12);
3810 size = IVAL(pdata,16);
3811 dosmode = IVAL(pdata,24);
3815 case SMB_SET_FILE_BASIC_INFO:
3816 case SMB_FILE_BASIC_INFORMATION:
3818 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3820 time_t changed_time;
3822 if (total_data < 36) {
3823 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3826 /* Ignore create time at offset pdata. */
3829 tvs.actime = interpret_long_date(pdata+8);
3831 write_time = interpret_long_date(pdata+16);
3832 changed_time = interpret_long_date(pdata+24);
3834 tvs.modtime = MIN(write_time, changed_time);
3836 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3837 tvs.modtime = write_time;
3839 /* Prefer a defined time to an undefined one. */
3840 if (null_mtime(tvs.modtime)) {
3841 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3845 dosmode = IVAL(pdata,32);
3849 case SMB_FILE_ALLOCATION_INFORMATION:
3850 case SMB_SET_FILE_ALLOCATION_INFO:
3853 SMB_BIG_UINT allocation_size;
3855 if (total_data < 8) {
3856 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3859 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3860 #ifdef LARGE_SMB_OFF_T
3861 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3862 #else /* LARGE_SMB_OFF_T */
3863 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3864 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3865 #endif /* LARGE_SMB_OFF_T */
3866 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3867 fname, (double)allocation_size ));
3869 if (allocation_size) {
3870 allocation_size = smb_roundup(conn, allocation_size);
3873 if(allocation_size != get_file_size(sbuf)) {
3874 SMB_STRUCT_STAT new_sbuf;
3876 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3877 fname, (double)allocation_size ));
3880 files_struct *new_fsp = NULL;
3881 int access_mode = 0;
3884 if(global_oplock_break) {
3885 /* Queue this file modify as we are the process of an oplock break. */
3887 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3888 DEBUGADD(2,( "in oplock break state.\n"));
3890 push_oplock_pending_smb_message(inbuf, length);
3894 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3895 SET_OPEN_MODE(DOS_OPEN_RDWR),
3896 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3897 FILE_ATTRIBUTE_NORMAL,
3898 INTERNAL_OPEN_ONLY, &access_mode, &action);
3900 if (new_fsp == NULL)
3901 return(UNIXERROR(ERRDOS,ERRbadpath));
3902 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3903 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3904 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3905 new_fsp->fnum, strerror(errno)));
3908 close_file(new_fsp,True);
3910 ret = vfs_allocate_file_space(fsp, allocation_size);
3911 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3912 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3913 fsp->fnum, strerror(errno)));
3918 return ERROR_NT(NT_STATUS_DISK_FULL);
3920 /* Allocate can truncate size... */
3921 size = get_file_size(new_sbuf);
3927 case SMB_FILE_END_OF_FILE_INFORMATION:
3928 case SMB_SET_FILE_END_OF_FILE_INFO:
3930 if (total_data < 8) {
3931 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3934 size = IVAL(pdata,0);
3935 #ifdef LARGE_SMB_OFF_T
3936 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3937 #else /* LARGE_SMB_OFF_T */
3938 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3939 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3940 #endif /* LARGE_SMB_OFF_T */
3941 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3945 case SMB_FILE_DISPOSITION_INFORMATION:
3946 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3948 BOOL delete_on_close;
3950 if (total_data < 1) {
3951 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3954 delete_on_close = (CVAL(pdata,0) ? True : False);
3956 /* Just ignore this set on a path. */
3957 if (tran_call != TRANSACT2_SETFILEINFO)
3961 return(UNIXERROR(ERRDOS,ERRbadfid));
3963 status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3965 if (!NT_STATUS_IS_OK(status)) {
3966 return ERROR_NT(status);
3969 /* The set is across all open files on this dev/inode pair. */
3970 status =set_delete_on_close_over_all(fsp, delete_on_close);
3971 if (!NT_STATUS_IS_OK(status)) {
3972 return ERROR_NT(status);
3976 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3980 case SMB_FILE_POSITION_INFORMATION:
3982 SMB_BIG_UINT position_information;
3984 if (total_data < 8) {
3985 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3988 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3989 #ifdef LARGE_SMB_OFF_T
3990 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3991 #else /* LARGE_SMB_OFF_T */
3992 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3993 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3994 #endif /* LARGE_SMB_OFF_T */
3995 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3996 fname, (double)position_information ));
3998 fsp->position_information = position_information;
4001 /* We're done. We only get position info in this call. */
4003 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4007 /* From tridge Samba4 :
4008 * MODE_INFORMATION in setfileinfo (I have no
4009 * idea what "mode information" on a file is - it takes a value of 0,
4010 * 2, 4 or 6. What could it be?).
4013 case SMB_FILE_MODE_INFORMATION:
4017 if (total_data < 4) {
4018 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4020 mode = IVAL(pdata,0);
4021 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4022 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4025 /* We're done. We only get mode info in this call. */
4027 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4032 * CIFS UNIX extensions.
4035 case SMB_SET_FILE_UNIX_BASIC:
4037 uint32 raw_unixmode;
4039 if (total_data < 100) {
4040 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4043 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4044 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4045 size=IVAL(pdata,0); /* first 8 Bytes are size */
4046 #ifdef LARGE_SMB_OFF_T
4047 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4048 #else /* LARGE_SMB_OFF_T */
4049 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
4050 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4051 #endif /* LARGE_SMB_OFF_T */
4053 pdata+=24; /* ctime & st_blocks are not changed */
4054 tvs.actime = interpret_long_date(pdata); /* access_time */
4055 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
4057 set_owner = (uid_t)IVAL(pdata,0);
4059 set_grp = (gid_t)IVAL(pdata,0);
4061 raw_unixmode = IVAL(pdata,28);
4062 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4063 dosmode = 0; /* Ensure dos mode change doesn't override this. */
4065 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4066 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4067 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4069 if (!VALID_STAT(sbuf)) {
4072 * The only valid use of this is to create character and block
4073 * devices, and named pipes. This is deprecated (IMHO) and
4074 * a new info level should be used for mknod. JRA.
4077 uint32 file_type = IVAL(pdata,0);
4078 #if defined(HAVE_MAKEDEV)
4079 uint32 dev_major = IVAL(pdata,4);
4080 uint32 dev_minor = IVAL(pdata,12);
4083 uid_t myuid = geteuid();
4084 gid_t mygid = getegid();
4085 SMB_DEV_T dev = (SMB_DEV_T)0;
4087 if (tran_call == TRANSACT2_SETFILEINFO)
4088 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4090 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4091 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4094 #if defined(HAVE_MAKEDEV)
4095 dev = makedev(dev_major, dev_minor);
4098 /* We can only create as the owner/group we are. */
4100 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4101 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4102 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4103 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4105 switch (file_type) {
4106 #if defined(S_IFIFO)
4107 case UNIX_TYPE_FIFO:
4108 unixmode |= S_IFIFO;
4111 #if defined(S_IFSOCK)
4112 case UNIX_TYPE_SOCKET:
4113 unixmode |= S_IFSOCK;
4116 #if defined(S_IFCHR)
4117 case UNIX_TYPE_CHARDEV:
4118 unixmode |= S_IFCHR;
4121 #if defined(S_IFBLK)
4122 case UNIX_TYPE_BLKDEV:
4123 unixmode |= S_IFBLK;
4127 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4130 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4131 0%o for file %s\n", (double)dev, unixmode, fname ));
4133 /* Ok - do the mknod. */
4134 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4135 return(UNIXERROR(ERRDOS,ERRnoaccess));
4137 inherit_access_acl(conn, fname, unixmode);
4140 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4145 * Deal with the UNIX specific mode set.
4148 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4149 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4150 (unsigned int)unixmode, fname ));
4151 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4152 return(UNIXERROR(ERRDOS,ERRnoaccess));
4156 * Deal with the UNIX specific uid set.
4159 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4160 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4161 (unsigned int)set_owner, fname ));
4162 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4163 return(UNIXERROR(ERRDOS,ERRnoaccess));
4167 * Deal with the UNIX specific gid set.
4170 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4171 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4172 (unsigned int)set_owner, fname ));
4173 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4174 return(UNIXERROR(ERRDOS,ERRnoaccess));
4179 case SMB_SET_FILE_UNIX_LINK:
4181 pstring link_target;
4182 char *newname = fname;
4184 /* Set a symbolic link. */
4185 /* Don't allow this if follow links is false. */
4187 if (!lp_symlinks(SNUM(conn)))
4188 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4190 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4192 /* !widelinks forces the target path to be within the share. */
4193 /* This means we can interpret the target as a pathname. */
4194 if (!lp_widelinks(SNUM(conn))) {
4196 char *last_dirp = NULL;
4198 unix_format(link_target);
4199 if (*link_target == '/') {
4200 /* No absolute paths allowed. */
4201 return(UNIXERROR(ERRDOS,ERRnoaccess));
4203 pstrcpy(rel_name, newname);
4204 last_dirp = strrchr_m(rel_name, '/');
4206 last_dirp[1] = '\0';
4208 pstrcpy(rel_name, "./");
4210 pstrcat(rel_name, link_target);
4212 if (!check_name(rel_name, conn)) {
4213 return(UNIXERROR(ERRDOS,ERRnoaccess));
4217 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4218 fname, link_target ));
4220 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4221 return(UNIXERROR(ERRDOS,ERRnoaccess));
4223 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4227 case SMB_SET_FILE_UNIX_HLINK:
4230 char *newname = fname;
4232 /* Set a hard link. */
4233 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
4234 if (!NT_STATUS_IS_OK(status)) {
4235 return ERROR_NT(status);
4238 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4241 status = hardlink_internals(conn, oldname, newname);
4242 if (!NT_STATUS_IS_OK(status)) {
4243 return ERROR_NT(status);
4247 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4251 case SMB_FILE_RENAME_INFORMATION:
4260 if (total_data < 12) {
4261 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4264 overwrite = (CVAL(pdata,0) ? True : False);
4265 root_fid = IVAL(pdata,4);
4266 len = IVAL(pdata,8);
4267 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
4268 if (!NT_STATUS_IS_OK(status)) {
4269 return ERROR_NT(status);
4272 /* Check the new name has no '/' characters. */
4273 if (strchr_m(newname, '/'))
4274 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4276 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4278 /* Create the base directory. */
4279 pstrcpy(base_name, fname);
4280 p = strrchr_m(base_name, '/');
4283 /* Append the new name. */
4284 pstrcat(base_name, "/");
4285 pstrcat(base_name, newname);
4288 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4289 fsp->fnum, fsp->fsp_name, base_name ));
4290 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4292 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4294 status = rename_internals(conn, fname, base_name, 0, overwrite);
4296 if (!NT_STATUS_IS_OK(status)) {
4297 return ERROR_NT(status);
4299 process_pending_change_notify_queue((time_t)0);
4301 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4305 #if defined(HAVE_POSIX_ACLS)
4306 case SMB_SET_POSIX_ACL:
4308 uint16 posix_acl_version;
4309 uint16 num_file_acls;
4310 uint16 num_def_acls;
4311 BOOL valid_file_acls = True;
4312 BOOL valid_def_acls = True;
4314 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4315 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4317 posix_acl_version = SVAL(pdata,0);
4318 num_file_acls = SVAL(pdata,2);
4319 num_def_acls = SVAL(pdata,4);
4321 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4322 valid_file_acls = False;
4326 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4327 valid_def_acls = False;
4331 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4332 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4335 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4336 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4337 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4340 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4341 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4342 return(UNIXERROR(ERRDOS,ERRnoaccess));
4345 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4346 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4347 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4348 return(UNIXERROR(ERRDOS,ERRnoaccess));
4352 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4358 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4361 /* get some defaults (no modifications) if any info is zero or -1. */
4362 if (null_mtime(tvs.actime)) {
4363 tvs.actime = sbuf.st_atime;
4366 if (null_mtime(tvs.modtime)) {
4367 tvs.modtime = sbuf.st_mtime;
4370 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4371 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4372 DEBUG(6,("size: %.0f ", (double)size));
4375 if (S_ISDIR(sbuf.st_mode))
4381 DEBUG(6,("dosmode: %x\n" , dosmode));
4383 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4384 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4385 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4386 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4389 * Only do this test if we are not explicitly
4390 * changing the size of a file.
4393 size = get_file_size(sbuf);
4397 * Try and set the times, size and mode of this file -
4398 * if they are different from the current values
4401 /* check the mode isn't different, before changing it */
4402 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4404 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4406 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4407 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4408 return(UNIXERROR(ERRDOS,ERRnoaccess));
4413 if (size != get_file_size(sbuf)) {
4417 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4418 fname, (double)size ));
4421 files_struct *new_fsp = NULL;
4422 int access_mode = 0;
4425 if(global_oplock_break) {
4426 /* Queue this file modify as we are the process of an oplock break. */
4428 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
4429 DEBUGADD(2,( "in oplock break state.\n"));
4431 push_oplock_pending_smb_message(inbuf, length);
4435 new_fsp = open_file_shared(conn, fname, &sbuf,
4436 SET_OPEN_MODE(DOS_OPEN_RDWR),
4437 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
4438 FILE_ATTRIBUTE_NORMAL,
4439 INTERNAL_OPEN_ONLY, &access_mode, &action);
4441 if (new_fsp == NULL)
4442 return(UNIXERROR(ERRDOS,ERRbadpath));
4443 ret = vfs_set_filelen(new_fsp, size);
4444 close_file(new_fsp,True);
4446 ret = vfs_set_filelen(fsp, size);
4450 return (UNIXERROR(ERRHRD,ERRdiskfull));
4454 * Finally the times.
4456 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4459 * This was a setfileinfo on an open file.
4460 * NT does this a lot. We also need to
4461 * set the time here, as it can be read by
4462 * FindFirst/FindNext and with the patch for bug #2045
4463 * in smbd/fileio.c it ensures that this timestamp is
4464 * kept sticky even after a write. We save the request
4465 * away and will set it on file close and after a write. JRA.
4468 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4469 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4470 fsp_set_pending_modtime(fsp, tvs.modtime);
4474 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4476 if(file_utime(conn, fname, &tvs)!=0) {
4477 return(UNIXERROR(ERRDOS,ERRnoaccess));
4482 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4487 /****************************************************************************
4488 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4489 ****************************************************************************/
4491 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4492 char **pparams, int total_params, char **ppdata, int total_data,
4493 unsigned int max_data_bytes)
4495 char *params = *pparams;
4496 char *pdata = *ppdata;
4499 SMB_STRUCT_STAT sbuf;
4500 BOOL bad_path = False;
4501 NTSTATUS status = NT_STATUS_OK;
4502 TALLOC_CTX *ctx = NULL;
4503 struct ea_list *ea_list = NULL;
4505 if (!CAN_WRITE(conn))
4506 return ERROR_DOS(ERRSRV,ERRaccess);
4508 if (total_params < 4) {
4509 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4512 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4513 if (!NT_STATUS_IS_OK(status)) {
4514 return ERROR_NT(status);
4517 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4519 unix_convert(directory,conn,0,&bad_path,&sbuf);
4521 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4524 /* Any data in this call is an EA list. */
4525 if (total_data && !lp_ea_support(SNUM(conn))) {
4526 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4530 if (total_data < 10) {
4531 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4534 if (IVAL(pdata,0) > total_data) {
4535 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4536 IVAL(pdata,0), (unsigned int)total_data));
4537 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4540 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4542 return ERROR_NT(NT_STATUS_NO_MEMORY);
4544 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4546 talloc_destroy(ctx);
4547 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4551 if (check_name(directory,conn)) {
4552 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4556 talloc_destroy(ctx);
4557 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4558 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4561 /* Try and set any given EA. */
4563 status = set_ea(conn, NULL, directory, ea_list);
4564 talloc_destroy(ctx);
4565 if (!NT_STATUS_IS_OK(status)) {
4566 return ERROR_NT(status);
4570 /* Realloc the parameter and data sizes */
4571 params = SMB_REALLOC(*pparams,2);
4572 if(params == NULL) {
4573 return ERROR_NT(NT_STATUS_NO_MEMORY);
4579 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4584 /****************************************************************************
4585 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4586 We don't actually do this - we just send a null response.
4587 ****************************************************************************/
4589 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4590 char **pparams, int total_params, char **ppdata, int total_data,
4591 unsigned int max_data_bytes)
4593 static uint16 fnf_handle = 257;
4594 char *params = *pparams;
4597 if (total_params < 6) {
4598 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4601 info_level = SVAL(params,4);
4602 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4604 switch (info_level) {
4609 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4612 /* Realloc the parameter and data sizes */
4613 params = SMB_REALLOC(*pparams,6);
4614 if(params == NULL) {
4615 return ERROR_NT(NT_STATUS_NO_MEMORY);
4619 SSVAL(params,0,fnf_handle);
4620 SSVAL(params,2,0); /* No changes */
4621 SSVAL(params,4,0); /* No EA errors */
4628 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4633 /****************************************************************************
4634 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4635 changes). Currently this does nothing.
4636 ****************************************************************************/
4638 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4639 char **pparams, int total_params, char **ppdata, int total_data,
4640 unsigned int max_data_bytes)
4642 char *params = *pparams;
4644 DEBUG(3,("call_trans2findnotifynext\n"));
4646 /* Realloc the parameter and data sizes */
4647 params = SMB_REALLOC(*pparams,4);
4648 if(params == NULL) {
4649 return ERROR_NT(NT_STATUS_NO_MEMORY);
4653 SSVAL(params,0,0); /* No changes */
4654 SSVAL(params,2,0); /* No EA errors */
4656 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4661 /****************************************************************************
4662 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4663 ****************************************************************************/
4665 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4666 char **pparams, int total_params, char **ppdata, int total_data,
4667 unsigned int max_data_bytes)
4669 char *params = *pparams;
4672 int max_referral_level;
4674 DEBUG(10,("call_trans2getdfsreferral\n"));
4676 if (total_params < 2) {
4677 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4680 max_referral_level = SVAL(params,0);
4682 if(!lp_host_msdfs())
4683 return ERROR_DOS(ERRDOS,ERRbadfunc);
4685 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4686 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4687 return UNIXERROR(ERRDOS,ERRbadfile);
4689 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4690 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4695 #define LMCAT_SPL 0x53
4696 #define LMFUNC_GETJOBID 0x60
4698 /****************************************************************************
4699 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4700 ****************************************************************************/
4702 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4703 char **pparams, int total_params, char **ppdata, int total_data,
4704 unsigned int max_data_bytes)
4706 char *pdata = *ppdata;
4707 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4709 /* check for an invalid fid before proceeding */
4712 return(ERROR_DOS(ERRDOS,ERRbadfid));
4714 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4715 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4716 pdata = SMB_REALLOC(*ppdata, 32);
4718 return ERROR_NT(NT_STATUS_NO_MEMORY);
4722 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4723 CAN ACCEPT THIS IN UNICODE. JRA. */
4725 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4726 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4727 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4728 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4731 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4732 return ERROR_DOS(ERRSRV,ERRerror);
4736 /****************************************************************************
4737 Reply to a SMBfindclose (stop trans2 directory search).
4738 ****************************************************************************/
4740 int reply_findclose(connection_struct *conn,
4741 char *inbuf,char *outbuf,int length,int bufsize)
4744 int dptr_num=SVALS(inbuf,smb_vwv0);
4745 START_PROFILE(SMBfindclose);
4747 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4749 dptr_close(&dptr_num);
4751 outsize = set_message(outbuf,0,0,True);
4753 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4755 END_PROFILE(SMBfindclose);
4759 /****************************************************************************
4760 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4761 ****************************************************************************/
4763 int reply_findnclose(connection_struct *conn,
4764 char *inbuf,char *outbuf,int length,int bufsize)
4768 START_PROFILE(SMBfindnclose);
4770 dptr_num = SVAL(inbuf,smb_vwv0);
4772 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4774 /* We never give out valid handles for a
4775 findnotifyfirst - so any dptr_num is ok here.
4778 outsize = set_message(outbuf,0,0,True);
4780 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4782 END_PROFILE(SMBfindnclose);
4786 /****************************************************************************
4787 Reply to a SMBtranss2 - just ignore it!
4788 ****************************************************************************/
4790 int reply_transs2(connection_struct *conn,
4791 char *inbuf,char *outbuf,int length,int bufsize)
4793 START_PROFILE(SMBtranss2);
4794 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4795 END_PROFILE(SMBtranss2);
4799 /****************************************************************************
4800 Reply to a SMBtrans2.
4801 ****************************************************************************/
4803 int reply_trans2(connection_struct *conn,
4804 char *inbuf,char *outbuf,int length,int bufsize)
4807 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4808 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4809 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4811 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4812 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4813 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4814 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4815 int32 timeout = IVALS(inbuf,smb_timeout);
4817 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4818 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4819 char *params = NULL, *data = NULL;
4820 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4821 START_PROFILE(SMBtrans2);
4823 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4824 /* Queue this open message as we are the process of an
4827 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4828 DEBUGADD(2,( "in oplock break state.\n"));
4830 push_oplock_pending_smb_message(inbuf, length);
4831 END_PROFILE(SMBtrans2);
4835 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4836 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4837 END_PROFILE(SMBtrans2);
4838 return ERROR_DOS(ERRSRV,ERRaccess);
4841 outsize = set_message(outbuf,0,0,True);
4843 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4844 is so as a sanity check */
4847 * Need to have rc=0 for ioctl to get job id for OS/2.
4848 * Network printing will fail if function is not successful.
4849 * Similar function in reply.c will be used if protocol
4850 * is LANMAN1.0 instead of LM1.2X002.
4851 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4852 * outbuf doesn't have to be set(only job id is used).
4854 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4855 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4856 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4857 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4859 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4860 DEBUG(2,("Transaction is %d\n",tran_call));
4861 END_PROFILE(SMBtrans2);
4862 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4866 /* Allocate the space for the maximum needed parameters and data */
4867 if (total_params > 0)
4868 params = (char *)SMB_MALLOC(total_params);
4870 data = (char *)SMB_MALLOC(total_data);
4872 if ((total_params && !params) || (total_data && !data)) {
4873 DEBUG(2,("Out of memory in reply_trans2\n"));
4876 END_PROFILE(SMBtrans2);
4877 return ERROR_NT(NT_STATUS_NO_MEMORY);
4880 /* Copy the param and data bytes sent with this request into
4881 the params buffer */
4882 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4883 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4885 if (num_params > total_params || num_data > total_data)
4886 exit_server("invalid params in reply_trans2");
4889 unsigned int psoff = SVAL(inbuf, smb_psoff);
4890 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4892 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4893 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4895 memcpy( params, smb_base(inbuf) + psoff, num_params);
4898 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4899 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4901 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4902 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4904 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4907 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4909 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4910 /* We need to send an interim response then receive the rest
4911 of the parameter/data bytes */
4912 outsize = set_message(outbuf,0,0,True);
4913 srv_signing_trans_stop();
4914 if (!send_smb(smbd_server_fd(),outbuf))
4915 exit_server("reply_trans2: send_smb failed.");
4917 while (num_data_sofar < total_data ||
4918 num_params_sofar < total_params) {
4920 unsigned int param_disp;
4921 unsigned int param_off;
4922 unsigned int data_disp;
4923 unsigned int data_off;
4925 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4927 /* We need to re-calcuate the new length after we've read the secondary packet. */
4928 length = smb_len(inbuf) + 4;
4931 * The sequence number for the trans reply is always
4932 * based on the last secondary received.
4935 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4938 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4939 outsize = set_message(outbuf,0,0,True);
4941 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4943 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4944 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4948 /* Revise total_params and total_data in case
4949 they have changed downwards */
4950 if (SVAL(inbuf, smb_tpscnt) < total_params)
4951 total_params = SVAL(inbuf, smb_tpscnt);
4952 if (SVAL(inbuf, smb_tdscnt) < total_data)
4953 total_data = SVAL(inbuf, smb_tdscnt);
4955 num_params = SVAL(inbuf,smb_spscnt);
4956 param_off = SVAL(inbuf, smb_spsoff);
4957 param_disp = SVAL(inbuf, smb_spsdisp);
4958 num_params_sofar += num_params;
4960 num_data = SVAL(inbuf, smb_sdscnt);
4961 data_off = SVAL(inbuf, smb_sdsoff);
4962 data_disp = SVAL(inbuf, smb_sdsdisp);
4963 num_data_sofar += num_data;
4965 if (num_params_sofar > total_params || num_data_sofar > total_data)
4969 if (param_disp + num_params > total_params)
4971 if ((param_disp + num_params < param_disp) ||
4972 (param_disp + num_params < num_params))
4974 if (param_disp > total_params)
4976 if ((smb_base(inbuf) + param_off + num_params > inbuf + length) ||
4977 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4979 if (params + param_disp < params)
4982 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
4985 if (data_disp + num_data > total_data)
4987 if ((data_disp + num_data < data_disp) ||
4988 (data_disp + num_data < num_data))
4990 if (data_disp > total_data)
4992 if ((smb_base(inbuf) + data_off + num_data > inbuf + length) ||
4993 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4995 if (data + data_disp < data)
4998 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
5003 if (Protocol >= PROTOCOL_NT1) {
5004 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
5007 /* Now we must call the relevant TRANS2 function */
5009 case TRANSACT2_OPEN:
5010 START_PROFILE_NESTED(Trans2_open);
5011 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
5012 ¶ms, total_params, &data, total_data, max_data_bytes);
5013 END_PROFILE_NESTED(Trans2_open);
5016 case TRANSACT2_FINDFIRST:
5017 START_PROFILE_NESTED(Trans2_findfirst);
5018 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
5019 ¶ms, total_params, &data, total_data, max_data_bytes);
5020 END_PROFILE_NESTED(Trans2_findfirst);
5023 case TRANSACT2_FINDNEXT:
5024 START_PROFILE_NESTED(Trans2_findnext);
5025 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
5026 ¶ms, total_params, &data, total_data, max_data_bytes);
5027 END_PROFILE_NESTED(Trans2_findnext);
5030 case TRANSACT2_QFSINFO:
5031 START_PROFILE_NESTED(Trans2_qfsinfo);
5032 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
5033 ¶ms, total_params, &data, total_data, max_data_bytes);
5034 END_PROFILE_NESTED(Trans2_qfsinfo);
5037 case TRANSACT2_SETFSINFO:
5038 START_PROFILE_NESTED(Trans2_setfsinfo);
5039 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
5040 ¶ms, total_params, &data, total_data, max_data_bytes);
5041 END_PROFILE_NESTED(Trans2_setfsinfo);
5044 case TRANSACT2_QPATHINFO:
5045 case TRANSACT2_QFILEINFO:
5046 START_PROFILE_NESTED(Trans2_qpathinfo);
5047 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5048 ¶ms, total_params, &data, total_data, max_data_bytes);
5049 END_PROFILE_NESTED(Trans2_qpathinfo);
5051 case TRANSACT2_SETPATHINFO:
5052 case TRANSACT2_SETFILEINFO:
5053 START_PROFILE_NESTED(Trans2_setpathinfo);
5054 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5055 ¶ms, total_params, &data, total_data, max_data_bytes);
5056 END_PROFILE_NESTED(Trans2_setpathinfo);
5059 case TRANSACT2_FINDNOTIFYFIRST:
5060 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5061 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
5062 ¶ms, total_params, &data, total_data, max_data_bytes);
5063 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5066 case TRANSACT2_FINDNOTIFYNEXT:
5067 START_PROFILE_NESTED(Trans2_findnotifynext);
5068 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
5069 ¶ms, total_params, &data, total_data, max_data_bytes);
5070 END_PROFILE_NESTED(Trans2_findnotifynext);
5072 case TRANSACT2_MKDIR:
5073 START_PROFILE_NESTED(Trans2_mkdir);
5074 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
5075 ¶ms, total_params, &data, total_data, max_data_bytes);
5076 END_PROFILE_NESTED(Trans2_mkdir);
5079 case TRANSACT2_GET_DFS_REFERRAL:
5080 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5081 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
5082 ¶ms, total_params, &data, total_data, max_data_bytes);
5083 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5085 case TRANSACT2_IOCTL:
5086 START_PROFILE_NESTED(Trans2_ioctl);
5087 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
5088 ¶ms, total_params, &data, total_data, max_data_bytes);
5089 END_PROFILE_NESTED(Trans2_ioctl);
5092 /* Error in request */
5093 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
5096 END_PROFILE(SMBtrans2);
5097 srv_signing_trans_stop();
5098 return ERROR_DOS(ERRSRV,ERRerror);
5101 /* As we do not know how many data packets will need to be
5102 returned here the various call_trans2xxxx calls
5103 must send their own. Thus a call_trans2xxx routine only
5104 returns a value other than -1 when it wants to send
5108 srv_signing_trans_stop();
5112 END_PROFILE(SMBtrans2);
5113 return outsize; /* If a correct response was needed the
5114 call_trans2xxx calls have already sent
5115 it. If outsize != -1 then it is returning */
5119 srv_signing_trans_stop();
5122 END_PROFILE(SMBtrans2);
5123 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);