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.
26 extern enum protocol_types Protocol;
27 extern int smb_read_error;
28 extern int global_oplock_break;
29 extern uint32 global_client_caps;
30 extern struct current_user current_user;
32 #define get_file_size(sbuf) ((sbuf).st_size)
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 /********************************************************************
36 Roundup a value to the nearest allocation roundup size boundary.
37 Only do this for Windows clients.
38 ********************************************************************/
40 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
42 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
44 /* Only roundup for Windows clients. */
45 enum remote_arch_types ra_type = get_remote_arch();
46 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
47 val = SMB_ROUNDUP(val,rval);
52 /********************************************************************
53 Given a stat buffer return the allocated size on disk, taking into
55 ********************************************************************/
57 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
61 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
62 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
64 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
67 if (!ret && fsp && fsp->initial_allocation_size)
68 ret = fsp->initial_allocation_size;
70 return smb_roundup(conn, ret);
73 /****************************************************************************
74 Utility functions for dealing with extended attributes.
75 ****************************************************************************/
77 static const char *prohibited_ea_names[] = {
78 SAMBA_POSIX_INHERITANCE_EA_NAME,
79 SAMBA_XATTR_DOS_ATTRIB,
83 /****************************************************************************
84 Refuse to allow clients to overwrite our private xattrs.
85 ****************************************************************************/
87 static BOOL samba_private_attr_name(const char *unix_ea_name)
91 for (i = 0; prohibited_ea_names[i]; i++) {
92 if (strequal( prohibited_ea_names[i], unix_ea_name))
99 struct ea_list *next, *prev;
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);
241 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 static 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 a list of EA names and data from an incoming data buffer. Create an ea_list with them.
424 ****************************************************************************/
426 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
428 struct ea_list *ea_list_head = NULL;
431 if (data_size < 10) {
435 if (IVAL(pdata,0) > data_size) {
436 DEBUG(10,("read_ea_list: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)data_size));
440 /* Each entry must be at least 6 bytes in length. */
441 while (offset + 6 <= data_size) {
443 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
445 unsigned int namelen;
447 eal->ea.flags = CVAL(pdata,offset);
448 namelen = CVAL(pdata,offset + 1);
449 val_len = SVAL(pdata,offset + 2);
451 /* integer wrap paranioa. */
452 if ((offset + namelen + 5 + val_len < offset) ||
453 (offset + namelen + 5 + val_len < namelen) ||
454 (offset + namelen + 5 + val_len < val_len) ||
455 (offset > data_size) ||
456 (namelen > data_size) ||
457 (offset + namelen >= data_size)) {
461 if (offset + 4 + namelen + 1 + val_len > data_size) {
465 /* Ensure the name is null terminated. */
466 if (pdata[offset + 4 + namelen] != '\0') {
469 pull_ascii_talloc(ctx, &eal->ea.name, pdata + offset + 4);
474 eal->ea.value = data_blob(NULL, (size_t)val_len + 1);
475 if (!eal->ea.value.data) {
479 memcpy(eal->ea.value.data, pdata + offset + 4 + namelen + 1, val_len);
481 /* Ensure we're null terminated just in case we print the value. */
482 eal->ea.value.data[val_len] = '\0';
483 /* But don't count the null. */
484 eal->ea.value.length--;
486 offset += 4 + namelen + 1 + val_len;
488 DLIST_ADD_END(ea_list_head, eal, tmp);
490 DEBUG(10,("read_ea_list: read ea name %s\n", eal->ea.name));
491 dump_data(10, eal->ea.value.data, eal->ea.value.length);
497 /****************************************************************************
498 Count the total EA size needed.
499 ****************************************************************************/
501 static size_t ea_list_size(struct ea_list *ealist)
504 struct ea_list *listp;
507 for (listp = ealist; listp; listp = listp->next) {
508 push_ascii_fstring(dos_ea_name, listp->ea.name);
509 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
511 /* Add on 4 for total length. */
519 /****************************************************************************
520 Return a union of EA's from a file list and a list of names.
521 The TALLOC context for the two lists *MUST* be identical as we steal
522 memory from one list to add to another. JRA.
523 ****************************************************************************/
525 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
527 struct ea_list *nlistp, *flistp;
529 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
530 for (flistp = file_list; flistp; flistp = flistp->next) {
531 if (strequal(nlistp->ea.name, flistp->ea.name)) {
537 /* Copy the data from this entry. */
538 nlistp->ea.flags = flistp->ea.flags;
539 nlistp->ea.value = flistp->ea.value;
542 nlistp->ea.flags = 0;
543 ZERO_STRUCT(nlistp->ea.value);
547 *total_ea_len = ea_list_size(name_list);
551 /****************************************************************************
552 Send the required number of replies back.
553 We assume all fields other than the data fields are
554 set correctly for the type of call.
555 HACK ! Always assumes smb_setup field is zero.
556 ****************************************************************************/
558 static int send_trans2_replies(char *outbuf,
565 /* As we are using a protocol > LANMAN1 then the max_send
566 variable must have been set in the sessetupX call.
567 This takes precedence over the max_xmit field in the
568 global struct. These different max_xmit variables should
569 be merged as this is now too confusing */
572 int data_to_send = datasize;
573 int params_to_send = paramsize;
577 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
578 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
579 int data_alignment_offset = 0;
581 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
583 set_message(outbuf,10,0,True);
585 /* If there genuinely are no parameters or data to send just send the empty packet */
587 if(params_to_send == 0 && data_to_send == 0) {
588 if (!send_smb(smbd_server_fd(),outbuf))
589 exit_server("send_trans2_replies: send_smb failed.");
593 /* When sending params and data ensure that both are nicely aligned */
594 /* Only do this alignment when there is also data to send - else
595 can cause NT redirector problems. */
597 if (((params_to_send % 4) != 0) && (data_to_send != 0))
598 data_alignment_offset = 4 - (params_to_send % 4);
600 /* Space is bufsize minus Netbios over TCP header minus SMB header */
601 /* The alignment_offset is to align the param bytes on an even byte
602 boundary. NT 4.0 Beta needs this to work correctly. */
604 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
606 /* useable_space can never be more than max_send minus the alignment offset. */
608 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
610 while (params_to_send || data_to_send) {
611 /* Calculate whether we will totally or partially fill this packet */
613 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
615 /* We can never send more than useable_space */
617 * Note that 'useable_space' does not include the alignment offsets,
618 * but we must include the alignment offsets in the calculation of
619 * the length of the data we send over the wire, as the alignment offsets
620 * are sent here. Fix from Marc_Jacobsen@hp.com.
623 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
625 set_message(outbuf, 10, total_sent_thistime, True);
627 /* Set total params and data to be sent */
628 SSVAL(outbuf,smb_tprcnt,paramsize);
629 SSVAL(outbuf,smb_tdrcnt,datasize);
631 /* Calculate how many parameters and data we can fit into
632 * this packet. Parameters get precedence
635 params_sent_thistime = MIN(params_to_send,useable_space);
636 data_sent_thistime = useable_space - params_sent_thistime;
637 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
639 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
641 /* smb_proff is the offset from the start of the SMB header to the
642 parameter bytes, however the first 4 bytes of outbuf are
643 the Netbios over TCP header. Thus use smb_base() to subtract
644 them from the calculation */
646 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
648 if(params_sent_thistime == 0)
649 SSVAL(outbuf,smb_prdisp,0);
651 /* Absolute displacement of param bytes sent in this packet */
652 SSVAL(outbuf,smb_prdisp,pp - params);
654 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
655 if(data_sent_thistime == 0) {
656 SSVAL(outbuf,smb_droff,0);
657 SSVAL(outbuf,smb_drdisp, 0);
659 /* The offset of the data bytes is the offset of the
660 parameter bytes plus the number of parameters being sent this time */
661 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
662 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
663 SSVAL(outbuf,smb_drdisp, pd - pdata);
666 /* Copy the param bytes into the packet */
668 if(params_sent_thistime)
669 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
671 /* Copy in the data bytes */
672 if(data_sent_thistime)
673 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
674 data_alignment_offset,pd,data_sent_thistime);
676 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
677 params_sent_thistime, data_sent_thistime, useable_space));
678 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
679 params_to_send, data_to_send, paramsize, datasize));
681 /* Send the packet */
682 if (!send_smb(smbd_server_fd(),outbuf))
683 exit_server("send_trans2_replies: send_smb failed.");
685 pp += params_sent_thistime;
686 pd += data_sent_thistime;
688 params_to_send -= params_sent_thistime;
689 data_to_send -= data_sent_thistime;
692 if(params_to_send < 0 || data_to_send < 0) {
693 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
694 params_to_send, data_to_send));
702 /****************************************************************************
703 Reply to a TRANSACT2_OPEN.
704 ****************************************************************************/
706 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
707 char **pparams, int total_params, char **ppdata, int total_data,
708 unsigned int max_data_bytes)
710 char *params = *pparams;
715 BOOL return_additional_info;
724 int fmode=0,mtime=0,rmode;
726 SMB_STRUCT_STAT sbuf;
728 BOOL bad_path = False;
733 * Ensure we have enough parameters to perform the operation.
736 if (total_params < 29) {
737 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
740 open_mode = SVAL(params, 2);
741 open_attr = SVAL(params,6);
742 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
744 return_additional_info = BITSETW(params,0);
745 open_sattr = SVAL(params, 4);
746 open_time = make_unix_date3(params+8);
748 open_ofun = SVAL(params,12);
749 open_size = IVAL(params,14);
753 return(ERROR_DOS(ERRSRV,ERRaccess));
755 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
756 if (!NT_STATUS_IS_OK(status)) {
757 return ERROR_NT(status);
760 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
761 fname,open_mode, open_attr, open_ofun, open_size));
763 /* XXXX we need to handle passed times, sattr and flags */
765 unix_convert(fname,conn,0,&bad_path,&sbuf);
767 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
770 if (!check_name(fname,conn)) {
771 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
774 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
775 oplock_request, &rmode,&smb_action);
778 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
779 /* We have re-scheduled this call. */
780 clear_cached_errors();
783 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
786 size = get_file_size(sbuf);
787 fmode = dos_mode(conn,fname,&sbuf);
788 mtime = sbuf.st_mtime;
791 close_file(fsp,False);
792 return(ERROR_DOS(ERRDOS,ERRnoaccess));
795 /* Realloc the size of parameters and data we will return */
796 params = SMB_REALLOC(*pparams, 28);
797 if( params == NULL ) {
798 return ERROR_NT(NT_STATUS_NO_MEMORY);
802 memset((char *)params,'\0',28);
803 SSVAL(params,0,fsp->fnum);
804 SSVAL(params,2,fmode);
805 put_dos_date2(params,4, mtime);
806 SIVAL(params,8, (uint32)size);
807 SSVAL(params,12,rmode);
809 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
810 smb_action |= EXTENDED_OPLOCK_GRANTED;
812 SSVAL(params,18,smb_action);
815 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
817 SIVAL(params,20,inode);
819 /* Send the required number of replies */
820 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
825 /*********************************************************
826 Routine to check if a given string matches exactly.
827 as a special case a mask of "." does NOT match. That
828 is required for correct wildcard semantics
829 Case can be significant or not.
830 **********************************************************/
832 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
834 if (mask[0] == '.' && mask[1] == 0)
837 return strcmp(str,mask)==0;
838 if (StrCaseCmp(str,mask) != 0) {
841 if (ms_has_wild(str)) {
847 /****************************************************************************
848 Return the filetype for UNIX extensions.
849 ****************************************************************************/
851 static uint32 unix_filetype(mode_t mode)
854 return UNIX_TYPE_FILE;
855 else if(S_ISDIR(mode))
856 return UNIX_TYPE_DIR;
858 else if(S_ISLNK(mode))
859 return UNIX_TYPE_SYMLINK;
862 else if(S_ISCHR(mode))
863 return UNIX_TYPE_CHARDEV;
866 else if(S_ISBLK(mode))
867 return UNIX_TYPE_BLKDEV;
870 else if(S_ISFIFO(mode))
871 return UNIX_TYPE_FIFO;
874 else if(S_ISSOCK(mode))
875 return UNIX_TYPE_SOCKET;
878 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
879 return UNIX_TYPE_UNKNOWN;
882 /****************************************************************************
883 Map wire perms onto standard UNIX permissions. Obey share restrictions.
884 ****************************************************************************/
886 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
890 if (perms == SMB_MODE_NO_CHANGE)
893 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
894 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
895 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
896 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
897 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
898 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
899 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
900 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
901 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
903 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
906 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
909 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
912 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
913 ret &= lp_dir_mask(SNUM(conn));
914 /* Add in force bits */
915 ret |= lp_force_dir_mode(SNUM(conn));
917 /* Apply mode mask */
918 ret &= lp_create_mask(SNUM(conn));
919 /* Add in force bits */
920 ret |= lp_force_create_mode(SNUM(conn));
926 /****************************************************************************
927 Get a level dependent lanman2 dir entry.
928 ****************************************************************************/
930 static BOOL get_lanman2_dir_entry(connection_struct *conn,
931 void *inbuf, void *outbuf,
932 char *path_mask,int dirtype,int info_level,
933 int requires_resume_key,
934 BOOL dont_descend,char **ppdata,
935 char *base_data, int space_remaining,
936 BOOL *out_of_space, BOOL *got_exact_match,
937 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
941 SMB_STRUCT_STAT sbuf;
945 char *p, *q, *pdata = *ppdata;
949 SMB_OFF_T file_size = 0;
950 SMB_BIG_UINT allocation_size = 0;
952 time_t mdate=0, adate=0, cdate=0;
954 char *last_entry_ptr;
956 int nt_extmode; /* Used for NT connections instead of mode */
957 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
960 *out_of_space = False;
961 *got_exact_match = False;
966 p = strrchr_m(path_mask,'/');
973 pstrcpy(mask, path_mask);
978 /* Needed if we run out of space */
979 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
980 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
983 * Due to bugs in NT client redirectors we are not using
984 * resume keys any more - set them to zero.
985 * Check out the related comments in findfirst/findnext.
991 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
992 (long)conn->dirptr,curr_dirpos));
997 pstrcpy(fname,dname);
999 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
1000 got_match = mask_match(fname, mask, conn->case_sensitive);
1002 if(!got_match && !mangle_is_8_3(fname, False)) {
1005 * It turns out that NT matches wildcards against
1006 * both long *and* short names. This may explain some
1007 * of the wildcard wierdness from old DOS clients
1008 * that some people have been seeing.... JRA.
1012 pstrcpy( newname, fname);
1013 mangle_map( newname, True, False, SNUM(conn));
1014 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
1015 got_match = mask_match(newname, mask, conn->case_sensitive);
1019 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1020 if (dont_descend && !isdots)
1023 pstrcpy(pathreal,conn->dirpath);
1025 pstrcat(pathreal,"/");
1026 pstrcat(pathreal,dname);
1028 if (INFO_LEVEL_IS_UNIX(info_level)) {
1029 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1030 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1031 pathreal,strerror(errno)));
1034 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1036 /* Needed to show the msdfs symlinks as
1039 if(lp_host_msdfs() &&
1040 lp_msdfs_root(SNUM(conn)) &&
1041 is_msdfs_link(conn, pathreal, NULL, NULL,
1044 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1045 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1049 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1050 pathreal,strerror(errno)));
1055 mode = dos_mode(conn,pathreal,&sbuf);
1057 if (!dir_check_ftype(conn,mode,dirtype)) {
1058 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1062 file_size = get_file_size(sbuf);
1063 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1064 mdate = sbuf.st_mtime;
1065 adate = sbuf.st_atime;
1066 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1068 if (lp_dos_filetime_resolution(SNUM(conn))) {
1075 /* This is necessary, as otherwise the
1076 * desktop.ini file in this folder is
1078 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
1082 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1088 mangle_map(fname,False,True,SNUM(conn));
1093 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1095 switch (info_level) {
1096 case SMB_FIND_INFO_STANDARD:
1097 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1098 if(requires_resume_key) {
1102 put_dos_date2(p,l1_fdateCreation,cdate);
1103 put_dos_date2(p,l1_fdateLastAccess,adate);
1104 put_dos_date2(p,l1_fdateLastWrite,mdate);
1105 SIVAL(p,l1_cbFile,(uint32)file_size);
1106 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
1107 SSVAL(p,l1_attrFile,mode);
1110 p += align_string(outbuf, p, 0);
1111 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1112 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1114 SCVAL(nameptr, -1, len - 2);
1116 SCVAL(nameptr, -1, 0);
1120 SCVAL(nameptr, -1, len - 1);
1122 SCVAL(nameptr, -1, 0);
1128 case SMB_FIND_EA_SIZE:
1129 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1130 if(requires_resume_key) {
1134 put_dos_date2(p,l2_fdateCreation,cdate);
1135 put_dos_date2(p,l2_fdateLastAccess,adate);
1136 put_dos_date2(p,l2_fdateLastWrite,mdate);
1137 SIVAL(p,l2_cbFile,(uint32)file_size);
1138 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1139 SSVAL(p,l2_attrFile,mode);
1141 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1142 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1146 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1147 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1160 SCVAL(nameptr,0,len);
1162 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1165 case SMB_FIND_EA_LIST:
1167 struct ea_list *file_list = NULL;
1170 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1174 if(requires_resume_key) {
1178 put_dos_date2(p,l2_fdateCreation,cdate);
1179 put_dos_date2(p,l2_fdateLastAccess,adate);
1180 put_dos_date2(p,l2_fdateLastWrite,mdate);
1181 SIVAL(p,l2_cbFile,(uint32)file_size);
1182 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1183 SSVAL(p,l2_attrFile,mode);
1184 p += l2_cbList; /* p now points to the EA area. */
1186 file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1187 name_list = ea_list_union(name_list, file_list, &ea_len);
1189 /* We need to determine if this entry will fit in the space available. */
1190 /* Max string size is 255 bytes. */
1191 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1192 /* Move the dirptr back to prev_dirpos */
1193 dptr_SeekDir(conn->dirptr, prev_dirpos);
1194 *out_of_space = True;
1195 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1196 return False; /* Not finished - just out of space */
1199 /* Push the ea_data followed by the name. */
1200 p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1202 len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1203 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1216 SCVAL(nameptr,0,len);
1218 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1222 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1223 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1224 was_8_3 = mangle_is_8_3(fname, True);
1226 SIVAL(p,0,reskey); p += 4;
1227 put_long_date(p,cdate); p += 8;
1228 put_long_date(p,adate); p += 8;
1229 put_long_date(p,mdate); p += 8;
1230 put_long_date(p,mdate); p += 8;
1231 SOFF_T(p,0,file_size); p += 8;
1232 SOFF_T(p,0,allocation_size); p += 8;
1233 SIVAL(p,0,nt_extmode); p += 4;
1234 q = p; p += 4; /* q is placeholder for name length. */
1236 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1237 SIVAL(p,0,ea_size); /* Extended attributes */
1240 /* Clear the short name buffer. This is
1241 * IMPORTANT as not doing so will trigger
1242 * a Win2k client bug. JRA.
1245 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1246 pstring mangled_name;
1247 pstrcpy(mangled_name, fname);
1248 mangle_map(mangled_name,True,True,SNUM(conn));
1249 mangled_name[12] = 0;
1250 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1257 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1260 len = PTR_DIFF(p, pdata);
1261 len = (len + 3) & ~3;
1266 case SMB_FIND_FILE_DIRECTORY_INFO:
1267 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1269 SIVAL(p,0,reskey); p += 4;
1270 put_long_date(p,cdate); p += 8;
1271 put_long_date(p,adate); p += 8;
1272 put_long_date(p,mdate); p += 8;
1273 put_long_date(p,mdate); p += 8;
1274 SOFF_T(p,0,file_size); p += 8;
1275 SOFF_T(p,0,allocation_size); p += 8;
1276 SIVAL(p,0,nt_extmode); p += 4;
1277 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1280 len = PTR_DIFF(p, pdata);
1281 len = (len + 3) & ~3;
1286 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1287 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1289 SIVAL(p,0,reskey); p += 4;
1290 put_long_date(p,cdate); p += 8;
1291 put_long_date(p,adate); p += 8;
1292 put_long_date(p,mdate); p += 8;
1293 put_long_date(p,mdate); p += 8;
1294 SOFF_T(p,0,file_size); p += 8;
1295 SOFF_T(p,0,allocation_size); p += 8;
1296 SIVAL(p,0,nt_extmode); p += 4;
1297 q = p; p += 4; /* q is placeholder for name length. */
1299 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1300 SIVAL(p,0,ea_size); /* Extended attributes */
1303 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1307 len = PTR_DIFF(p, pdata);
1308 len = (len + 3) & ~3;
1313 case SMB_FIND_FILE_NAMES_INFO:
1314 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1316 SIVAL(p,0,reskey); p += 4;
1318 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1319 acl on a dir (tridge) */
1320 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1323 len = PTR_DIFF(p, pdata);
1324 len = (len + 3) & ~3;
1329 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1330 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1332 SIVAL(p,0,reskey); p += 4;
1333 put_long_date(p,cdate); p += 8;
1334 put_long_date(p,adate); p += 8;
1335 put_long_date(p,mdate); p += 8;
1336 put_long_date(p,mdate); p += 8;
1337 SOFF_T(p,0,file_size); p += 8;
1338 SOFF_T(p,0,allocation_size); p += 8;
1339 SIVAL(p,0,nt_extmode); p += 4;
1340 q = p; p += 4; /* q is placeholder for name length. */
1342 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1343 SIVAL(p,0,ea_size); /* Extended attributes */
1346 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1347 SIVAL(p,0,sbuf.st_dev); p += 4;
1348 SIVAL(p,0,sbuf.st_ino); p += 4;
1349 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1352 len = PTR_DIFF(p, pdata);
1353 len = (len + 3) & ~3;
1358 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1359 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1360 was_8_3 = mangle_is_8_3(fname, True);
1362 SIVAL(p,0,reskey); p += 4;
1363 put_long_date(p,cdate); p += 8;
1364 put_long_date(p,adate); p += 8;
1365 put_long_date(p,mdate); p += 8;
1366 put_long_date(p,mdate); p += 8;
1367 SOFF_T(p,0,file_size); p += 8;
1368 SOFF_T(p,0,allocation_size); p += 8;
1369 SIVAL(p,0,nt_extmode); p += 4;
1370 q = p; p += 4; /* q is placeholder for name length */
1372 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1373 SIVAL(p,0,ea_size); /* Extended attributes */
1376 /* Clear the short name buffer. This is
1377 * IMPORTANT as not doing so will trigger
1378 * a Win2k client bug. JRA.
1381 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1382 pstring mangled_name;
1383 pstrcpy(mangled_name, fname);
1384 mangle_map(mangled_name,True,True,SNUM(conn));
1385 mangled_name[12] = 0;
1386 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1393 SSVAL(p,0,0); p += 2; /* Reserved ? */
1394 SIVAL(p,0,sbuf.st_dev); p += 4;
1395 SIVAL(p,0,sbuf.st_ino); p += 4;
1396 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1399 len = PTR_DIFF(p, pdata);
1400 len = (len + 3) & ~3;
1405 /* CIFS UNIX Extension. */
1407 case SMB_FIND_FILE_UNIX:
1408 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1410 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1412 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1413 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1416 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1419 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1420 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1421 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1424 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1428 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1432 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1435 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1439 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1443 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1446 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1450 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1454 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1457 len = PTR_DIFF(p, pdata);
1458 len = (len + 3) & ~3;
1459 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1461 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1470 if (PTR_DIFF(p,pdata) > space_remaining) {
1471 /* Move the dirptr back to prev_dirpos */
1472 dptr_SeekDir(conn->dirptr, prev_dirpos);
1473 *out_of_space = True;
1474 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1475 return False; /* Not finished - just out of space */
1478 /* Setup the last entry pointer, as an offset from base_data */
1479 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1480 /* Advance the data pointer to the next slot */
1486 /****************************************************************************
1487 Reply to a TRANS2_FINDFIRST.
1488 ****************************************************************************/
1490 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1491 char **pparams, int total_params, char **ppdata, int total_data,
1492 unsigned int max_data_bytes)
1494 /* We must be careful here that we don't return more than the
1495 allowed number of data bytes. If this means returning fewer than
1496 maxentries then so be it. We assume that the redirector has
1497 enough room for the fixed number of parameter bytes it has
1499 char *params = *pparams;
1500 char *pdata = *ppdata;
1501 int dirtype = SVAL(params,0);
1502 int maxentries = SVAL(params,2);
1503 uint16 findfirst_flags = SVAL(params,4);
1504 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1505 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1506 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1507 int info_level = SVAL(params,6);
1511 int last_entry_off=0;
1515 BOOL finished = False;
1516 BOOL dont_descend = False;
1517 BOOL out_of_space = False;
1518 int space_remaining;
1519 BOOL bad_path = False;
1520 SMB_STRUCT_STAT sbuf;
1521 TALLOC_CTX *ea_ctx = NULL;
1522 struct ea_list *ea_list = NULL;
1523 NTSTATUS ntstatus = NT_STATUS_OK;
1525 if (total_params < 12) {
1526 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1529 *directory = *mask = 0;
1531 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1532 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1533 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1534 info_level, max_data_bytes));
1537 /* W2K3 seems to treat zero as 1. */
1541 switch (info_level) {
1542 case SMB_FIND_INFO_STANDARD:
1543 case SMB_FIND_EA_SIZE:
1544 case SMB_FIND_EA_LIST:
1545 case SMB_FIND_FILE_DIRECTORY_INFO:
1546 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1547 case SMB_FIND_FILE_NAMES_INFO:
1548 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1549 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1550 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1552 case SMB_FIND_FILE_UNIX:
1553 if (!lp_unix_extensions())
1554 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1557 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1560 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1561 if (!NT_STATUS_IS_OK(ntstatus)) {
1562 return ERROR_NT(ntstatus);
1565 RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1567 unix_convert(directory,conn,0,&bad_path,&sbuf);
1569 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1571 if(!check_name(directory,conn)) {
1572 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1575 p = strrchr_m(directory,'/');
1577 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1578 if((directory[0] == '.') && (directory[1] == '\0'))
1581 pstrcpy(mask,directory);
1582 pstrcpy(directory,"./");
1588 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1590 if (info_level == SMB_FIND_EA_LIST) {
1593 if (total_data < 4) {
1594 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1597 ea_size = IVAL(pdata,0);
1598 if (ea_size != total_data) {
1599 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1600 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1601 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1604 if (!lp_ea_support(SNUM(conn))) {
1605 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1608 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1609 return ERROR_NT(NT_STATUS_NO_MEMORY);
1612 /* Pull out the list of names. */
1613 ea_list = read_ea_name_list(ea_ctx, pdata, ea_size);
1615 talloc_destroy(ea_ctx);
1616 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1620 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1621 if( pdata == NULL ) {
1622 talloc_destroy(ea_ctx);
1623 return ERROR_NT(NT_STATUS_NO_MEMORY);
1627 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1629 /* Realloc the params space */
1630 params = SMB_REALLOC(*pparams, 10);
1631 if (params == NULL) {
1632 talloc_destroy(ea_ctx);
1633 return ERROR_NT(NT_STATUS_NO_MEMORY);
1637 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1639 talloc_destroy(ea_ctx);
1640 return(UNIXERROR(ERRDOS,ERRbadfile));
1643 /* Save the wildcard match and attribs we are using on this directory -
1644 needed as lanman2 assumes these are being saved between calls */
1646 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1647 dptr_close(&dptr_num);
1648 talloc_destroy(ea_ctx);
1649 return ERROR_NT(NT_STATUS_NO_MEMORY);
1652 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1654 /* We don't need to check for VOL here as this is returned by
1655 a different TRANS2 call. */
1657 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1658 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1659 dont_descend = True;
1662 space_remaining = max_data_bytes;
1663 out_of_space = False;
1665 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1666 BOOL got_exact_match = False;
1668 /* this is a heuristic to avoid seeking the dirptr except when
1669 absolutely necessary. It allows for a filename of about 40 chars */
1670 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1671 out_of_space = True;
1674 finished = !get_lanman2_dir_entry(conn,
1676 mask,dirtype,info_level,
1677 requires_resume_key,dont_descend,
1678 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1679 &last_entry_off, ea_list, ea_ctx);
1682 if (finished && out_of_space)
1685 if (!finished && !out_of_space)
1689 * As an optimisation if we know we aren't looking
1690 * for a wildcard name (ie. the name matches the wildcard exactly)
1691 * then we can finish on any (first) match.
1692 * This speeds up large directory searches. JRA.
1698 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1701 talloc_destroy(ea_ctx);
1703 /* Check if we can close the dirptr */
1704 if(close_after_first || (finished && close_if_end)) {
1705 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1706 dptr_close(&dptr_num);
1710 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1711 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1712 * the protocol level is less than NT1. Tested with smbclient. JRA.
1713 * This should fix the OS/2 client bug #2335.
1716 if(numentries == 0) {
1717 dptr_close(&dptr_num);
1718 if (Protocol < PROTOCOL_NT1) {
1719 return ERROR_DOS(ERRDOS,ERRnofiles);
1721 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1725 /* At this point pdata points to numentries directory entries. */
1727 /* Set up the return parameter block */
1728 SSVAL(params,0,dptr_num);
1729 SSVAL(params,2,numentries);
1730 SSVAL(params,4,finished);
1731 SSVAL(params,6,0); /* Never an EA error */
1732 SSVAL(params,8,last_entry_off);
1734 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1736 if ((! *directory) && dptr_path(dptr_num))
1737 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1739 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1740 smb_fn_name(CVAL(inbuf,smb_com)),
1741 mask, directory, dirtype, numentries ) );
1744 * Force a name mangle here to ensure that the
1745 * mask as an 8.3 name is top of the mangled cache.
1746 * The reasons for this are subtle. Don't remove
1747 * this code unless you know what you are doing
1748 * (see PR#13758). JRA.
1751 if(!mangle_is_8_3_wildcards( mask, False))
1752 mangle_map(mask, True, True, SNUM(conn));
1757 /****************************************************************************
1758 Reply to a TRANS2_FINDNEXT.
1759 ****************************************************************************/
1761 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1762 char **pparams, int total_params, char **ppdata, int total_data,
1763 unsigned int max_data_bytes)
1765 /* We must be careful here that we don't return more than the
1766 allowed number of data bytes. If this means returning fewer than
1767 maxentries then so be it. We assume that the redirector has
1768 enough room for the fixed number of parameter bytes it has
1770 char *params = *pparams;
1771 char *pdata = *ppdata;
1772 int dptr_num = SVAL(params,0);
1773 int maxentries = SVAL(params,2);
1774 uint16 info_level = SVAL(params,4);
1775 uint32 resume_key = IVAL(params,6);
1776 uint16 findnext_flags = SVAL(params,10);
1777 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1778 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1779 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1780 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1781 pstring resume_name;
1787 int i, last_entry_off=0;
1788 BOOL finished = False;
1789 BOOL dont_descend = False;
1790 BOOL out_of_space = False;
1791 int space_remaining;
1792 TALLOC_CTX *ea_ctx = NULL;
1793 struct ea_list *ea_list = NULL;
1794 NTSTATUS ntstatus = NT_STATUS_OK;
1796 if (total_params < 12) {
1797 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1800 *mask = *directory = *resume_name = 0;
1802 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1803 if (!NT_STATUS_IS_OK(ntstatus)) {
1804 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1805 complain (it thinks we're asking for the directory above the shared
1806 path or an invalid name). Catch this as the resume name is only compared, never used in
1807 a file access. JRA. */
1808 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1809 pstrcpy(resume_name, "..");
1810 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1811 pstrcpy(resume_name, ".");
1813 return ERROR_NT(ntstatus);
1817 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1818 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1819 resume_key = %d resume name = %s continue=%d level = %d\n",
1820 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1821 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1824 /* W2K3 seems to treat zero as 1. */
1828 switch (info_level) {
1829 case SMB_FIND_INFO_STANDARD:
1830 case SMB_FIND_EA_SIZE:
1831 case SMB_FIND_EA_LIST:
1832 case SMB_FIND_FILE_DIRECTORY_INFO:
1833 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1834 case SMB_FIND_FILE_NAMES_INFO:
1835 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1837 case SMB_FIND_FILE_UNIX:
1838 if (!lp_unix_extensions())
1839 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1842 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1845 if (info_level == SMB_FIND_EA_LIST) {
1848 if (total_data < 4) {
1849 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1852 ea_size = IVAL(pdata,0);
1853 if (ea_size != total_data) {
1854 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1855 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1856 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1859 if (!lp_ea_support(SNUM(conn))) {
1860 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1863 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1864 return ERROR_NT(NT_STATUS_NO_MEMORY);
1867 /* Pull out the list of names. */
1868 ea_list = read_ea_name_list(ea_ctx, pdata, ea_size);
1870 talloc_destroy(ea_ctx);
1871 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1875 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1877 talloc_destroy(ea_ctx);
1878 return ERROR_NT(NT_STATUS_NO_MEMORY);
1882 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1884 /* Realloc the params space */
1885 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1886 if( params == NULL ) {
1887 talloc_destroy(ea_ctx);
1888 return ERROR_NT(NT_STATUS_NO_MEMORY);
1893 /* Check that the dptr is valid */
1894 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
1895 talloc_destroy(ea_ctx);
1896 return ERROR_DOS(ERRDOS,ERRnofiles);
1899 string_set(&conn->dirpath,dptr_path(dptr_num));
1901 /* Get the wildcard mask from the dptr */
1902 if((p = dptr_wcard(dptr_num))== NULL) {
1903 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1904 talloc_destroy(ea_ctx);
1905 return ERROR_DOS(ERRDOS,ERRnofiles);
1909 pstrcpy(directory,conn->dirpath);
1911 /* Get the attr mask from the dptr */
1912 dirtype = dptr_attr(dptr_num);
1914 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
1915 dptr_num, mask, dirtype,
1917 dptr_TellDir(conn->dirptr)));
1919 /* We don't need to check for VOL here as this is returned by
1920 a different TRANS2 call. */
1922 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1923 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1924 dont_descend = True;
1927 space_remaining = max_data_bytes;
1928 out_of_space = False;
1931 * Seek to the correct position. We no longer use the resume key but
1932 * depend on the last file name instead.
1935 if(*resume_name && !continue_bit) {
1938 long current_pos = 0;
1940 * Remember, mangle_map is called by
1941 * get_lanman2_dir_entry(), so the resume name
1942 * could be mangled. Ensure we check the unmangled name.
1945 if (mangle_is_mangled(resume_name)) {
1946 mangle_check_cache(resume_name, sizeof(resume_name)-1);
1950 * Fix for NT redirector problem triggered by resume key indexes
1951 * changing between directory scans. We now return a resume key of 0
1952 * and instead look for the filename to continue from (also given
1953 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1954 * findfirst/findnext (as is usual) then the directory pointer
1955 * should already be at the correct place.
1958 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
1959 } /* end if resume_name && !continue_bit */
1961 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1962 BOOL got_exact_match = False;
1964 /* this is a heuristic to avoid seeking the dirptr except when
1965 absolutely necessary. It allows for a filename of about 40 chars */
1966 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1967 out_of_space = True;
1970 finished = !get_lanman2_dir_entry(conn,
1972 mask,dirtype,info_level,
1973 requires_resume_key,dont_descend,
1974 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1975 &last_entry_off, ea_list, ea_ctx);
1978 if (finished && out_of_space)
1981 if (!finished && !out_of_space)
1985 * As an optimisation if we know we aren't looking
1986 * for a wildcard name (ie. the name matches the wildcard exactly)
1987 * then we can finish on any (first) match.
1988 * This speeds up large directory searches. JRA.
1994 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1997 talloc_destroy(ea_ctx);
1999 /* Check if we can close the dirptr */
2000 if(close_after_request || (finished && close_if_end)) {
2001 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2002 dptr_close(&dptr_num); /* This frees up the saved mask */
2005 /* Set up the return parameter block */
2006 SSVAL(params,0,numentries);
2007 SSVAL(params,2,finished);
2008 SSVAL(params,4,0); /* Never an EA error */
2009 SSVAL(params,6,last_entry_off);
2011 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2013 if ((! *directory) && dptr_path(dptr_num))
2014 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2016 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2017 smb_fn_name(CVAL(inbuf,smb_com)),
2018 mask, directory, dirtype, numentries ) );
2023 /****************************************************************************
2024 Reply to a TRANS2_QFSINFO (query filesystem info).
2025 ****************************************************************************/
2027 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2028 char **pparams, int total_params, char **ppdata, int total_data,
2029 unsigned int max_data_bytes)
2031 char *pdata = *ppdata;
2032 char *params = *pparams;
2033 uint16 info_level = SVAL(params,0);
2036 char *vname = volume_label(SNUM(conn));
2037 int snum = SNUM(conn);
2038 char *fstype = lp_fstype(SNUM(conn));
2041 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2043 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2044 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2045 return ERROR_DOS(ERRSRV,ERRinvdevice);
2048 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2049 if ( pdata == NULL ) {
2050 return ERROR_NT(NT_STATUS_NO_MEMORY);
2054 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2056 switch (info_level) {
2057 case SMB_INFO_ALLOCATION:
2059 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2061 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2062 return(UNIXERROR(ERRHRD,ERRgeneral));
2065 block_size = lp_block_size(snum);
2066 if (bsize < block_size) {
2067 SMB_BIG_UINT factor = block_size/bsize;
2072 if (bsize > block_size) {
2073 SMB_BIG_UINT factor = bsize/block_size;
2078 bytes_per_sector = 512;
2079 sectors_per_unit = bsize/bytes_per_sector;
2081 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2082 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2083 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2085 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2086 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2087 SIVAL(pdata,l1_cUnit,dsize);
2088 SIVAL(pdata,l1_cUnitAvail,dfree);
2089 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2093 case SMB_INFO_VOLUME:
2094 /* Return volume name */
2096 * Add volume serial number - hash of a combination of
2097 * the called hostname and the service name.
2099 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2100 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
2101 SCVAL(pdata,l2_vol_cch,len);
2102 data_len = l2_vol_szVolLabel + len;
2103 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2104 (unsigned)st.st_ctime, len, vname));
2107 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2108 case SMB_FS_ATTRIBUTE_INFORMATION:
2111 #if defined(HAVE_SYS_QUOTAS)
2112 quota_flag = FILE_VOLUME_QUOTAS;
2115 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2116 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2117 quota_flag); /* FS ATTRIBUTES */
2119 SIVAL(pdata,4,255); /* Max filename component length */
2120 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2121 and will think we can't do long filenames */
2122 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2124 data_len = 12 + len;
2127 case SMB_QUERY_FS_LABEL_INFO:
2128 case SMB_FS_LABEL_INFORMATION:
2129 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2134 case SMB_QUERY_FS_VOLUME_INFO:
2135 case SMB_FS_VOLUME_INFORMATION:
2138 * Add volume serial number - hash of a combination of
2139 * the called hostname and the service name.
2141 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2142 (str_checksum(get_local_machine_name())<<16));
2144 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2145 SIVAL(pdata,12,len);
2147 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2148 (int)strlen(vname),vname, lp_servicename(snum)));
2151 case SMB_QUERY_FS_SIZE_INFO:
2152 case SMB_FS_SIZE_INFORMATION:
2154 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2156 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2157 return(UNIXERROR(ERRHRD,ERRgeneral));
2159 block_size = lp_block_size(snum);
2160 if (bsize < block_size) {
2161 SMB_BIG_UINT factor = block_size/bsize;
2166 if (bsize > block_size) {
2167 SMB_BIG_UINT factor = bsize/block_size;
2172 bytes_per_sector = 512;
2173 sectors_per_unit = bsize/bytes_per_sector;
2174 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2175 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2176 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2177 SBIG_UINT(pdata,0,dsize);
2178 SBIG_UINT(pdata,8,dfree);
2179 SIVAL(pdata,16,sectors_per_unit);
2180 SIVAL(pdata,20,bytes_per_sector);
2184 case SMB_FS_FULL_SIZE_INFORMATION:
2186 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2188 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2189 return(UNIXERROR(ERRHRD,ERRgeneral));
2191 block_size = lp_block_size(snum);
2192 if (bsize < block_size) {
2193 SMB_BIG_UINT factor = block_size/bsize;
2198 if (bsize > block_size) {
2199 SMB_BIG_UINT factor = bsize/block_size;
2204 bytes_per_sector = 512;
2205 sectors_per_unit = bsize/bytes_per_sector;
2206 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2207 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2208 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2209 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2210 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2211 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2212 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2213 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2217 case SMB_QUERY_FS_DEVICE_INFO:
2218 case SMB_FS_DEVICE_INFORMATION:
2220 SIVAL(pdata,0,0); /* dev type */
2221 SIVAL(pdata,4,0); /* characteristics */
2224 #ifdef HAVE_SYS_QUOTAS
2225 case SMB_FS_QUOTA_INFORMATION:
2227 * what we have to send --metze:
2229 * Unknown1: 24 NULL bytes
2230 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2231 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2232 * Quota Flags: 2 byte :
2233 * Unknown3: 6 NULL bytes
2237 * details for Quota Flags:
2239 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2240 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2241 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2242 * 0x0001 Enable Quotas: enable quota for this fs
2246 /* we need to fake up a fsp here,
2247 * because its not send in this call
2250 SMB_NTQUOTA_STRUCT quotas;
2253 ZERO_STRUCT(quotas);
2260 if (current_user.uid != 0) {
2261 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2262 lp_servicename(SNUM(conn)),conn->user));
2263 return ERROR_DOS(ERRDOS,ERRnoaccess);
2266 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2267 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2268 return ERROR_DOS(ERRSRV,ERRerror);
2273 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2275 /* Unknown1 24 NULL bytes*/
2276 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2277 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2278 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2280 /* Default Soft Quota 8 bytes */
2281 SBIG_UINT(pdata,24,quotas.softlim);
2283 /* Default Hard Quota 8 bytes */
2284 SBIG_UINT(pdata,32,quotas.hardlim);
2286 /* Quota flag 2 bytes */
2287 SSVAL(pdata,40,quotas.qflags);
2289 /* Unknown3 6 NULL bytes */
2295 #endif /* HAVE_SYS_QUOTAS */
2296 case SMB_FS_OBJECTID_INFORMATION:
2301 * Query the version and capabilities of the CIFS UNIX extensions
2305 case SMB_QUERY_CIFS_UNIX_INFO:
2306 if (!lp_unix_extensions())
2307 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2309 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2310 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2311 SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
2314 case SMB_MAC_QUERY_FS_INFO:
2316 * Thursby MAC extension... ONLY on NTFS filesystems
2317 * once we do streams then we don't need this
2319 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2321 SIVAL(pdata,84,0x100); /* Don't support mac... */
2326 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2330 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2332 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2337 #ifdef HAVE_SYS_QUOTAS
2338 /****************************************************************************
2339 Reply to a TRANS2_SETFSINFO (set filesystem info).
2340 ****************************************************************************/
2342 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2343 char **pparams, int total_params, char **ppdata, int total_data,
2344 unsigned int max_data_bytes)
2346 char *pdata = *ppdata;
2347 char *params = *pparams;
2348 files_struct *fsp = NULL;
2351 SMB_NTQUOTA_STRUCT quotas;
2353 ZERO_STRUCT(quotas);
2355 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2358 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2359 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2360 lp_servicename(SNUM(conn)),conn->user));
2361 return ERROR_DOS(ERRSRV,ERRaccess);
2365 if (total_params < 4) {
2366 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2368 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2371 fsp = file_fsp(params,0);
2373 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2374 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2375 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2378 info_level = SVAL(params,2);
2380 switch(info_level) {
2381 case SMB_FS_QUOTA_INFORMATION:
2382 /* note: normaly there're 48 bytes,
2383 * but we didn't use the last 6 bytes for now
2386 if (total_data < 42) {
2387 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2389 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2392 /* unknown_1 24 NULL bytes in pdata*/
2394 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2395 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2396 #ifdef LARGE_SMB_OFF_T
2397 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2398 #else /* LARGE_SMB_OFF_T */
2399 if ((IVAL(pdata,28) != 0)&&
2400 ((quotas.softlim != 0xFFFFFFFF)||
2401 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2402 /* more than 32 bits? */
2403 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2405 #endif /* LARGE_SMB_OFF_T */
2407 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2408 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2409 #ifdef LARGE_SMB_OFF_T
2410 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2411 #else /* LARGE_SMB_OFF_T */
2412 if ((IVAL(pdata,36) != 0)&&
2413 ((quotas.hardlim != 0xFFFFFFFF)||
2414 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2415 /* more than 32 bits? */
2416 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2418 #endif /* LARGE_SMB_OFF_T */
2420 /* quota_flags 2 bytes **/
2421 quotas.qflags = SVAL(pdata,40);
2423 /* unknown_2 6 NULL bytes follow*/
2425 /* now set the quotas */
2426 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2427 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2428 return ERROR_DOS(ERRSRV,ERRerror);
2433 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2435 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2440 * sending this reply works fine,
2441 * but I'm not sure it's the same
2442 * like windows do...
2445 outsize = set_message(outbuf,10,0,True);
2449 #endif /* HAVE_SYS_QUOTAS */
2451 /****************************************************************************
2452 Utility function to set bad path error.
2453 ****************************************************************************/
2455 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2457 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2458 err, (int)bad_path ));
2462 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2464 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2467 return UNIXERROR(def_class,def_code);
2470 #if defined(HAVE_POSIX_ACLS)
2471 /****************************************************************************
2472 Utility function to count the number of entries in a POSIX acl.
2473 ****************************************************************************/
2475 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2477 unsigned int ace_count = 0;
2478 int entry_id = SMB_ACL_FIRST_ENTRY;
2479 SMB_ACL_ENTRY_T entry;
2481 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2483 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2484 entry_id = SMB_ACL_NEXT_ENTRY;
2491 /****************************************************************************
2492 Utility function to marshall a POSIX acl into wire format.
2493 ****************************************************************************/
2495 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2497 int entry_id = SMB_ACL_FIRST_ENTRY;
2498 SMB_ACL_ENTRY_T entry;
2500 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2501 SMB_ACL_TAG_T tagtype;
2502 SMB_ACL_PERMSET_T permset;
2503 unsigned char perms = 0;
2504 unsigned int own_grp;
2507 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2508 entry_id = SMB_ACL_NEXT_ENTRY;
2511 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2512 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2516 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2517 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2521 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2522 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2523 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2525 SCVAL(pdata,1,perms);
2528 case SMB_ACL_USER_OBJ:
2529 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2530 own_grp = (unsigned int)pst->st_uid;
2531 SIVAL(pdata,2,own_grp);
2536 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2538 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2540 own_grp = (unsigned int)*puid;
2541 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2542 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2543 SIVAL(pdata,2,own_grp);
2547 case SMB_ACL_GROUP_OBJ:
2548 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2549 own_grp = (unsigned int)pst->st_gid;
2550 SIVAL(pdata,2,own_grp);
2555 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2557 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2559 own_grp = (unsigned int)*pgid;
2560 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2561 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2562 SIVAL(pdata,2,own_grp);
2567 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2568 SIVAL(pdata,2,0xFFFFFFFF);
2569 SIVAL(pdata,6,0xFFFFFFFF);
2572 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2573 SIVAL(pdata,2,0xFFFFFFFF);
2574 SIVAL(pdata,6,0xFFFFFFFF);
2577 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2580 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2587 /****************************************************************************
2588 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2589 file name or file id).
2590 ****************************************************************************/
2592 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2593 char **pparams, int total_params, char **ppdata, int total_data,
2594 unsigned int max_data_bytes)
2596 char *params = *pparams;
2597 char *pdata = *ppdata;
2598 uint16 tran_call = SVAL(inbuf, smb_setup0);
2601 SMB_OFF_T file_size=0;
2602 SMB_BIG_UINT allocation_size=0;
2603 unsigned int data_size = 0;
2604 unsigned int param_size = 2;
2605 SMB_STRUCT_STAT sbuf;
2606 pstring fname, dos_fname;
2611 BOOL bad_path = False;
2612 BOOL delete_pending = False;
2615 files_struct *fsp = NULL;
2616 TALLOC_CTX *ea_ctx = NULL;
2617 struct ea_list *ea_list = NULL;
2618 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2621 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2625 if (tran_call == TRANSACT2_QFILEINFO) {
2626 if (total_params < 4) {
2627 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2630 fsp = file_fsp(params,0);
2631 info_level = SVAL(params,2);
2633 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2635 if(fsp && (fsp->fake_file_handle)) {
2637 * This is actually for the QUOTA_FAKE_FILE --metze
2640 pstrcpy(fname, fsp->fsp_name);
2641 /* We know this name is ok, it's already passed the checks. */
2643 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2645 * This is actually a QFILEINFO on a directory
2646 * handle (returned from an NT SMB). NT5.0 seems
2647 * to do this call. JRA.
2649 /* We know this name is ok, it's already passed the checks. */
2650 pstrcpy(fname, fsp->fsp_name);
2652 if (INFO_LEVEL_IS_UNIX(info_level)) {
2653 /* Always do lstat for UNIX calls. */
2654 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2655 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2656 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2658 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2659 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2660 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2663 delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2666 * Original code - this is an open file.
2668 CHECK_FSP(fsp,conn);
2670 pstrcpy(fname, fsp->fsp_name);
2671 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2672 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2673 return(UNIXERROR(ERRDOS,ERRbadfid));
2675 pos = fsp->position_information;
2676 delete_pending = fsp->delete_on_close;
2677 desired_access = fsp->desired_access;
2680 NTSTATUS status = NT_STATUS_OK;
2683 if (total_params < 6) {
2684 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2687 info_level = SVAL(params,0);
2689 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2691 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2692 if (!NT_STATUS_IS_OK(status)) {
2693 return ERROR_NT(status);
2696 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2698 unix_convert(fname,conn,0,&bad_path,&sbuf);
2700 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2702 if (!check_name(fname,conn)) {
2703 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2704 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2707 if (INFO_LEVEL_IS_UNIX(info_level)) {
2708 /* Always do lstat for UNIX calls. */
2709 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2710 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2711 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2713 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2714 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2715 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2719 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2720 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2722 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2723 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2725 p = strrchr_m(fname,'/');
2731 mode = dos_mode(conn,fname,&sbuf);
2733 mode = FILE_ATTRIBUTE_NORMAL;
2735 fullpathname = fname;
2736 file_size = get_file_size(sbuf);
2737 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2739 /* This is necessary, as otherwise the desktop.ini file in
2740 * this folder is ignored */
2741 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2745 /* Pull any EA list from the data portion. */
2746 if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2749 if (total_data < 4) {
2750 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2752 ea_size = IVAL(pdata,0);
2754 if (total_data > 0 && ea_size != total_data) {
2755 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2756 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2757 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2760 if (!lp_ea_support(SNUM(conn))) {
2761 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2764 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2765 return ERROR_NT(NT_STATUS_NO_MEMORY);
2768 /* Pull out the list of names. */
2769 ea_list = read_ea_name_list(ea_ctx, pdata, ea_size);
2771 talloc_destroy(ea_ctx);
2772 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2776 params = SMB_REALLOC(*pparams,2);
2777 if (params == NULL) {
2778 talloc_destroy(ea_ctx);
2779 return ERROR_NT(NT_STATUS_NO_MEMORY);
2782 memset((char *)params,'\0',2);
2783 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2784 pdata = SMB_REALLOC(*ppdata, data_size);
2785 if ( pdata == NULL ) {
2786 talloc_destroy(ea_ctx);
2787 return ERROR_NT(NT_STATUS_NO_MEMORY);
2791 memset((char *)pdata,'\0',data_size);
2793 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2796 if (fsp->pending_modtime) {
2797 /* the pending modtime overrides the current modtime */
2798 sbuf.st_mtime = fsp->pending_modtime;
2801 /* Do we have this path open ? */
2802 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2803 if (fsp1 && fsp1->pending_modtime) {
2804 /* the pending modtime overrides the current modtime */
2805 sbuf.st_mtime = fsp1->pending_modtime;
2809 if (lp_dos_filetime_resolution(SNUM(conn))) {
2811 sbuf.st_atime &= ~1;
2812 sbuf.st_ctime &= ~1;
2813 sbuf.st_mtime &= ~1;
2816 /* NT expects the name to be in an exact form of the *full*
2817 filename. See the trans2 torture test */
2818 if (strequal(base_name,".")) {
2819 pstrcpy(dos_fname, "\\");
2821 pstr_sprintf(dos_fname, "\\%s", fname);
2822 string_replace(dos_fname, '/', '\\');
2825 switch (info_level) {
2826 case SMB_INFO_STANDARD:
2827 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2829 put_dos_date2(pdata,l1_fdateCreation,c_time);
2830 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2831 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2832 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2833 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2834 SSVAL(pdata,l1_attrFile,mode);
2837 case SMB_INFO_QUERY_EA_SIZE:
2839 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2840 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2842 put_dos_date2(pdata,l1_fdateCreation,c_time);
2843 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2844 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2845 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2846 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2847 SSVAL(pdata,l1_attrFile,mode);
2848 SIVAL(pdata,l1_attrFile+2,ea_size);
2852 case SMB_INFO_IS_NAME_VALID:
2853 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2854 if (tran_call == TRANSACT2_QFILEINFO) {
2855 /* os/2 needs this ? really ?*/
2856 return ERROR_DOS(ERRDOS,ERRbadfunc);
2862 case SMB_INFO_QUERY_EAS_FROM_LIST:
2864 size_t total_ea_len = 0;
2865 struct ea_list *ea_file_list = NULL;
2867 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2869 ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2870 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
2872 if (!ea_list || (total_ea_len > data_size)) {
2873 talloc_destroy(ea_ctx);
2878 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
2879 talloc_destroy(ea_ctx);
2883 case SMB_INFO_QUERY_ALL_EAS:
2885 /* We have data_size bytes to put EA's into. */
2886 size_t total_ea_len = 0;
2888 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2890 ea_ctx = talloc_init("ea_ctx");
2892 return ERROR_NT(NT_STATUS_NO_MEMORY);
2895 ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2896 if (!ea_list || (total_ea_len > data_size)) {
2897 talloc_destroy(ea_ctx);
2902 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
2903 talloc_destroy(ea_ctx);
2907 case SMB_FILE_BASIC_INFORMATION:
2908 case SMB_QUERY_FILE_BASIC_INFO:
2910 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2911 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2912 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2914 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2918 put_long_date(pdata,c_time);
2919 put_long_date(pdata+8,sbuf.st_atime);
2920 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2921 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2922 SIVAL(pdata,32,mode);
2924 DEBUG(5,("SMB_QFBI - "));
2926 time_t create_time = c_time;
2927 DEBUG(5,("create: %s ", ctime(&create_time)));
2929 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2930 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2931 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2932 DEBUG(5,("mode: %x\n", mode));
2936 case SMB_FILE_STANDARD_INFORMATION:
2937 case SMB_QUERY_FILE_STANDARD_INFO:
2939 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2941 SOFF_T(pdata,0,allocation_size);
2942 SOFF_T(pdata,8,file_size);
2943 if (delete_pending & sbuf.st_nlink)
2944 SIVAL(pdata,16,sbuf.st_nlink - 1);
2946 SIVAL(pdata,16,sbuf.st_nlink);
2948 SCVAL(pdata,21,(mode&aDIR)?1:0);
2951 case SMB_FILE_EA_INFORMATION:
2952 case SMB_QUERY_FILE_EA_INFO:
2954 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2955 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2957 SIVAL(pdata,0,ea_size);
2961 /* Get the 8.3 name - used if NT SMB was negotiated. */
2962 case SMB_QUERY_FILE_ALT_NAME_INFO:
2963 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2967 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2968 pstrcpy(short_name,base_name);
2969 /* Mangle if not already 8.3 */
2970 if(!mangle_is_8_3(short_name, True)) {
2971 mangle_map(short_name,True,True,SNUM(conn));
2973 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2974 data_size = 4 + len;
2979 case SMB_QUERY_FILE_NAME_INFO:
2981 this must be *exactly* right for ACLs on mapped drives to work
2983 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2984 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2985 data_size = 4 + len;
2989 case SMB_FILE_ALLOCATION_INFORMATION:
2990 case SMB_QUERY_FILE_ALLOCATION_INFO:
2991 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2993 SOFF_T(pdata,0,allocation_size);
2996 case SMB_FILE_END_OF_FILE_INFORMATION:
2997 case SMB_QUERY_FILE_END_OF_FILEINFO:
2998 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3000 SOFF_T(pdata,0,file_size);
3003 case SMB_QUERY_FILE_ALL_INFO:
3004 case SMB_FILE_ALL_INFORMATION:
3006 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3007 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3008 put_long_date(pdata,c_time);
3009 put_long_date(pdata+8,sbuf.st_atime);
3010 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3011 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3012 SIVAL(pdata,32,mode);
3014 SOFF_T(pdata,0,allocation_size);
3015 SOFF_T(pdata,8,file_size);
3016 if (delete_pending && sbuf.st_nlink)
3017 SIVAL(pdata,16,sbuf.st_nlink - 1);
3019 SIVAL(pdata,16,sbuf.st_nlink);
3020 SCVAL(pdata,20,delete_pending);
3021 SCVAL(pdata,21,(mode&aDIR)?1:0);
3023 SIVAL(pdata,0,ea_size);
3024 pdata += 4; /* EA info */
3025 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3028 data_size = PTR_DIFF(pdata,(*ppdata));
3031 case SMB_FILE_INTERNAL_INFORMATION:
3032 /* This should be an index number - looks like
3035 I think this causes us to fail the IFSKIT
3036 BasicFileInformationTest. -tpot */
3038 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3039 SIVAL(pdata,0,sbuf.st_dev);
3040 SIVAL(pdata,4,sbuf.st_ino);
3044 case SMB_FILE_ACCESS_INFORMATION:
3045 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3046 SIVAL(pdata,0,desired_access);
3050 case SMB_FILE_NAME_INFORMATION:
3051 /* Pathname with leading '\'. */
3054 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
3055 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3056 SIVAL(pdata,0,byte_len);
3057 data_size = 4 + byte_len;
3061 case SMB_FILE_DISPOSITION_INFORMATION:
3062 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3064 SCVAL(pdata,0,delete_pending);
3067 case SMB_FILE_POSITION_INFORMATION:
3068 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3070 SOFF_T(pdata,0,pos);
3073 case SMB_FILE_MODE_INFORMATION:
3074 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3075 SIVAL(pdata,0,mode);
3079 case SMB_FILE_ALIGNMENT_INFORMATION:
3080 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3081 SIVAL(pdata,0,0); /* No alignment needed. */
3087 * NT4 server just returns "invalid query" to this - if we try to answer
3088 * it then NTws gets a BSOD! (tridge).
3089 * W2K seems to want this. JRA.
3091 case SMB_QUERY_FILE_STREAM_INFO:
3093 case SMB_FILE_STREAM_INFORMATION:
3094 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3098 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
3099 SIVAL(pdata,0,0); /* ??? */
3100 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3101 SOFF_T(pdata,8,file_size);
3102 SIVAL(pdata,16,allocation_size);
3103 SIVAL(pdata,20,0); /* ??? */
3104 data_size = 24 + byte_len;
3108 case SMB_QUERY_COMPRESSION_INFO:
3109 case SMB_FILE_COMPRESSION_INFORMATION:
3110 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3111 SOFF_T(pdata,0,file_size);
3112 SIVAL(pdata,8,0); /* ??? */
3113 SIVAL(pdata,12,0); /* ??? */
3117 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3118 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3119 put_long_date(pdata,c_time);
3120 put_long_date(pdata+8,sbuf.st_atime);
3121 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3122 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3123 SIVAL(pdata,32,allocation_size);
3124 SOFF_T(pdata,40,file_size);
3125 SIVAL(pdata,48,mode);
3126 SIVAL(pdata,52,0); /* ??? */
3130 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3131 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3132 SIVAL(pdata,0,mode);
3138 * CIFS UNIX Extensions.
3141 case SMB_QUERY_FILE_UNIX_BASIC:
3143 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3144 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3146 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
3149 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3152 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
3153 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
3154 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
3157 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
3161 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
3165 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3168 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
3172 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
3176 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
3179 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
3183 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
3186 data_size = PTR_DIFF(pdata,(*ppdata));
3190 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3192 for (i=0; i<100; i++)
3193 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3199 case SMB_QUERY_FILE_UNIX_LINK:
3203 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3205 if(!S_ISLNK(sbuf.st_mode))
3206 return(UNIXERROR(ERRSRV,ERRbadlink));
3208 return(UNIXERROR(ERRDOS,ERRbadlink));
3210 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3212 return(UNIXERROR(ERRDOS,ERRnoaccess));
3214 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3216 data_size = PTR_DIFF(pdata,(*ppdata));
3221 #if defined(HAVE_POSIX_ACLS)
3222 case SMB_QUERY_POSIX_ACL:
3224 SMB_ACL_T file_acl = NULL;
3225 SMB_ACL_T def_acl = NULL;
3226 uint16 num_file_acls = 0;
3227 uint16 num_def_acls = 0;
3229 if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
3230 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
3232 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3235 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3236 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3238 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3241 if (S_ISDIR(sbuf.st_mode)) {
3242 if (fsp && fsp->is_directory) {
3243 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3245 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3247 def_acl = free_empty_sys_acl(conn, def_acl);
3250 num_file_acls = count_acl_entries(conn, file_acl);
3251 num_def_acls = count_acl_entries(conn, def_acl);
3253 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3254 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3256 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3257 SMB_POSIX_ACL_HEADER_SIZE) ));
3259 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3262 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3264 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3267 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3268 SSVAL(pdata,2,num_file_acls);
3269 SSVAL(pdata,4,num_def_acls);
3270 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3272 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3275 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3277 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3279 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3281 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3284 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3286 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3290 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3293 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3295 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3301 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3304 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3309 /****************************************************************************
3310 Deal with the internal needs of setting the delete on close flag. Note that
3311 as the tdb locking is recursive, it is safe to call this from within
3312 open_file_shared. JRA.
3313 ****************************************************************************/
3315 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
3317 if (delete_on_close) {
3319 * Only allow delete on close for writable files.
3322 if (!lp_delete_readonly(SNUM(fsp->conn))) {
3323 if (dosmode & aRONLY) {
3324 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
3326 return NT_STATUS_CANNOT_DELETE;
3331 * Only allow delete on close for writable shares.
3334 if (!CAN_WRITE(fsp->conn)) {
3335 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
3337 return NT_STATUS_ACCESS_DENIED;
3341 * Only allow delete on close for files/directories opened with delete intent.
3344 if (!(fsp->desired_access & DELETE_ACCESS)) {
3345 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
3347 return NT_STATUS_ACCESS_DENIED;
3351 if(fsp->is_directory) {
3352 fsp->directory_delete_on_close = delete_on_close;
3353 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3354 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3356 fsp->delete_on_close = delete_on_close;
3357 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3358 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3361 return NT_STATUS_OK;
3364 /****************************************************************************
3365 Sets the delete on close flag over all share modes on this file.
3366 Modify the share mode entry for all files open
3367 on this device and inode to tell other smbds we have
3368 changed the delete on close flag. This will be noticed
3369 in the close code, the last closer will delete the file
3371 ****************************************************************************/
3373 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3375 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3376 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3378 if (fsp->is_directory || fsp->is_stat)
3379 return NT_STATUS_OK;
3381 if (lock_share_entry_fsp(fsp) == False)
3382 return NT_STATUS_ACCESS_DENIED;
3384 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3385 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3387 unlock_share_entry_fsp(fsp);
3388 return NT_STATUS_ACCESS_DENIED;
3391 unlock_share_entry_fsp(fsp);
3392 return NT_STATUS_OK;
3395 /****************************************************************************
3396 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3398 ****************************************************************************/
3400 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3402 BOOL bad_path_oldname = False;
3403 BOOL bad_path_newname = False;
3404 SMB_STRUCT_STAT sbuf1, sbuf2;
3405 pstring last_component_oldname;
3406 pstring last_component_newname;
3407 NTSTATUS status = NT_STATUS_OK;
3413 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3414 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3417 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3418 if (bad_path_oldname) {
3419 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3422 /* Quick check for "." and ".." */
3423 if (last_component_oldname[0] == '.') {
3424 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3425 return NT_STATUS_OBJECT_NAME_INVALID;
3429 /* source must already exist. */
3430 if (!VALID_STAT(sbuf1)) {
3431 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3434 if (!check_name(oldname,conn)) {
3435 return NT_STATUS_ACCESS_DENIED;
3438 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3439 if (bad_path_newname) {
3440 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3443 /* Quick check for "." and ".." */
3444 if (last_component_newname[0] == '.') {
3445 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3446 return NT_STATUS_OBJECT_NAME_INVALID;
3450 /* Disallow if newname already exists. */
3451 if (VALID_STAT(sbuf2)) {
3452 return NT_STATUS_OBJECT_NAME_COLLISION;
3455 if (!check_name(newname,conn)) {
3456 return NT_STATUS_ACCESS_DENIED;
3459 /* No links from a directory. */
3460 if (S_ISDIR(sbuf1.st_mode)) {
3461 return NT_STATUS_FILE_IS_A_DIRECTORY;
3464 /* Ensure this is within the share. */
3465 if (!reduce_name(conn, oldname) != 0)
3466 return NT_STATUS_ACCESS_DENIED;
3468 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3470 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3471 status = map_nt_error_from_unix(errno);
3472 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3473 nt_errstr(status), newname, oldname));
3479 /****************************************************************************
3480 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3481 ****************************************************************************/
3483 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3484 char **pparams, int total_params, char **ppdata, int total_data,
3485 unsigned int max_data_bytes)
3487 char *params = *pparams;
3488 char *pdata = *ppdata;
3489 uint16 tran_call = SVAL(inbuf, smb_setup0);
3494 SMB_STRUCT_STAT sbuf;
3497 BOOL bad_path = False;
3498 files_struct *fsp = NULL;
3499 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3500 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3501 mode_t unixmode = 0;
3502 NTSTATUS status = NT_STATUS_OK;
3505 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3509 if (tran_call == TRANSACT2_SETFILEINFO) {
3510 if (total_params < 4) {
3511 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3514 fsp = file_fsp(params,0);
3515 info_level = SVAL(params,2);
3517 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3519 * This is actually a SETFILEINFO on a directory
3520 * handle (returned from an NT SMB). NT5.0 seems
3521 * to do this call. JRA.
3523 pstrcpy(fname, fsp->fsp_name);
3524 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3525 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3526 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3528 } else if (fsp && fsp->print_file) {
3530 * Doing a DELETE_ON_CLOSE should cancel a print job.
3532 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3533 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3535 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3538 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3541 return (UNIXERROR(ERRDOS,ERRbadpath));
3544 * Original code - this is an open file.
3546 CHECK_FSP(fsp,conn);
3548 pstrcpy(fname, fsp->fsp_name);
3551 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3552 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3553 return(UNIXERROR(ERRDOS,ERRbadfid));
3558 if (total_params < 6) {
3559 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3562 info_level = SVAL(params,0);
3563 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3564 if (!NT_STATUS_IS_OK(status)) {
3565 return ERROR_NT(status);
3567 unix_convert(fname,conn,0,&bad_path,&sbuf);
3569 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3573 * For CIFS UNIX extensions the target name may not exist.
3576 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3577 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3578 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3581 if(!check_name(fname, conn)) {
3582 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3587 if (!CAN_WRITE(conn))
3588 return ERROR_DOS(ERRSRV,ERRaccess);
3590 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3591 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3593 if (VALID_STAT(sbuf))
3594 unixmode = sbuf.st_mode;
3596 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3597 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3599 /* Realloc the parameter size */
3600 params = SMB_REALLOC(*pparams,2);
3601 if(params == NULL) {
3602 return ERROR_NT(NT_STATUS_NO_MEMORY);
3608 if (fsp && fsp->pending_modtime) {
3609 /* the pending modtime overrides the current modtime */
3610 sbuf.st_mtime = fsp->pending_modtime;
3613 size = get_file_size(sbuf);
3614 tvs.modtime = sbuf.st_mtime;
3615 tvs.actime = sbuf.st_atime;
3616 dosmode = dos_mode(conn,fname,&sbuf);
3617 unixmode = sbuf.st_mode;
3619 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3620 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3622 switch (info_level) {
3623 case SMB_INFO_STANDARD:
3625 if (total_data < 12) {
3626 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3630 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3632 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3636 case SMB_INFO_SET_EA:
3638 struct ea_list *ea_list = NULL;
3639 TALLOC_CTX *ctx = talloc_init("SMB_INFO_SET_EA");
3641 return ERROR_NT(NT_STATUS_NO_MEMORY);
3643 ea_list = read_ea_list(ctx, pdata, total_data);
3645 talloc_destroy(ctx);
3646 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3648 status = set_ea(conn, fsp, fname, ea_list);
3649 talloc_destroy(ctx);
3651 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) {
3652 return ERROR_NT(status);
3658 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3659 /* XXXX um, i don't think this is right.
3660 it's also not in the cifs6.txt spec.
3662 case SMB_INFO_QUERY_EAS_FROM_LIST:
3663 if (total_data < 28)
3664 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3666 tvs.actime = make_unix_date2(pdata+8);
3667 tvs.modtime = make_unix_date2(pdata+12);
3668 size = IVAL(pdata,16);
3669 dosmode = IVAL(pdata,24);
3672 /* XXXX nor this. not in cifs6.txt, either. */
3673 case SMB_INFO_QUERY_ALL_EAS:
3674 if (total_data < 28)
3675 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3677 tvs.actime = make_unix_date2(pdata+8);
3678 tvs.modtime = make_unix_date2(pdata+12);
3679 size = IVAL(pdata,16);
3680 dosmode = IVAL(pdata,24);
3684 case SMB_SET_FILE_BASIC_INFO:
3685 case SMB_FILE_BASIC_INFORMATION:
3687 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3689 time_t changed_time;
3691 if (total_data < 36) {
3692 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3695 /* Ignore create time at offset pdata. */
3698 tvs.actime = interpret_long_date(pdata+8);
3700 write_time = interpret_long_date(pdata+16);
3701 changed_time = interpret_long_date(pdata+24);
3703 tvs.modtime = MIN(write_time, changed_time);
3705 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3706 tvs.modtime = write_time;
3708 /* Prefer a defined time to an undefined one. */
3709 if (null_mtime(tvs.modtime)) {
3710 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3714 dosmode = IVAL(pdata,32);
3718 case SMB_FILE_ALLOCATION_INFORMATION:
3719 case SMB_SET_FILE_ALLOCATION_INFO:
3722 SMB_BIG_UINT allocation_size;
3724 if (total_data < 8) {
3725 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3728 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3729 #ifdef LARGE_SMB_OFF_T
3730 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3731 #else /* LARGE_SMB_OFF_T */
3732 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3733 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3734 #endif /* LARGE_SMB_OFF_T */
3735 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3736 fname, (double)allocation_size ));
3738 if (allocation_size) {
3739 allocation_size = smb_roundup(conn, allocation_size);
3742 if(allocation_size != get_file_size(sbuf)) {
3743 SMB_STRUCT_STAT new_sbuf;
3745 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3746 fname, (double)allocation_size ));
3749 files_struct *new_fsp = NULL;
3750 int access_mode = 0;
3753 if(global_oplock_break) {
3754 /* Queue this file modify as we are the process of an oplock break. */
3756 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3757 DEBUGADD(2,( "in oplock break state.\n"));
3759 push_oplock_pending_smb_message(inbuf, length);
3763 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3764 SET_OPEN_MODE(DOS_OPEN_RDWR),
3765 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3766 FILE_ATTRIBUTE_NORMAL,
3767 INTERNAL_OPEN_ONLY, &access_mode, &action);
3769 if (new_fsp == NULL)
3770 return(UNIXERROR(ERRDOS,ERRbadpath));
3771 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3772 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3773 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3774 new_fsp->fnum, strerror(errno)));
3777 close_file(new_fsp,True);
3779 ret = vfs_allocate_file_space(fsp, allocation_size);
3780 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3781 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3782 fsp->fnum, strerror(errno)));
3787 return ERROR_NT(NT_STATUS_DISK_FULL);
3789 /* Allocate can truncate size... */
3790 size = get_file_size(new_sbuf);
3796 case SMB_FILE_END_OF_FILE_INFORMATION:
3797 case SMB_SET_FILE_END_OF_FILE_INFO:
3799 if (total_data < 8) {
3800 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3803 size = IVAL(pdata,0);
3804 #ifdef LARGE_SMB_OFF_T
3805 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3806 #else /* LARGE_SMB_OFF_T */
3807 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3808 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3809 #endif /* LARGE_SMB_OFF_T */
3810 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3814 case SMB_FILE_DISPOSITION_INFORMATION:
3815 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3817 BOOL delete_on_close;
3819 if (total_data < 1) {
3820 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3823 delete_on_close = (CVAL(pdata,0) ? True : False);
3825 /* Just ignore this set on a path. */
3826 if (tran_call != TRANSACT2_SETFILEINFO)
3830 return(UNIXERROR(ERRDOS,ERRbadfid));
3832 status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3834 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3835 return ERROR_NT(status);
3837 /* The set is across all open files on this dev/inode pair. */
3838 status =set_delete_on_close_over_all(fsp, delete_on_close);
3839 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3840 return ERROR_NT(status);
3845 case SMB_FILE_POSITION_INFORMATION:
3847 SMB_BIG_UINT position_information;
3849 if (total_data < 8) {
3850 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3853 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3854 #ifdef LARGE_SMB_OFF_T
3855 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3856 #else /* LARGE_SMB_OFF_T */
3857 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3858 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3859 #endif /* LARGE_SMB_OFF_T */
3860 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3861 fname, (double)position_information ));
3863 fsp->position_information = position_information;
3867 /* From tridge Samba4 :
3868 * MODE_INFORMATION in setfileinfo (I have no
3869 * idea what "mode information" on a file is - it takes a value of 0,
3870 * 2, 4 or 6. What could it be?).
3873 case SMB_FILE_MODE_INFORMATION:
3877 if (total_data < 4) {
3878 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3880 mode = IVAL(pdata,0);
3881 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
3882 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3888 * CIFS UNIX extensions.
3891 case SMB_SET_FILE_UNIX_BASIC:
3893 uint32 raw_unixmode;
3895 if (total_data < 100) {
3896 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3899 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3900 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3901 size=IVAL(pdata,0); /* first 8 Bytes are size */
3902 #ifdef LARGE_SMB_OFF_T
3903 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3904 #else /* LARGE_SMB_OFF_T */
3905 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3906 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3907 #endif /* LARGE_SMB_OFF_T */
3909 pdata+=24; /* ctime & st_blocks are not changed */
3910 tvs.actime = interpret_long_date(pdata); /* access_time */
3911 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
3913 set_owner = (uid_t)IVAL(pdata,0);
3915 set_grp = (gid_t)IVAL(pdata,0);
3917 raw_unixmode = IVAL(pdata,28);
3918 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3919 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3921 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3922 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3923 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3925 if (!VALID_STAT(sbuf)) {
3928 * The only valid use of this is to create character and block
3929 * devices, and named pipes. This is deprecated (IMHO) and
3930 * a new info level should be used for mknod. JRA.
3933 uint32 file_type = IVAL(pdata,0);
3934 #if defined(HAVE_MAKEDEV)
3935 uint32 dev_major = IVAL(pdata,4);
3936 uint32 dev_minor = IVAL(pdata,12);
3939 uid_t myuid = geteuid();
3940 gid_t mygid = getegid();
3941 SMB_DEV_T dev = (SMB_DEV_T)0;
3943 if (tran_call == TRANSACT2_SETFILEINFO)
3944 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3946 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
3947 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3950 #if defined(HAVE_MAKEDEV)
3951 dev = makedev(dev_major, dev_minor);
3954 /* We can only create as the owner/group we are. */
3956 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3957 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3958 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3959 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3961 switch (file_type) {
3962 #if defined(S_IFIFO)
3963 case UNIX_TYPE_FIFO:
3964 unixmode |= S_IFIFO;
3967 #if defined(S_IFSOCK)
3968 case UNIX_TYPE_SOCKET:
3969 unixmode |= S_IFSOCK;
3972 #if defined(S_IFCHR)
3973 case UNIX_TYPE_CHARDEV:
3974 unixmode |= S_IFCHR;
3977 #if defined(S_IFBLK)
3978 case UNIX_TYPE_BLKDEV:
3979 unixmode |= S_IFBLK;
3983 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3986 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3987 0%o for file %s\n", (double)dev, unixmode, fname ));
3989 /* Ok - do the mknod. */
3990 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
3991 return(UNIXERROR(ERRDOS,ERRnoaccess));
3993 inherit_access_acl(conn, fname, unixmode);
3996 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4001 * Deal with the UNIX specific mode set.
4004 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4005 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4006 (unsigned int)unixmode, fname ));
4007 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4008 return(UNIXERROR(ERRDOS,ERRnoaccess));
4012 * Deal with the UNIX specific uid set.
4015 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4016 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4017 (unsigned int)set_owner, fname ));
4018 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4019 return(UNIXERROR(ERRDOS,ERRnoaccess));
4023 * Deal with the UNIX specific gid set.
4026 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4027 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4028 (unsigned int)set_owner, fname ));
4029 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4030 return(UNIXERROR(ERRDOS,ERRnoaccess));
4035 case SMB_SET_FILE_UNIX_LINK:
4037 pstring link_target;
4038 char *newname = fname;
4040 /* Set a symbolic link. */
4041 /* Don't allow this if follow links is false. */
4043 if (!lp_symlinks(SNUM(conn)))
4044 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4046 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4048 /* !widelinks forces the target path to be within the share. */
4049 /* This means we can interpret the target as a pathname. */
4050 if (!lp_widelinks(SNUM(conn))) {
4052 char *last_dirp = NULL;
4054 unix_format(link_target);
4055 if (*link_target == '/') {
4056 /* No absolute paths allowed. */
4057 return(UNIXERROR(ERRDOS,ERRnoaccess));
4059 pstrcpy(rel_name, newname);
4060 last_dirp = strrchr_m(rel_name, '/');
4062 last_dirp[1] = '\0';
4064 pstrcpy(rel_name, "./");
4066 pstrcat(rel_name, link_target);
4068 if (!check_name(rel_name, conn)) {
4069 return(UNIXERROR(ERRDOS,ERRnoaccess));
4073 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4074 fname, link_target ));
4076 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4077 return(UNIXERROR(ERRDOS,ERRnoaccess));
4079 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4083 case SMB_SET_FILE_UNIX_HLINK:
4086 char *newname = fname;
4088 /* Set a hard link. */
4089 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
4090 if (!NT_STATUS_IS_OK(status)) {
4091 return ERROR_NT(status);
4094 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4097 status = hardlink_internals(conn, oldname, newname);
4098 if (!NT_STATUS_IS_OK(status)) {
4099 return ERROR_NT(status);
4103 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4107 case SMB_FILE_RENAME_INFORMATION:
4116 if (total_data < 12) {
4117 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4120 overwrite = (CVAL(pdata,0) ? True : False);
4121 root_fid = IVAL(pdata,4);
4122 len = IVAL(pdata,8);
4123 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
4124 if (!NT_STATUS_IS_OK(status)) {
4125 return ERROR_NT(status);
4128 /* Check the new name has no '/' characters. */
4129 if (strchr_m(newname, '/'))
4130 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4132 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4134 /* Create the base directory. */
4135 pstrcpy(base_name, fname);
4136 p = strrchr_m(base_name, '/');
4139 /* Append the new name. */
4140 pstrcat(base_name, "/");
4141 pstrcat(base_name, newname);
4144 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4145 fsp->fnum, fsp->fsp_name, base_name ));
4146 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4148 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4150 status = rename_internals(conn, fname, base_name, 0, overwrite);
4152 if (!NT_STATUS_IS_OK(status)) {
4153 return ERROR_NT(status);
4155 process_pending_change_notify_queue((time_t)0);
4157 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4161 #if defined(HAVE_POSIX_ACLS)
4162 case SMB_SET_POSIX_ACL:
4164 uint16 posix_acl_version;
4165 uint16 num_file_acls;
4166 uint16 num_def_acls;
4167 BOOL valid_file_acls = True;
4168 BOOL valid_def_acls = True;
4170 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4171 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4173 posix_acl_version = SVAL(pdata,0);
4174 num_file_acls = SVAL(pdata,2);
4175 num_def_acls = SVAL(pdata,4);
4177 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4178 valid_file_acls = False;
4182 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4183 valid_def_acls = False;
4187 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4188 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4191 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4192 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4193 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4196 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4197 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4198 return(UNIXERROR(ERRDOS,ERRnoaccess));
4201 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4202 pdata + SMB_POSIX_ACL_HEADER_SIZE +
4203 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4204 return(UNIXERROR(ERRDOS,ERRnoaccess));
4208 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4214 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4217 /* get some defaults (no modifications) if any info is zero or -1. */
4218 if (null_mtime(tvs.actime)) {
4219 tvs.actime = sbuf.st_atime;
4222 if (null_mtime(tvs.modtime)) {
4223 tvs.modtime = sbuf.st_mtime;
4226 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4227 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4228 DEBUG(6,("size: %.0f ", (double)size));
4231 if (S_ISDIR(sbuf.st_mode))
4237 DEBUG(6,("dosmode: %x\n" , dosmode));
4239 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4240 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4241 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4242 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4245 * Only do this test if we are not explicitly
4246 * changing the size of a file.
4249 size = get_file_size(sbuf);
4253 * Try and set the times, size and mode of this file -
4254 * if they are different from the current values
4257 /* check the mode isn't different, before changing it */
4258 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4260 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4262 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4263 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4264 return(UNIXERROR(ERRDOS,ERRnoaccess));
4269 if (size != get_file_size(sbuf)) {
4273 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4274 fname, (double)size ));
4277 files_struct *new_fsp = NULL;
4278 int access_mode = 0;
4281 if(global_oplock_break) {
4282 /* Queue this file modify as we are the process of an oplock break. */
4284 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
4285 DEBUGADD(2,( "in oplock break state.\n"));
4287 push_oplock_pending_smb_message(inbuf, length);
4291 new_fsp = open_file_shared(conn, fname, &sbuf,
4292 SET_OPEN_MODE(DOS_OPEN_RDWR),
4293 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
4294 FILE_ATTRIBUTE_NORMAL,
4295 INTERNAL_OPEN_ONLY, &access_mode, &action);
4297 if (new_fsp == NULL)
4298 return(UNIXERROR(ERRDOS,ERRbadpath));
4299 ret = vfs_set_filelen(new_fsp, size);
4300 close_file(new_fsp,True);
4302 ret = vfs_set_filelen(fsp, size);
4306 return (UNIXERROR(ERRHRD,ERRdiskfull));
4310 * Finally the times.
4312 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4315 * This was a setfileinfo on an open file.
4316 * NT does this a lot. We also need to
4317 * set the time here, as it can be read by
4318 * FindFirst/FindNext and with the patch for bug #2045
4319 * in smbd/fileio.c it ensures that this timestamp is
4320 * kept sticky even after a write. We save the request
4321 * away and will set it on file close and after a write. JRA.
4324 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4325 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4326 fsp_set_pending_modtime(fsp, tvs.modtime);
4330 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4332 if(file_utime(conn, fname, &tvs)!=0) {
4333 return(UNIXERROR(ERRDOS,ERRnoaccess));
4338 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4343 /****************************************************************************
4344 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4345 ****************************************************************************/
4347 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4348 char **pparams, int total_params, char **ppdata, int total_data,
4349 unsigned int max_data_bytes)
4351 char *params = *pparams;
4354 SMB_STRUCT_STAT sbuf;
4355 BOOL bad_path = False;
4356 NTSTATUS status = NT_STATUS_OK;
4358 if (!CAN_WRITE(conn))
4359 return ERROR_DOS(ERRSRV,ERRaccess);
4361 if (total_params < 4) {
4362 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4365 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4366 if (!NT_STATUS_IS_OK(status)) {
4367 return ERROR_NT(status);
4370 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4372 unix_convert(directory,conn,0,&bad_path,&sbuf);
4374 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4376 if (check_name(directory,conn))
4377 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4380 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4381 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4384 /* Realloc the parameter and data sizes */
4385 params = SMB_REALLOC(*pparams,2);
4386 if(params == NULL) {
4387 return ERROR_NT(NT_STATUS_NO_MEMORY);
4393 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4398 /****************************************************************************
4399 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4400 We don't actually do this - we just send a null response.
4401 ****************************************************************************/
4403 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4404 char **pparams, int total_params, char **ppdata, int total_data,
4405 unsigned int max_data_bytes)
4407 static uint16 fnf_handle = 257;
4408 char *params = *pparams;
4411 if (total_params < 6) {
4412 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4415 info_level = SVAL(params,4);
4416 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4418 switch (info_level) {
4423 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4426 /* Realloc the parameter and data sizes */
4427 params = SMB_REALLOC(*pparams,6);
4428 if(params == NULL) {
4429 return ERROR_NT(NT_STATUS_NO_MEMORY);
4433 SSVAL(params,0,fnf_handle);
4434 SSVAL(params,2,0); /* No changes */
4435 SSVAL(params,4,0); /* No EA errors */
4442 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4447 /****************************************************************************
4448 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4449 changes). Currently this does nothing.
4450 ****************************************************************************/
4452 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4453 char **pparams, int total_params, char **ppdata, int total_data,
4454 unsigned int max_data_bytes)
4456 char *params = *pparams;
4458 DEBUG(3,("call_trans2findnotifynext\n"));
4460 /* Realloc the parameter and data sizes */
4461 params = SMB_REALLOC(*pparams,4);
4462 if(params == NULL) {
4463 return ERROR_NT(NT_STATUS_NO_MEMORY);
4467 SSVAL(params,0,0); /* No changes */
4468 SSVAL(params,2,0); /* No EA errors */
4470 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4475 /****************************************************************************
4476 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4477 ****************************************************************************/
4479 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4480 char **pparams, int total_params, char **ppdata, int total_data,
4481 unsigned int max_data_bytes)
4483 char *params = *pparams;
4486 int max_referral_level;
4488 DEBUG(10,("call_trans2getdfsreferral\n"));
4490 if (total_params < 2) {
4491 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4494 max_referral_level = SVAL(params,0);
4496 if(!lp_host_msdfs())
4497 return ERROR_DOS(ERRDOS,ERRbadfunc);
4499 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4500 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4501 return UNIXERROR(ERRDOS,ERRbadfile);
4503 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4504 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4509 #define LMCAT_SPL 0x53
4510 #define LMFUNC_GETJOBID 0x60
4512 /****************************************************************************
4513 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4514 ****************************************************************************/
4516 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4517 char **pparams, int total_params, char **ppdata, int total_data,
4518 unsigned int max_data_bytes)
4520 char *pdata = *ppdata;
4521 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4523 /* check for an invalid fid before proceeding */
4526 return(ERROR_DOS(ERRDOS,ERRbadfid));
4528 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4529 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4530 pdata = SMB_REALLOC(*ppdata, 32);
4532 return ERROR_NT(NT_STATUS_NO_MEMORY);
4536 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4537 CAN ACCEPT THIS IN UNICODE. JRA. */
4539 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4540 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4541 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4542 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4545 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4546 return ERROR_DOS(ERRSRV,ERRerror);
4550 /****************************************************************************
4551 Reply to a SMBfindclose (stop trans2 directory search).
4552 ****************************************************************************/
4554 int reply_findclose(connection_struct *conn,
4555 char *inbuf,char *outbuf,int length,int bufsize)
4558 int dptr_num=SVALS(inbuf,smb_vwv0);
4559 START_PROFILE(SMBfindclose);
4561 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4563 dptr_close(&dptr_num);
4565 outsize = set_message(outbuf,0,0,True);
4567 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4569 END_PROFILE(SMBfindclose);
4573 /****************************************************************************
4574 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4575 ****************************************************************************/
4577 int reply_findnclose(connection_struct *conn,
4578 char *inbuf,char *outbuf,int length,int bufsize)
4582 START_PROFILE(SMBfindnclose);
4584 dptr_num = SVAL(inbuf,smb_vwv0);
4586 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4588 /* We never give out valid handles for a
4589 findnotifyfirst - so any dptr_num is ok here.
4592 outsize = set_message(outbuf,0,0,True);
4594 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4596 END_PROFILE(SMBfindnclose);
4600 /****************************************************************************
4601 Reply to a SMBtranss2 - just ignore it!
4602 ****************************************************************************/
4604 int reply_transs2(connection_struct *conn,
4605 char *inbuf,char *outbuf,int length,int bufsize)
4607 START_PROFILE(SMBtranss2);
4608 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4609 END_PROFILE(SMBtranss2);
4613 /****************************************************************************
4614 Reply to a SMBtrans2.
4615 ****************************************************************************/
4617 int reply_trans2(connection_struct *conn,
4618 char *inbuf,char *outbuf,int length,int bufsize)
4621 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4622 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4623 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4625 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4626 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4627 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4628 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4629 int32 timeout = IVALS(inbuf,smb_timeout);
4631 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4632 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4633 char *params = NULL, *data = NULL;
4634 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4635 START_PROFILE(SMBtrans2);
4637 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4638 /* Queue this open message as we are the process of an
4641 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4642 DEBUGADD(2,( "in oplock break state.\n"));
4644 push_oplock_pending_smb_message(inbuf, length);
4645 END_PROFILE(SMBtrans2);
4649 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4650 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4651 END_PROFILE(SMBtrans2);
4652 return ERROR_DOS(ERRSRV,ERRaccess);
4655 outsize = set_message(outbuf,0,0,True);
4657 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4658 is so as a sanity check */
4661 * Need to have rc=0 for ioctl to get job id for OS/2.
4662 * Network printing will fail if function is not successful.
4663 * Similar function in reply.c will be used if protocol
4664 * is LANMAN1.0 instead of LM1.2X002.
4665 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4666 * outbuf doesn't have to be set(only job id is used).
4668 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4669 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4670 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4671 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4673 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4674 DEBUG(2,("Transaction is %d\n",tran_call));
4675 END_PROFILE(SMBtrans2);
4676 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4680 /* Allocate the space for the maximum needed parameters and data */
4681 if (total_params > 0)
4682 params = (char *)SMB_MALLOC(total_params);
4684 data = (char *)SMB_MALLOC(total_data);
4686 if ((total_params && !params) || (total_data && !data)) {
4687 DEBUG(2,("Out of memory in reply_trans2\n"));
4690 END_PROFILE(SMBtrans2);
4691 return ERROR_NT(NT_STATUS_NO_MEMORY);
4694 /* Copy the param and data bytes sent with this request into
4695 the params buffer */
4696 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4697 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4699 if (num_params > total_params || num_data > total_data)
4700 exit_server("invalid params in reply_trans2");
4703 unsigned int psoff = SVAL(inbuf, smb_psoff);
4704 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4706 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4707 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4709 memcpy( params, smb_base(inbuf) + psoff, num_params);
4712 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4713 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4715 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4716 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4718 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4721 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4723 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4724 /* We need to send an interim response then receive the rest
4725 of the parameter/data bytes */
4726 outsize = set_message(outbuf,0,0,True);
4727 srv_signing_trans_stop();
4728 if (!send_smb(smbd_server_fd(),outbuf))
4729 exit_server("reply_trans2: send_smb failed.");
4731 while (num_data_sofar < total_data ||
4732 num_params_sofar < total_params) {
4734 unsigned int param_disp;
4735 unsigned int param_off;
4736 unsigned int data_disp;
4737 unsigned int data_off;
4739 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4742 * The sequence number for the trans reply is always
4743 * based on the last secondary received.
4746 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4749 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4750 outsize = set_message(outbuf,0,0,True);
4752 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4754 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4755 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4759 /* Revise total_params and total_data in case
4760 they have changed downwards */
4761 if (SVAL(inbuf, smb_tpscnt) < total_params)
4762 total_params = SVAL(inbuf, smb_tpscnt);
4763 if (SVAL(inbuf, smb_tdscnt) < total_data)
4764 total_data = SVAL(inbuf, smb_tdscnt);
4766 num_params = SVAL(inbuf,smb_spscnt);
4767 param_off = SVAL(inbuf, smb_spsoff);
4768 param_disp = SVAL(inbuf, smb_spsdisp);
4769 num_params_sofar += num_params;
4771 num_data = SVAL(inbuf, smb_sdscnt);
4772 data_off = SVAL(inbuf, smb_sdsoff);
4773 data_disp = SVAL(inbuf, smb_sdsdisp);
4774 num_data_sofar += num_data;
4776 if (num_params_sofar > total_params || num_data_sofar > total_data)
4780 if (param_disp + num_params > total_params)
4782 if ((param_disp + num_params < param_disp) ||
4783 (param_disp + num_params < num_params))
4785 if (param_disp > total_params)
4787 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4788 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4790 if (params + param_disp < params)
4793 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
4796 if (data_disp + num_data > total_data)
4798 if ((data_disp + num_data < data_disp) ||
4799 (data_disp + num_data < num_data))
4801 if (data_disp > total_data)
4803 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4804 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4806 if (data + data_disp < data)
4809 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4814 if (Protocol >= PROTOCOL_NT1) {
4815 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4818 /* Now we must call the relevant TRANS2 function */
4820 case TRANSACT2_OPEN:
4821 START_PROFILE_NESTED(Trans2_open);
4822 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4823 ¶ms, total_params, &data, total_data, max_data_bytes);
4824 END_PROFILE_NESTED(Trans2_open);
4827 case TRANSACT2_FINDFIRST:
4828 START_PROFILE_NESTED(Trans2_findfirst);
4829 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4830 ¶ms, total_params, &data, total_data, max_data_bytes);
4831 END_PROFILE_NESTED(Trans2_findfirst);
4834 case TRANSACT2_FINDNEXT:
4835 START_PROFILE_NESTED(Trans2_findnext);
4836 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4837 ¶ms, total_params, &data, total_data, max_data_bytes);
4838 END_PROFILE_NESTED(Trans2_findnext);
4841 case TRANSACT2_QFSINFO:
4842 START_PROFILE_NESTED(Trans2_qfsinfo);
4843 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4844 ¶ms, total_params, &data, total_data, max_data_bytes);
4845 END_PROFILE_NESTED(Trans2_qfsinfo);
4848 #ifdef HAVE_SYS_QUOTAS
4849 case TRANSACT2_SETFSINFO:
4850 START_PROFILE_NESTED(Trans2_setfsinfo);
4851 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4852 ¶ms, total_params, &data, total_data, max_data_bytes);
4853 END_PROFILE_NESTED(Trans2_setfsinfo);
4856 case TRANSACT2_QPATHINFO:
4857 case TRANSACT2_QFILEINFO:
4858 START_PROFILE_NESTED(Trans2_qpathinfo);
4859 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4860 ¶ms, total_params, &data, total_data, max_data_bytes);
4861 END_PROFILE_NESTED(Trans2_qpathinfo);
4863 case TRANSACT2_SETPATHINFO:
4864 case TRANSACT2_SETFILEINFO:
4865 START_PROFILE_NESTED(Trans2_setpathinfo);
4866 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4867 ¶ms, total_params, &data, total_data, max_data_bytes);
4868 END_PROFILE_NESTED(Trans2_setpathinfo);
4871 case TRANSACT2_FINDNOTIFYFIRST:
4872 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4873 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4874 ¶ms, total_params, &data, total_data, max_data_bytes);
4875 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4878 case TRANSACT2_FINDNOTIFYNEXT:
4879 START_PROFILE_NESTED(Trans2_findnotifynext);
4880 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4881 ¶ms, total_params, &data, total_data, max_data_bytes);
4882 END_PROFILE_NESTED(Trans2_findnotifynext);
4884 case TRANSACT2_MKDIR:
4885 START_PROFILE_NESTED(Trans2_mkdir);
4886 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4887 ¶ms, total_params, &data, total_data, max_data_bytes);
4888 END_PROFILE_NESTED(Trans2_mkdir);
4891 case TRANSACT2_GET_DFS_REFERRAL:
4892 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4893 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4894 ¶ms, total_params, &data, total_data, max_data_bytes);
4895 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4897 case TRANSACT2_IOCTL:
4898 START_PROFILE_NESTED(Trans2_ioctl);
4899 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4900 ¶ms, total_params, &data, total_data, max_data_bytes);
4901 END_PROFILE_NESTED(Trans2_ioctl);
4904 /* Error in request */
4905 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4908 END_PROFILE(SMBtrans2);
4909 srv_signing_trans_stop();
4910 return ERROR_DOS(ERRSRV,ERRerror);
4913 /* As we do not know how many data packets will need to be
4914 returned here the various call_trans2xxxx calls
4915 must send their own. Thus a call_trans2xxx routine only
4916 returns a value other than -1 when it wants to send
4920 srv_signing_trans_stop();
4924 END_PROFILE(SMBtrans2);
4925 return outsize; /* If a correct response was needed the
4926 call_trans2xxx calls have already sent
4927 it. If outsize != -1 then it is returning */
4931 srv_signing_trans_stop();
4934 END_PROFILE(SMBtrans2);
4935 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);