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,
317 char *pdata, int total_data)
319 unsigned int namelen;
322 fstring unix_ea_name;
324 if (!lp_ea_support(SNUM(conn))) {
325 return NT_STATUS_EAS_NOT_SUPPORTED;
328 if (total_data < 8) {
329 return NT_STATUS_INVALID_PARAMETER;
332 if (IVAL(pdata,0) > total_data) {
333 DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data));
334 return NT_STATUS_INVALID_PARAMETER;
338 namelen = CVAL(pdata,1);
339 ealen = SVAL(pdata,2);
341 if (total_data < 8 + namelen + 1 + ealen) {
342 DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n",
343 (unsigned int)total_data, namelen, ealen));
344 return NT_STATUS_INVALID_PARAMETER;
347 if (pdata[namelen] != '\0') {
348 DEBUG(10,("set_ea: ea name not null terminated\n"));
349 return NT_STATUS_INVALID_PARAMETER;
352 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
353 pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE);
354 pdata += (namelen + 1);
356 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
358 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen));
360 DEBUG(10,("set_ea: data :\n"));
361 dump_data(10, pdata, ealen);
364 if (samba_private_attr_name(unix_ea_name)) {
365 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
366 return NT_STATUS_ACCESS_DENIED;
370 /* Remove the attribute. */
371 if (fsp && (fsp->fd != -1)) {
372 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
373 unix_ea_name, fsp->fsp_name));
374 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
376 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
377 unix_ea_name, fname));
378 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
381 /* Removing a non existent attribute always succeeds. */
382 if (ret == -1 && errno == ENOATTR) {
383 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name));
388 if (fsp && (fsp->fd != -1)) {
389 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
390 unix_ea_name, fsp->fsp_name));
391 ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0);
393 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
394 unix_ea_name, fname));
395 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0);
401 if (errno == ENOTSUP) {
402 return NT_STATUS_EAS_NOT_SUPPORTED;
405 return map_nt_error_from_unix(errno);
411 /****************************************************************************
412 Read a list of EA's from an incoming data buffer. Create an ea_list with them.
413 ****************************************************************************/
415 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
417 struct ea_list *ea_list_head = NULL;
420 while (offset + 2 < data_size) {
422 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
423 unsigned int namelen = CVAL(pdata,offset);
425 offset++; /* Go past the namelen byte. */
426 if (offset + namelen >= data_size) {
429 eal->ea.name = TALLOC_ARRAY(ctx, char, namelen + 1);
433 memcpy(eal->ea.name, pdata + offset, namelen);
434 eal->ea.name[namelen] = '\0';
436 offset += (namelen + 1); /* Go past the name + terminating zero. */
437 DLIST_ADD_END(ea_list_head, eal, tmp);
443 /****************************************************************************
444 Count the total EA size needed.
445 ****************************************************************************/
447 static size_t ea_list_size(struct ea_list *ealist)
450 struct ea_list *listp;
453 for (listp = ealist; listp; listp = listp->next) {
454 push_ascii_fstring(dos_ea_name, listp->ea.name);
455 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
457 /* Add on 4 for total length. */
465 /****************************************************************************
466 Return a union of EA's from a file list and a list of names.
467 ****************************************************************************/
469 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
471 struct ea_list *nlistp, *flistp;
473 for (flistp = file_list; flistp;) {
474 struct ea_list *rem_entry = flistp;
476 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
477 if (strequal(nlistp->ea.name, flistp->ea.name)) {
482 flistp = flistp->next;
484 if (nlistp == NULL) {
485 /* Remove this entry from file ea list. */
486 DLIST_REMOVE(file_list, rem_entry);
490 *total_ea_len = ea_list_size(file_list);
494 /****************************************************************************
495 Send the required number of replies back.
496 We assume all fields other than the data fields are
497 set correctly for the type of call.
498 HACK ! Always assumes smb_setup field is zero.
499 ****************************************************************************/
501 static int send_trans2_replies(char *outbuf,
508 /* As we are using a protocol > LANMAN1 then the max_send
509 variable must have been set in the sessetupX call.
510 This takes precedence over the max_xmit field in the
511 global struct. These different max_xmit variables should
512 be merged as this is now too confusing */
515 int data_to_send = datasize;
516 int params_to_send = paramsize;
520 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
521 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
522 int data_alignment_offset = 0;
524 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
526 set_message(outbuf,10,0,True);
528 /* If there genuinely are no parameters or data to send just send the empty packet */
530 if(params_to_send == 0 && data_to_send == 0) {
531 if (!send_smb(smbd_server_fd(),outbuf))
532 exit_server("send_trans2_replies: send_smb failed.");
536 /* When sending params and data ensure that both are nicely aligned */
537 /* Only do this alignment when there is also data to send - else
538 can cause NT redirector problems. */
540 if (((params_to_send % 4) != 0) && (data_to_send != 0))
541 data_alignment_offset = 4 - (params_to_send % 4);
543 /* Space is bufsize minus Netbios over TCP header minus SMB header */
544 /* The alignment_offset is to align the param bytes on an even byte
545 boundary. NT 4.0 Beta needs this to work correctly. */
547 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
549 /* useable_space can never be more than max_send minus the alignment offset. */
551 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
553 while (params_to_send || data_to_send) {
554 /* Calculate whether we will totally or partially fill this packet */
556 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
558 /* We can never send more than useable_space */
560 * Note that 'useable_space' does not include the alignment offsets,
561 * but we must include the alignment offsets in the calculation of
562 * the length of the data we send over the wire, as the alignment offsets
563 * are sent here. Fix from Marc_Jacobsen@hp.com.
566 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
568 set_message(outbuf, 10, total_sent_thistime, True);
570 /* Set total params and data to be sent */
571 SSVAL(outbuf,smb_tprcnt,paramsize);
572 SSVAL(outbuf,smb_tdrcnt,datasize);
574 /* Calculate how many parameters and data we can fit into
575 * this packet. Parameters get precedence
578 params_sent_thistime = MIN(params_to_send,useable_space);
579 data_sent_thistime = useable_space - params_sent_thistime;
580 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
582 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
584 /* smb_proff is the offset from the start of the SMB header to the
585 parameter bytes, however the first 4 bytes of outbuf are
586 the Netbios over TCP header. Thus use smb_base() to subtract
587 them from the calculation */
589 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
591 if(params_sent_thistime == 0)
592 SSVAL(outbuf,smb_prdisp,0);
594 /* Absolute displacement of param bytes sent in this packet */
595 SSVAL(outbuf,smb_prdisp,pp - params);
597 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
598 if(data_sent_thistime == 0) {
599 SSVAL(outbuf,smb_droff,0);
600 SSVAL(outbuf,smb_drdisp, 0);
602 /* The offset of the data bytes is the offset of the
603 parameter bytes plus the number of parameters being sent this time */
604 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
605 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
606 SSVAL(outbuf,smb_drdisp, pd - pdata);
609 /* Copy the param bytes into the packet */
611 if(params_sent_thistime)
612 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
614 /* Copy in the data bytes */
615 if(data_sent_thistime)
616 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
617 data_alignment_offset,pd,data_sent_thistime);
619 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
620 params_sent_thistime, data_sent_thistime, useable_space));
621 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
622 params_to_send, data_to_send, paramsize, datasize));
624 /* Send the packet */
625 if (!send_smb(smbd_server_fd(),outbuf))
626 exit_server("send_trans2_replies: send_smb failed.");
628 pp += params_sent_thistime;
629 pd += data_sent_thistime;
631 params_to_send -= params_sent_thistime;
632 data_to_send -= data_sent_thistime;
635 if(params_to_send < 0 || data_to_send < 0) {
636 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
637 params_to_send, data_to_send));
645 /****************************************************************************
646 Reply to a TRANSACT2_OPEN.
647 ****************************************************************************/
649 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
650 char **pparams, int total_params, char **ppdata, int total_data,
651 unsigned int max_data_bytes)
653 char *params = *pparams;
658 BOOL return_additional_info;
667 int fmode=0,mtime=0,rmode;
669 SMB_STRUCT_STAT sbuf;
671 BOOL bad_path = False;
676 * Ensure we have enough parameters to perform the operation.
679 if (total_params < 29)
680 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
682 open_mode = SVAL(params, 2);
683 open_attr = SVAL(params,6);
684 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
686 return_additional_info = BITSETW(params,0);
687 open_sattr = SVAL(params, 4);
688 open_time = make_unix_date3(params+8);
690 open_ofun = SVAL(params,12);
691 open_size = IVAL(params,14);
695 return(ERROR_DOS(ERRSRV,ERRaccess));
697 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
698 if (!NT_STATUS_IS_OK(status)) {
699 return ERROR_NT(status);
702 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
703 fname,open_mode, open_attr, open_ofun, open_size));
705 /* XXXX we need to handle passed times, sattr and flags */
707 unix_convert(fname,conn,0,&bad_path,&sbuf);
709 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
712 if (!check_name(fname,conn)) {
713 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
716 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
717 oplock_request, &rmode,&smb_action);
720 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
721 /* We have re-scheduled this call. */
722 clear_cached_errors();
725 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
728 size = get_file_size(sbuf);
729 fmode = dos_mode(conn,fname,&sbuf);
730 mtime = sbuf.st_mtime;
733 close_file(fsp,False);
734 return(ERROR_DOS(ERRDOS,ERRnoaccess));
737 /* Realloc the size of parameters and data we will return */
738 params = SMB_REALLOC(*pparams, 28);
740 return(ERROR_DOS(ERRDOS,ERRnomem));
743 memset((char *)params,'\0',28);
744 SSVAL(params,0,fsp->fnum);
745 SSVAL(params,2,fmode);
746 put_dos_date2(params,4, mtime);
747 SIVAL(params,8, (uint32)size);
748 SSVAL(params,12,rmode);
750 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
751 smb_action |= EXTENDED_OPLOCK_GRANTED;
753 SSVAL(params,18,smb_action);
756 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
758 SIVAL(params,20,inode);
760 /* Send the required number of replies */
761 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
766 /*********************************************************
767 Routine to check if a given string matches exactly.
768 as a special case a mask of "." does NOT match. That
769 is required for correct wildcard semantics
770 Case can be significant or not.
771 **********************************************************/
773 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
775 if (mask[0] == '.' && mask[1] == 0)
778 return strcmp(str,mask)==0;
779 if (StrCaseCmp(str,mask) != 0) {
782 if (ms_has_wild(str)) {
788 /****************************************************************************
789 Return the filetype for UNIX extensions.
790 ****************************************************************************/
792 static uint32 unix_filetype(mode_t mode)
795 return UNIX_TYPE_FILE;
796 else if(S_ISDIR(mode))
797 return UNIX_TYPE_DIR;
799 else if(S_ISLNK(mode))
800 return UNIX_TYPE_SYMLINK;
803 else if(S_ISCHR(mode))
804 return UNIX_TYPE_CHARDEV;
807 else if(S_ISBLK(mode))
808 return UNIX_TYPE_BLKDEV;
811 else if(S_ISFIFO(mode))
812 return UNIX_TYPE_FIFO;
815 else if(S_ISSOCK(mode))
816 return UNIX_TYPE_SOCKET;
819 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
820 return UNIX_TYPE_UNKNOWN;
823 /****************************************************************************
824 Map wire perms onto standard UNIX permissions. Obey share restrictions.
825 ****************************************************************************/
827 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
831 if (perms == SMB_MODE_NO_CHANGE)
834 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
835 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
836 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
837 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
838 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
839 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
840 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
841 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
842 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
844 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
847 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
850 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
853 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
854 ret &= lp_dir_mask(SNUM(conn));
855 /* Add in force bits */
856 ret |= lp_force_dir_mode(SNUM(conn));
858 /* Apply mode mask */
859 ret &= lp_create_mask(SNUM(conn));
860 /* Add in force bits */
861 ret |= lp_force_create_mode(SNUM(conn));
867 /****************************************************************************
868 Get a level dependent lanman2 dir entry.
869 ****************************************************************************/
871 static BOOL get_lanman2_dir_entry(connection_struct *conn,
872 void *inbuf, void *outbuf,
873 char *path_mask,int dirtype,int info_level,
874 int requires_resume_key,
875 BOOL dont_descend,char **ppdata,
876 char *base_data, int space_remaining,
877 BOOL *out_of_space, BOOL *got_exact_match,
882 SMB_STRUCT_STAT sbuf;
886 char *p, *q, *pdata = *ppdata;
890 SMB_OFF_T file_size = 0;
891 SMB_BIG_UINT allocation_size = 0;
893 time_t mdate=0, adate=0, cdate=0;
895 char *last_entry_ptr;
897 int nt_extmode; /* Used for NT connections instead of mode */
898 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
901 *out_of_space = False;
902 *got_exact_match = False;
907 p = strrchr_m(path_mask,'/');
914 pstrcpy(mask, path_mask);
919 /* Needed if we run out of space */
920 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
921 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
924 * Due to bugs in NT client redirectors we are not using
925 * resume keys any more - set them to zero.
926 * Check out the related comments in findfirst/findnext.
932 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
933 (long)conn->dirptr,curr_dirpos));
938 pstrcpy(fname,dname);
940 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
941 got_match = mask_match(fname, mask, conn->case_sensitive);
943 if(!got_match && !mangle_is_8_3(fname, False)) {
946 * It turns out that NT matches wildcards against
947 * both long *and* short names. This may explain some
948 * of the wildcard wierdness from old DOS clients
949 * that some people have been seeing.... JRA.
953 pstrcpy( newname, fname);
954 mangle_map( newname, True, False, SNUM(conn));
955 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
956 got_match = mask_match(newname, mask, conn->case_sensitive);
960 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
961 if (dont_descend && !isdots)
964 pstrcpy(pathreal,conn->dirpath);
966 pstrcat(pathreal,"/");
967 pstrcat(pathreal,dname);
969 if (INFO_LEVEL_IS_UNIX(info_level)) {
970 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
971 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
972 pathreal,strerror(errno)));
975 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
977 /* Needed to show the msdfs symlinks as
980 if(lp_host_msdfs() &&
981 lp_msdfs_root(SNUM(conn)) &&
982 is_msdfs_link(conn, pathreal, NULL, NULL,
985 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
986 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
990 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
991 pathreal,strerror(errno)));
996 mode = dos_mode(conn,pathreal,&sbuf);
998 if (!dir_check_ftype(conn,mode,dirtype)) {
999 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1003 file_size = get_file_size(sbuf);
1004 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1005 mdate = sbuf.st_mtime;
1006 adate = sbuf.st_atime;
1007 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1009 if (lp_dos_filetime_resolution(SNUM(conn))) {
1016 /* This is necessary, as otherwise the
1017 * desktop.ini file in this folder is
1019 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
1023 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1029 mangle_map(fname,False,True,SNUM(conn));
1034 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1036 switch (info_level) {
1037 case SMB_FIND_INFO_STANDARD:
1038 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1039 if(requires_resume_key) {
1043 put_dos_date2(p,l1_fdateCreation,cdate);
1044 put_dos_date2(p,l1_fdateLastAccess,adate);
1045 put_dos_date2(p,l1_fdateLastWrite,mdate);
1046 SIVAL(p,l1_cbFile,(uint32)file_size);
1047 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
1048 SSVAL(p,l1_attrFile,mode);
1051 p += align_string(outbuf, p, 0);
1052 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1053 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1055 SCVAL(nameptr, -1, len - 2);
1057 SCVAL(nameptr, -1, 0);
1061 SCVAL(nameptr, -1, len - 1);
1063 SCVAL(nameptr, -1, 0);
1069 case SMB_FIND_EA_SIZE:
1070 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1071 if(requires_resume_key) {
1075 put_dos_date2(p,l2_fdateCreation,cdate);
1076 put_dos_date2(p,l2_fdateLastAccess,adate);
1077 put_dos_date2(p,l2_fdateLastWrite,mdate);
1078 SIVAL(p,l2_cbFile,(uint32)file_size);
1079 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1080 SSVAL(p,l2_attrFile,mode);
1082 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1083 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1087 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1088 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1101 SCVAL(nameptr,0,len);
1103 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1107 case SMB_FIND_EA_LIST:
1108 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1109 if(requires_resume_key) {
1115 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1116 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1117 was_8_3 = mangle_is_8_3(fname, True);
1119 SIVAL(p,0,reskey); p += 4;
1120 put_long_date(p,cdate); p += 8;
1121 put_long_date(p,adate); p += 8;
1122 put_long_date(p,mdate); p += 8;
1123 put_long_date(p,mdate); p += 8;
1124 SOFF_T(p,0,file_size); p += 8;
1125 SOFF_T(p,0,allocation_size); p += 8;
1126 SIVAL(p,0,nt_extmode); p += 4;
1127 q = p; p += 4; /* q is placeholder for name length. */
1129 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1130 SIVAL(p,0,ea_size); /* Extended attributes */
1133 /* Clear the short name buffer. This is
1134 * IMPORTANT as not doing so will trigger
1135 * a Win2k client bug. JRA.
1138 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1139 pstring mangled_name;
1140 pstrcpy(mangled_name, fname);
1141 mangle_map(mangled_name,True,True,SNUM(conn));
1142 mangled_name[12] = 0;
1143 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1150 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1153 len = PTR_DIFF(p, pdata);
1154 len = (len + 3) & ~3;
1159 case SMB_FIND_FILE_DIRECTORY_INFO:
1160 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1162 SIVAL(p,0,reskey); p += 4;
1163 put_long_date(p,cdate); p += 8;
1164 put_long_date(p,adate); p += 8;
1165 put_long_date(p,mdate); p += 8;
1166 put_long_date(p,mdate); p += 8;
1167 SOFF_T(p,0,file_size); p += 8;
1168 SOFF_T(p,0,allocation_size); p += 8;
1169 SIVAL(p,0,nt_extmode); p += 4;
1170 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1173 len = PTR_DIFF(p, pdata);
1174 len = (len + 3) & ~3;
1179 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1180 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1182 SIVAL(p,0,reskey); p += 4;
1183 put_long_date(p,cdate); p += 8;
1184 put_long_date(p,adate); p += 8;
1185 put_long_date(p,mdate); p += 8;
1186 put_long_date(p,mdate); p += 8;
1187 SOFF_T(p,0,file_size); p += 8;
1188 SOFF_T(p,0,allocation_size); p += 8;
1189 SIVAL(p,0,nt_extmode); p += 4;
1190 q = p; p += 4; /* q is placeholder for name length. */
1192 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1193 SIVAL(p,0,ea_size); /* Extended attributes */
1196 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1200 len = PTR_DIFF(p, pdata);
1201 len = (len + 3) & ~3;
1206 case SMB_FIND_FILE_NAMES_INFO:
1207 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1209 SIVAL(p,0,reskey); p += 4;
1211 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1212 acl on a dir (tridge) */
1213 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1216 len = PTR_DIFF(p, pdata);
1217 len = (len + 3) & ~3;
1222 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1223 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1225 SIVAL(p,0,reskey); p += 4;
1226 put_long_date(p,cdate); p += 8;
1227 put_long_date(p,adate); p += 8;
1228 put_long_date(p,mdate); p += 8;
1229 put_long_date(p,mdate); p += 8;
1230 SOFF_T(p,0,file_size); p += 8;
1231 SOFF_T(p,0,allocation_size); p += 8;
1232 SIVAL(p,0,nt_extmode); p += 4;
1233 q = p; p += 4; /* q is placeholder for name length. */
1235 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1236 SIVAL(p,0,ea_size); /* Extended attributes */
1239 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1240 SIVAL(p,0,sbuf.st_dev); p += 4;
1241 SIVAL(p,0,sbuf.st_ino); p += 4;
1242 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1245 len = PTR_DIFF(p, pdata);
1246 len = (len + 3) & ~3;
1251 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1252 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1253 was_8_3 = mangle_is_8_3(fname, True);
1255 SIVAL(p,0,reskey); p += 4;
1256 put_long_date(p,cdate); p += 8;
1257 put_long_date(p,adate); p += 8;
1258 put_long_date(p,mdate); p += 8;
1259 put_long_date(p,mdate); p += 8;
1260 SOFF_T(p,0,file_size); p += 8;
1261 SOFF_T(p,0,allocation_size); p += 8;
1262 SIVAL(p,0,nt_extmode); p += 4;
1263 q = p; p += 4; /* q is placeholder for name length */
1265 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1266 SIVAL(p,0,ea_size); /* Extended attributes */
1269 /* Clear the short name buffer. This is
1270 * IMPORTANT as not doing so will trigger
1271 * a Win2k client bug. JRA.
1274 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1275 pstring mangled_name;
1276 pstrcpy(mangled_name, fname);
1277 mangle_map(mangled_name,True,True,SNUM(conn));
1278 mangled_name[12] = 0;
1279 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1286 SSVAL(p,0,0); p += 2; /* Reserved ? */
1287 SIVAL(p,0,sbuf.st_dev); p += 4;
1288 SIVAL(p,0,sbuf.st_ino); p += 4;
1289 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1292 len = PTR_DIFF(p, pdata);
1293 len = (len + 3) & ~3;
1298 /* CIFS UNIX Extension. */
1300 case SMB_FIND_FILE_UNIX:
1301 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1303 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1305 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1306 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1309 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1312 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1313 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1314 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1317 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1321 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1325 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1328 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1332 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1336 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1339 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1343 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1347 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1350 len = PTR_DIFF(p, pdata);
1351 len = (len + 3) & ~3;
1352 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1354 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1363 if (PTR_DIFF(p,pdata) > space_remaining) {
1364 /* Move the dirptr back to prev_dirpos */
1365 dptr_SeekDir(conn->dirptr, prev_dirpos);
1366 *out_of_space = True;
1367 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1368 return False; /* Not finished - just out of space */
1371 /* Setup the last entry pointer, as an offset from base_data */
1372 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1373 /* Advance the data pointer to the next slot */
1379 /****************************************************************************
1380 Reply to a TRANS2_FINDFIRST.
1381 ****************************************************************************/
1383 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1384 char **pparams, int total_params, char **ppdata, int total_data,
1385 unsigned int max_data_bytes)
1387 /* We must be careful here that we don't return more than the
1388 allowed number of data bytes. If this means returning fewer than
1389 maxentries then so be it. We assume that the redirector has
1390 enough room for the fixed number of parameter bytes it has
1392 char *params = *pparams;
1393 char *pdata = *ppdata;
1394 int dirtype = SVAL(params,0);
1395 int maxentries = SVAL(params,2);
1396 uint16 findfirst_flags = SVAL(params,4);
1397 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1398 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1399 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1400 int info_level = SVAL(params,6);
1404 int last_entry_off=0;
1408 BOOL finished = False;
1409 BOOL dont_descend = False;
1410 BOOL out_of_space = False;
1411 int space_remaining;
1412 BOOL bad_path = False;
1413 SMB_STRUCT_STAT sbuf;
1414 NTSTATUS ntstatus = NT_STATUS_OK;
1416 if (total_params < 12)
1417 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1419 *directory = *mask = 0;
1421 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1422 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1423 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1424 info_level, max_data_bytes));
1427 /* W2K3 seems to treat zero as 1. */
1431 switch (info_level) {
1432 case SMB_FIND_INFO_STANDARD:
1433 case SMB_FIND_EA_SIZE:
1434 case SMB_FIND_FILE_DIRECTORY_INFO:
1435 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1436 case SMB_FIND_FILE_NAMES_INFO:
1437 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1438 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1439 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1441 case SMB_FIND_FILE_UNIX:
1442 if (!lp_unix_extensions())
1443 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1446 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1449 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1450 if (!NT_STATUS_IS_OK(ntstatus)) {
1451 return ERROR_NT(ntstatus);
1454 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
1456 unix_convert(directory,conn,0,&bad_path,&sbuf);
1458 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1460 if(!check_name(directory,conn)) {
1461 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1464 p = strrchr_m(directory,'/');
1466 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1467 if((directory[0] == '.') && (directory[1] == '\0'))
1470 pstrcpy(mask,directory);
1471 pstrcpy(directory,"./");
1477 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1479 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1481 return(ERROR_DOS(ERRDOS,ERRnomem));
1484 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1486 /* Realloc the params space */
1487 params = SMB_REALLOC(*pparams, 10);
1489 return ERROR_DOS(ERRDOS,ERRnomem);
1492 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1494 return(UNIXERROR(ERRDOS,ERRbadfile));
1496 /* Save the wildcard match and attribs we are using on this directory -
1497 needed as lanman2 assumes these are being saved between calls */
1499 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1500 dptr_close(&dptr_num);
1501 return ERROR_DOS(ERRDOS,ERRnomem);
1504 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1506 /* We don't need to check for VOL here as this is returned by
1507 a different TRANS2 call. */
1509 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1510 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1511 dont_descend = True;
1514 space_remaining = max_data_bytes;
1515 out_of_space = False;
1517 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1518 BOOL got_exact_match = False;
1520 /* this is a heuristic to avoid seeking the dirptr except when
1521 absolutely necessary. It allows for a filename of about 40 chars */
1522 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1523 out_of_space = True;
1526 finished = !get_lanman2_dir_entry(conn,
1528 mask,dirtype,info_level,
1529 requires_resume_key,dont_descend,
1530 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1534 if (finished && out_of_space)
1537 if (!finished && !out_of_space)
1541 * As an optimisation if we know we aren't looking
1542 * for a wildcard name (ie. the name matches the wildcard exactly)
1543 * then we can finish on any (first) match.
1544 * This speeds up large directory searches. JRA.
1550 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1553 /* Check if we can close the dirptr */
1554 if(close_after_first || (finished && close_if_end)) {
1555 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1556 dptr_close(&dptr_num);
1560 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1561 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1562 * the protocol level is less than NT1. Tested with smbclient. JRA.
1563 * This should fix the OS/2 client bug #2335.
1566 if(numentries == 0) {
1567 dptr_close(&dptr_num);
1568 if (Protocol < PROTOCOL_NT1) {
1569 return ERROR_DOS(ERRDOS,ERRnofiles);
1571 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1575 /* At this point pdata points to numentries directory entries. */
1577 /* Set up the return parameter block */
1578 SSVAL(params,0,dptr_num);
1579 SSVAL(params,2,numentries);
1580 SSVAL(params,4,finished);
1581 SSVAL(params,6,0); /* Never an EA error */
1582 SSVAL(params,8,last_entry_off);
1584 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1586 if ((! *directory) && dptr_path(dptr_num))
1587 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1589 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1590 smb_fn_name(CVAL(inbuf,smb_com)),
1591 mask, directory, dirtype, numentries ) );
1594 * Force a name mangle here to ensure that the
1595 * mask as an 8.3 name is top of the mangled cache.
1596 * The reasons for this are subtle. Don't remove
1597 * this code unless you know what you are doing
1598 * (see PR#13758). JRA.
1601 if(!mangle_is_8_3_wildcards( mask, False))
1602 mangle_map(mask, True, True, SNUM(conn));
1607 /****************************************************************************
1608 Reply to a TRANS2_FINDNEXT.
1609 ****************************************************************************/
1611 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1612 char **pparams, int total_params, char **ppdata, int total_data,
1613 unsigned int max_data_bytes)
1615 /* We must be careful here that we don't return more than the
1616 allowed number of data bytes. If this means returning fewer than
1617 maxentries then so be it. We assume that the redirector has
1618 enough room for the fixed number of parameter bytes it has
1620 char *params = *pparams;
1621 char *pdata = *ppdata;
1622 int dptr_num = SVAL(params,0);
1623 int maxentries = SVAL(params,2);
1624 uint16 info_level = SVAL(params,4);
1625 uint32 resume_key = IVAL(params,6);
1626 uint16 findnext_flags = SVAL(params,10);
1627 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1628 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1629 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1630 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1631 pstring resume_name;
1637 int i, last_entry_off=0;
1638 BOOL finished = False;
1639 BOOL dont_descend = False;
1640 BOOL out_of_space = False;
1641 int space_remaining;
1642 NTSTATUS ntstatus = NT_STATUS_OK;
1644 if (total_params < 12)
1645 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1647 *mask = *directory = *resume_name = 0;
1649 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1650 if (!NT_STATUS_IS_OK(ntstatus)) {
1651 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1652 complain (it thinks we're asking for the directory above the shared
1653 path or an invalid name). Catch this as the resume name is only compared, never used in
1654 a file access. JRA. */
1655 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1656 pstrcpy(resume_name, "..");
1657 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1658 pstrcpy(resume_name, ".");
1660 return ERROR_NT(ntstatus);
1664 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1665 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1666 resume_key = %d resume name = %s continue=%d level = %d\n",
1667 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1668 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1671 /* W2K3 seems to treat zero as 1. */
1675 switch (info_level) {
1676 case SMB_FIND_INFO_STANDARD:
1677 case SMB_FIND_EA_SIZE:
1678 case SMB_FIND_FILE_DIRECTORY_INFO:
1679 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1680 case SMB_FIND_FILE_NAMES_INFO:
1681 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1683 case SMB_FIND_FILE_UNIX:
1684 if (!lp_unix_extensions())
1685 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1688 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1691 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1693 return ERROR_DOS(ERRDOS,ERRnomem);
1696 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1698 /* Realloc the params space */
1699 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1700 if( params == NULL )
1701 return ERROR_DOS(ERRDOS,ERRnomem);
1705 /* Check that the dptr is valid */
1706 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1707 return ERROR_DOS(ERRDOS,ERRnofiles);
1709 string_set(&conn->dirpath,dptr_path(dptr_num));
1711 /* Get the wildcard mask from the dptr */
1712 if((p = dptr_wcard(dptr_num))== NULL) {
1713 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1714 return ERROR_DOS(ERRDOS,ERRnofiles);
1718 pstrcpy(directory,conn->dirpath);
1720 /* Get the attr mask from the dptr */
1721 dirtype = dptr_attr(dptr_num);
1723 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
1724 dptr_num, mask, dirtype,
1726 dptr_TellDir(conn->dirptr)));
1728 /* We don't need to check for VOL here as this is returned by
1729 a different TRANS2 call. */
1731 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1732 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1733 dont_descend = True;
1736 space_remaining = max_data_bytes;
1737 out_of_space = False;
1740 * Seek to the correct position. We no longer use the resume key but
1741 * depend on the last file name instead.
1744 if(*resume_name && !continue_bit) {
1747 long current_pos = 0;
1749 * Remember, mangle_map is called by
1750 * get_lanman2_dir_entry(), so the resume name
1751 * could be mangled. Ensure we check the unmangled name.
1754 if (mangle_is_mangled(resume_name)) {
1755 mangle_check_cache(resume_name, sizeof(resume_name)-1);
1759 * Fix for NT redirector problem triggered by resume key indexes
1760 * changing between directory scans. We now return a resume key of 0
1761 * and instead look for the filename to continue from (also given
1762 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1763 * findfirst/findnext (as is usual) then the directory pointer
1764 * should already be at the correct place.
1767 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
1768 } /* end if resume_name && !continue_bit */
1770 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1771 BOOL got_exact_match = False;
1773 /* this is a heuristic to avoid seeking the dirptr except when
1774 absolutely necessary. It allows for a filename of about 40 chars */
1775 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1776 out_of_space = True;
1779 finished = !get_lanman2_dir_entry(conn,
1781 mask,dirtype,info_level,
1782 requires_resume_key,dont_descend,
1783 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1787 if (finished && out_of_space)
1790 if (!finished && !out_of_space)
1794 * As an optimisation if we know we aren't looking
1795 * for a wildcard name (ie. the name matches the wildcard exactly)
1796 * then we can finish on any (first) match.
1797 * This speeds up large directory searches. JRA.
1803 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1806 /* Check if we can close the dirptr */
1807 if(close_after_request || (finished && close_if_end)) {
1808 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1809 dptr_close(&dptr_num); /* This frees up the saved mask */
1812 /* Set up the return parameter block */
1813 SSVAL(params,0,numentries);
1814 SSVAL(params,2,finished);
1815 SSVAL(params,4,0); /* Never an EA error */
1816 SSVAL(params,6,last_entry_off);
1818 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1820 if ((! *directory) && dptr_path(dptr_num))
1821 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1823 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1824 smb_fn_name(CVAL(inbuf,smb_com)),
1825 mask, directory, dirtype, numentries ) );
1830 /****************************************************************************
1831 Reply to a TRANS2_QFSINFO (query filesystem info).
1832 ****************************************************************************/
1834 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1835 char **pparams, int total_params, char **ppdata, int total_data,
1836 unsigned int max_data_bytes)
1838 char *pdata = *ppdata;
1839 char *params = *pparams;
1840 uint16 info_level = SVAL(params,0);
1843 char *vname = volume_label(SNUM(conn));
1844 int snum = SNUM(conn);
1845 char *fstype = lp_fstype(SNUM(conn));
1848 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1850 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1851 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1852 return ERROR_DOS(ERRSRV,ERRinvdevice);
1855 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1856 if ( pdata == NULL )
1857 return ERROR_DOS(ERRDOS,ERRnomem);
1860 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1862 switch (info_level) {
1863 case SMB_INFO_ALLOCATION:
1865 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1867 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1868 return(UNIXERROR(ERRHRD,ERRgeneral));
1871 block_size = lp_block_size(snum);
1872 if (bsize < block_size) {
1873 SMB_BIG_UINT factor = block_size/bsize;
1878 if (bsize > block_size) {
1879 SMB_BIG_UINT factor = bsize/block_size;
1884 bytes_per_sector = 512;
1885 sectors_per_unit = bsize/bytes_per_sector;
1887 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1888 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1889 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1891 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1892 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1893 SIVAL(pdata,l1_cUnit,dsize);
1894 SIVAL(pdata,l1_cUnitAvail,dfree);
1895 SSVAL(pdata,l1_cbSector,bytes_per_sector);
1899 case SMB_INFO_VOLUME:
1900 /* Return volume name */
1902 * Add volume serial number - hash of a combination of
1903 * the called hostname and the service name.
1905 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
1906 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1907 SCVAL(pdata,l2_vol_cch,len);
1908 data_len = l2_vol_szVolLabel + len;
1909 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1910 (unsigned)st.st_ctime, len, vname));
1913 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1914 case SMB_FS_ATTRIBUTE_INFORMATION:
1917 #if defined(HAVE_SYS_QUOTAS)
1918 quota_flag = FILE_VOLUME_QUOTAS;
1921 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1922 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1923 quota_flag); /* FS ATTRIBUTES */
1925 SIVAL(pdata,4,255); /* Max filename component length */
1926 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1927 and will think we can't do long filenames */
1928 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1930 data_len = 12 + len;
1933 case SMB_QUERY_FS_LABEL_INFO:
1934 case SMB_FS_LABEL_INFORMATION:
1935 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1940 case SMB_QUERY_FS_VOLUME_INFO:
1941 case SMB_FS_VOLUME_INFORMATION:
1944 * Add volume serial number - hash of a combination of
1945 * the called hostname and the service name.
1947 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1948 (str_checksum(get_local_machine_name())<<16));
1950 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1951 SIVAL(pdata,12,len);
1953 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1954 (int)strlen(vname),vname, lp_servicename(snum)));
1957 case SMB_QUERY_FS_SIZE_INFO:
1958 case SMB_FS_SIZE_INFORMATION:
1960 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1962 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1963 return(UNIXERROR(ERRHRD,ERRgeneral));
1965 block_size = lp_block_size(snum);
1966 if (bsize < block_size) {
1967 SMB_BIG_UINT factor = block_size/bsize;
1972 if (bsize > block_size) {
1973 SMB_BIG_UINT factor = bsize/block_size;
1978 bytes_per_sector = 512;
1979 sectors_per_unit = bsize/bytes_per_sector;
1980 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1981 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1982 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1983 SBIG_UINT(pdata,0,dsize);
1984 SBIG_UINT(pdata,8,dfree);
1985 SIVAL(pdata,16,sectors_per_unit);
1986 SIVAL(pdata,20,bytes_per_sector);
1990 case SMB_FS_FULL_SIZE_INFORMATION:
1992 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1994 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1995 return(UNIXERROR(ERRHRD,ERRgeneral));
1997 block_size = lp_block_size(snum);
1998 if (bsize < block_size) {
1999 SMB_BIG_UINT factor = block_size/bsize;
2004 if (bsize > block_size) {
2005 SMB_BIG_UINT factor = bsize/block_size;
2010 bytes_per_sector = 512;
2011 sectors_per_unit = bsize/bytes_per_sector;
2012 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2013 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2014 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2015 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2016 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2017 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2018 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2019 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2023 case SMB_QUERY_FS_DEVICE_INFO:
2024 case SMB_FS_DEVICE_INFORMATION:
2026 SIVAL(pdata,0,0); /* dev type */
2027 SIVAL(pdata,4,0); /* characteristics */
2030 #ifdef HAVE_SYS_QUOTAS
2031 case SMB_FS_QUOTA_INFORMATION:
2033 * what we have to send --metze:
2035 * Unknown1: 24 NULL bytes
2036 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2037 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2038 * Quota Flags: 2 byte :
2039 * Unknown3: 6 NULL bytes
2043 * details for Quota Flags:
2045 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2046 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2047 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2048 * 0x0001 Enable Quotas: enable quota for this fs
2052 /* we need to fake up a fsp here,
2053 * because its not send in this call
2056 SMB_NTQUOTA_STRUCT quotas;
2059 ZERO_STRUCT(quotas);
2066 if (current_user.uid != 0) {
2067 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2068 lp_servicename(SNUM(conn)),conn->user));
2069 return ERROR_DOS(ERRDOS,ERRnoaccess);
2072 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2073 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2074 return ERROR_DOS(ERRSRV,ERRerror);
2079 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2081 /* Unknown1 24 NULL bytes*/
2082 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2083 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2084 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2086 /* Default Soft Quota 8 bytes */
2087 SBIG_UINT(pdata,24,quotas.softlim);
2089 /* Default Hard Quota 8 bytes */
2090 SBIG_UINT(pdata,32,quotas.hardlim);
2092 /* Quota flag 2 bytes */
2093 SSVAL(pdata,40,quotas.qflags);
2095 /* Unknown3 6 NULL bytes */
2101 #endif /* HAVE_SYS_QUOTAS */
2102 case SMB_FS_OBJECTID_INFORMATION:
2107 * Query the version and capabilities of the CIFS UNIX extensions
2111 case SMB_QUERY_CIFS_UNIX_INFO:
2112 if (!lp_unix_extensions())
2113 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2115 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2116 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2117 SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
2120 case SMB_MAC_QUERY_FS_INFO:
2122 * Thursby MAC extension... ONLY on NTFS filesystems
2123 * once we do streams then we don't need this
2125 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2127 SIVAL(pdata,84,0x100); /* Don't support mac... */
2132 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2136 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2138 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2143 #ifdef HAVE_SYS_QUOTAS
2144 /****************************************************************************
2145 Reply to a TRANS2_SETFSINFO (set filesystem info).
2146 ****************************************************************************/
2148 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2149 char **pparams, int total_params, char **ppdata, int total_data,
2150 unsigned int max_data_bytes)
2152 char *pdata = *ppdata;
2153 char *params = *pparams;
2154 files_struct *fsp = NULL;
2157 SMB_NTQUOTA_STRUCT quotas;
2159 ZERO_STRUCT(quotas);
2161 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2164 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2165 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2166 lp_servicename(SNUM(conn)),conn->user));
2167 return ERROR_DOS(ERRSRV,ERRaccess);
2171 if (total_params < 4) {
2172 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2174 return ERROR_DOS(ERRDOS,ERRinvalidparam);
2177 fsp = file_fsp(params,0);
2179 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2180 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2181 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2184 info_level = SVAL(params,2);
2186 switch(info_level) {
2187 case SMB_FS_QUOTA_INFORMATION:
2188 /* note: normaly there're 48 bytes,
2189 * but we didn't use the last 6 bytes for now
2192 if (total_data < 42) {
2193 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2195 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2198 /* unknown_1 24 NULL bytes in pdata*/
2200 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2201 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2202 #ifdef LARGE_SMB_OFF_T
2203 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2204 #else /* LARGE_SMB_OFF_T */
2205 if ((IVAL(pdata,28) != 0)&&
2206 ((quotas.softlim != 0xFFFFFFFF)||
2207 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2208 /* more than 32 bits? */
2209 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2211 #endif /* LARGE_SMB_OFF_T */
2213 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2214 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2215 #ifdef LARGE_SMB_OFF_T
2216 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2217 #else /* LARGE_SMB_OFF_T */
2218 if ((IVAL(pdata,36) != 0)&&
2219 ((quotas.hardlim != 0xFFFFFFFF)||
2220 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2221 /* more than 32 bits? */
2222 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2224 #endif /* LARGE_SMB_OFF_T */
2226 /* quota_flags 2 bytes **/
2227 quotas.qflags = SVAL(pdata,40);
2229 /* unknown_2 6 NULL bytes follow*/
2231 /* now set the quotas */
2232 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2233 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2234 return ERROR_DOS(ERRSRV,ERRerror);
2239 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2241 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2246 * sending this reply works fine,
2247 * but I'm not sure it's the same
2248 * like windows do...
2251 outsize = set_message(outbuf,10,0,True);
2255 #endif /* HAVE_SYS_QUOTAS */
2257 /****************************************************************************
2258 Utility function to set bad path error.
2259 ****************************************************************************/
2261 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2263 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2264 err, (int)bad_path ));
2268 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2270 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2273 return UNIXERROR(def_class,def_code);
2276 #if defined(HAVE_POSIX_ACLS)
2277 /****************************************************************************
2278 Utility function to count the number of entries in a POSIX acl.
2279 ****************************************************************************/
2281 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2283 unsigned int ace_count = 0;
2284 int entry_id = SMB_ACL_FIRST_ENTRY;
2285 SMB_ACL_ENTRY_T entry;
2287 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2289 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2290 entry_id = SMB_ACL_NEXT_ENTRY;
2297 /****************************************************************************
2298 Utility function to marshall a POSIX acl into wire format.
2299 ****************************************************************************/
2301 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2303 int entry_id = SMB_ACL_FIRST_ENTRY;
2304 SMB_ACL_ENTRY_T entry;
2306 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2307 SMB_ACL_TAG_T tagtype;
2308 SMB_ACL_PERMSET_T permset;
2309 unsigned char perms = 0;
2310 unsigned int own_grp;
2313 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2314 entry_id = SMB_ACL_NEXT_ENTRY;
2317 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2318 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2322 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2323 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2327 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2328 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2329 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2331 SCVAL(pdata,1,perms);
2334 case SMB_ACL_USER_OBJ:
2335 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2336 own_grp = (unsigned int)pst->st_uid;
2337 SIVAL(pdata,2,own_grp);
2342 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2344 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2346 own_grp = (unsigned int)*puid;
2347 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2348 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2349 SIVAL(pdata,2,own_grp);
2353 case SMB_ACL_GROUP_OBJ:
2354 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2355 own_grp = (unsigned int)pst->st_gid;
2356 SIVAL(pdata,2,own_grp);
2361 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2363 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2365 own_grp = (unsigned int)*pgid;
2366 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2367 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2368 SIVAL(pdata,2,own_grp);
2373 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2374 SIVAL(pdata,2,0xFFFFFFFF);
2375 SIVAL(pdata,6,0xFFFFFFFF);
2378 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2379 SIVAL(pdata,2,0xFFFFFFFF);
2380 SIVAL(pdata,6,0xFFFFFFFF);
2383 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2386 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2393 /****************************************************************************
2394 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2395 file name or file id).
2396 ****************************************************************************/
2398 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2399 char **pparams, int total_params, char **ppdata, int total_data,
2400 unsigned int max_data_bytes)
2402 char *params = *pparams;
2403 char *pdata = *ppdata;
2404 uint16 tran_call = SVAL(inbuf, smb_setup0);
2407 SMB_OFF_T file_size=0;
2408 SMB_BIG_UINT allocation_size=0;
2409 unsigned int data_size = 0;
2410 unsigned int param_size = 2;
2411 SMB_STRUCT_STAT sbuf;
2412 pstring fname, dos_fname;
2417 BOOL bad_path = False;
2418 BOOL delete_pending = False;
2421 files_struct *fsp = NULL;
2422 TALLOC_CTX *ea_ctx = NULL;
2423 struct ea_list *ea_list = NULL;
2424 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2427 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2431 if (tran_call == TRANSACT2_QFILEINFO) {
2432 if (total_params < 4)
2433 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2435 fsp = file_fsp(params,0);
2436 info_level = SVAL(params,2);
2438 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2440 if(fsp && (fsp->fake_file_handle)) {
2442 * This is actually for the QUOTA_FAKE_FILE --metze
2445 pstrcpy(fname, fsp->fsp_name);
2446 /* We know this name is ok, it's already passed the checks. */
2448 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2450 * This is actually a QFILEINFO on a directory
2451 * handle (returned from an NT SMB). NT5.0 seems
2452 * to do this call. JRA.
2454 /* We know this name is ok, it's already passed the checks. */
2455 pstrcpy(fname, fsp->fsp_name);
2457 if (INFO_LEVEL_IS_UNIX(info_level)) {
2458 /* Always do lstat for UNIX calls. */
2459 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2460 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2461 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2463 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2464 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2465 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2468 delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2471 * Original code - this is an open file.
2473 CHECK_FSP(fsp,conn);
2475 pstrcpy(fname, fsp->fsp_name);
2476 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2477 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2478 return(UNIXERROR(ERRDOS,ERRbadfid));
2480 pos = fsp->position_information;
2481 delete_pending = fsp->delete_on_close;
2482 desired_access = fsp->desired_access;
2485 NTSTATUS status = NT_STATUS_OK;
2488 if (total_params < 6)
2489 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2491 info_level = SVAL(params,0);
2493 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2495 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2496 if (!NT_STATUS_IS_OK(status)) {
2497 return ERROR_NT(status);
2500 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2502 unix_convert(fname,conn,0,&bad_path,&sbuf);
2504 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2506 if (!check_name(fname,conn)) {
2507 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2508 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2511 if (INFO_LEVEL_IS_UNIX(info_level)) {
2512 /* Always do lstat for UNIX calls. */
2513 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2514 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2515 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2517 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2518 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2519 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2523 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2524 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2526 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2527 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2529 p = strrchr_m(fname,'/');
2535 mode = dos_mode(conn,fname,&sbuf);
2537 mode = FILE_ATTRIBUTE_NORMAL;
2539 fullpathname = fname;
2540 file_size = get_file_size(sbuf);
2541 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2543 /* This is necessary, as otherwise the desktop.ini file in
2544 * this folder is ignored */
2545 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2549 /* Pull any EA list from the data portion. */
2550 if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2551 uint32 ea_size = IVAL(pdata,0);
2553 if (total_data > 0 && ea_size != total_data) {
2554 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2555 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2556 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2559 if (!lp_ea_support(SNUM(conn))) {
2560 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2563 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2564 return ERROR_NT(NT_STATUS_NO_MEMORY);
2567 /* Pull out the list of names. */
2568 ea_list = read_ea_list(ea_ctx, pdata, ea_size);
2570 talloc_destroy(ea_ctx);
2571 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2575 params = SMB_REALLOC(*pparams,2);
2576 if (params == NULL) {
2577 talloc_destroy(ea_ctx);
2578 return ERROR_NT(NT_STATUS_NO_MEMORY);
2581 memset((char *)params,'\0',2);
2582 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2583 pdata = SMB_REALLOC(*ppdata, data_size);
2584 if ( pdata == NULL ) {
2585 talloc_destroy(ea_ctx);
2586 return ERROR_NT(NT_STATUS_NO_MEMORY);
2590 memset((char *)pdata,'\0',data_size);
2592 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2595 if (fsp->pending_modtime) {
2596 /* the pending modtime overrides the current modtime */
2597 sbuf.st_mtime = fsp->pending_modtime;
2600 /* Do we have this path open ? */
2601 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2602 if (fsp1 && fsp1->pending_modtime) {
2603 /* the pending modtime overrides the current modtime */
2604 sbuf.st_mtime = fsp1->pending_modtime;
2608 if (lp_dos_filetime_resolution(SNUM(conn))) {
2610 sbuf.st_atime &= ~1;
2611 sbuf.st_ctime &= ~1;
2612 sbuf.st_mtime &= ~1;
2615 /* NT expects the name to be in an exact form of the *full*
2616 filename. See the trans2 torture test */
2617 if (strequal(base_name,".")) {
2618 pstrcpy(dos_fname, "\\");
2620 pstr_sprintf(dos_fname, "\\%s", fname);
2621 string_replace(dos_fname, '/', '\\');
2624 switch (info_level) {
2625 case SMB_INFO_STANDARD:
2626 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2628 put_dos_date2(pdata,l1_fdateCreation,c_time);
2629 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2630 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2631 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2632 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2633 SSVAL(pdata,l1_attrFile,mode);
2636 case SMB_INFO_QUERY_EA_SIZE:
2638 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2639 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2641 put_dos_date2(pdata,l1_fdateCreation,c_time);
2642 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2643 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2644 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2645 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2646 SSVAL(pdata,l1_attrFile,mode);
2647 SIVAL(pdata,l1_attrFile+2,ea_size);
2651 case SMB_INFO_IS_NAME_VALID:
2652 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2653 if (tran_call == TRANSACT2_QFILEINFO) {
2654 /* os/2 needs this ? really ?*/
2655 return ERROR_DOS(ERRDOS,ERRbadfunc);
2661 case SMB_INFO_QUERY_EAS_FROM_LIST:
2663 size_t total_ea_len = 0;
2664 struct ea_list *ea_file_list = NULL;
2666 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2667 put_dos_date2(pdata,0,c_time);
2668 put_dos_date2(pdata,4,sbuf.st_atime);
2669 put_dos_date2(pdata,8,sbuf.st_mtime);
2670 SIVAL(pdata,12,(uint32)file_size);
2671 SIVAL(pdata,16,(uint32)allocation_size);
2672 SIVAL(pdata,20,mode);
2674 ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2676 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
2678 if (!ea_list || (total_ea_len > data_size - 24)) {
2679 talloc_destroy(ea_ctx);
2684 data_size = fill_ea_buffer(ea_ctx, pdata + 24, data_size - 24, conn, ea_list);
2686 talloc_destroy(ea_ctx);
2690 case SMB_INFO_QUERY_ALL_EAS:
2692 /* We have data_size bytes to put EA's into. */
2693 size_t total_ea_len = 0;
2695 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2697 ea_ctx = talloc_init("ea_ctx");
2699 return ERROR_NT(NT_STATUS_NO_MEMORY);
2702 ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2703 if (!ea_list || (total_ea_len > data_size)) {
2704 talloc_destroy(ea_ctx);
2709 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
2710 talloc_destroy(ea_ctx);
2714 case SMB_FILE_BASIC_INFORMATION:
2715 case SMB_QUERY_FILE_BASIC_INFO:
2717 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2718 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2719 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2721 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2725 put_long_date(pdata,c_time);
2726 put_long_date(pdata+8,sbuf.st_atime);
2727 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2728 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2729 SIVAL(pdata,32,mode);
2731 DEBUG(5,("SMB_QFBI - "));
2733 time_t create_time = c_time;
2734 DEBUG(5,("create: %s ", ctime(&create_time)));
2736 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2737 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2738 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2739 DEBUG(5,("mode: %x\n", mode));
2743 case SMB_FILE_STANDARD_INFORMATION:
2744 case SMB_QUERY_FILE_STANDARD_INFO:
2746 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2748 SOFF_T(pdata,0,allocation_size);
2749 SOFF_T(pdata,8,file_size);
2750 if (delete_pending & sbuf.st_nlink)
2751 SIVAL(pdata,16,sbuf.st_nlink - 1);
2753 SIVAL(pdata,16,sbuf.st_nlink);
2755 SCVAL(pdata,21,(mode&aDIR)?1:0);
2758 case SMB_FILE_EA_INFORMATION:
2759 case SMB_QUERY_FILE_EA_INFO:
2761 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2762 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2764 SIVAL(pdata,0,ea_size);
2768 /* Get the 8.3 name - used if NT SMB was negotiated. */
2769 case SMB_QUERY_FILE_ALT_NAME_INFO:
2770 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2774 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2775 pstrcpy(short_name,base_name);
2776 /* Mangle if not already 8.3 */
2777 if(!mangle_is_8_3(short_name, True)) {
2778 mangle_map(short_name,True,True,SNUM(conn));
2780 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2781 data_size = 4 + len;
2786 case SMB_QUERY_FILE_NAME_INFO:
2788 this must be *exactly* right for ACLs on mapped drives to work
2790 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2791 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2792 data_size = 4 + len;
2796 case SMB_FILE_ALLOCATION_INFORMATION:
2797 case SMB_QUERY_FILE_ALLOCATION_INFO:
2798 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2800 SOFF_T(pdata,0,allocation_size);
2803 case SMB_FILE_END_OF_FILE_INFORMATION:
2804 case SMB_QUERY_FILE_END_OF_FILEINFO:
2805 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2807 SOFF_T(pdata,0,file_size);
2810 case SMB_QUERY_FILE_ALL_INFO:
2811 case SMB_FILE_ALL_INFORMATION:
2813 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2814 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2815 put_long_date(pdata,c_time);
2816 put_long_date(pdata+8,sbuf.st_atime);
2817 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2818 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2819 SIVAL(pdata,32,mode);
2821 SOFF_T(pdata,0,allocation_size);
2822 SOFF_T(pdata,8,file_size);
2823 if (delete_pending && sbuf.st_nlink)
2824 SIVAL(pdata,16,sbuf.st_nlink - 1);
2826 SIVAL(pdata,16,sbuf.st_nlink);
2827 SCVAL(pdata,20,delete_pending);
2828 SCVAL(pdata,21,(mode&aDIR)?1:0);
2830 SIVAL(pdata,0,ea_size);
2831 pdata += 4; /* EA info */
2832 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2835 data_size = PTR_DIFF(pdata,(*ppdata));
2838 case SMB_FILE_INTERNAL_INFORMATION:
2839 /* This should be an index number - looks like
2842 I think this causes us to fail the IFSKIT
2843 BasicFileInformationTest. -tpot */
2845 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2846 SIVAL(pdata,0,sbuf.st_dev);
2847 SIVAL(pdata,4,sbuf.st_ino);
2851 case SMB_FILE_ACCESS_INFORMATION:
2852 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2853 SIVAL(pdata,0,desired_access);
2857 case SMB_FILE_NAME_INFORMATION:
2858 /* Pathname with leading '\'. */
2861 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2862 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2863 SIVAL(pdata,0,byte_len);
2864 data_size = 4 + byte_len;
2868 case SMB_FILE_DISPOSITION_INFORMATION:
2869 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2871 SCVAL(pdata,0,delete_pending);
2874 case SMB_FILE_POSITION_INFORMATION:
2875 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2877 SOFF_T(pdata,0,pos);
2880 case SMB_FILE_MODE_INFORMATION:
2881 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2882 SIVAL(pdata,0,mode);
2886 case SMB_FILE_ALIGNMENT_INFORMATION:
2887 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2888 SIVAL(pdata,0,0); /* No alignment needed. */
2894 * NT4 server just returns "invalid query" to this - if we try to answer
2895 * it then NTws gets a BSOD! (tridge).
2896 * W2K seems to want this. JRA.
2898 case SMB_QUERY_FILE_STREAM_INFO:
2900 case SMB_FILE_STREAM_INFORMATION:
2901 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2905 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2906 SIVAL(pdata,0,0); /* ??? */
2907 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2908 SOFF_T(pdata,8,file_size);
2909 SIVAL(pdata,16,allocation_size);
2910 SIVAL(pdata,20,0); /* ??? */
2911 data_size = 24 + byte_len;
2915 case SMB_QUERY_COMPRESSION_INFO:
2916 case SMB_FILE_COMPRESSION_INFORMATION:
2917 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2918 SOFF_T(pdata,0,file_size);
2919 SIVAL(pdata,8,0); /* ??? */
2920 SIVAL(pdata,12,0); /* ??? */
2924 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2925 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2926 put_long_date(pdata,c_time);
2927 put_long_date(pdata+8,sbuf.st_atime);
2928 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2929 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2930 SIVAL(pdata,32,allocation_size);
2931 SOFF_T(pdata,40,file_size);
2932 SIVAL(pdata,48,mode);
2933 SIVAL(pdata,52,0); /* ??? */
2937 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2938 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2939 SIVAL(pdata,0,mode);
2945 * CIFS UNIX Extensions.
2948 case SMB_QUERY_FILE_UNIX_BASIC:
2950 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2951 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2953 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2956 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2959 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2960 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2961 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2964 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2968 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2972 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2975 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2979 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2983 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2986 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2990 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2993 data_size = PTR_DIFF(pdata,(*ppdata));
2997 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2999 for (i=0; i<100; i++)
3000 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3006 case SMB_QUERY_FILE_UNIX_LINK:
3010 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3012 if(!S_ISLNK(sbuf.st_mode))
3013 return(UNIXERROR(ERRSRV,ERRbadlink));
3015 return(UNIXERROR(ERRDOS,ERRbadlink));
3017 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3019 return(UNIXERROR(ERRDOS,ERRnoaccess));
3021 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3023 data_size = PTR_DIFF(pdata,(*ppdata));
3028 #if defined(HAVE_POSIX_ACLS)
3029 case SMB_QUERY_POSIX_ACL:
3031 SMB_ACL_T file_acl = NULL;
3032 SMB_ACL_T def_acl = NULL;
3033 uint16 num_file_acls = 0;
3034 uint16 num_def_acls = 0;
3036 if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
3037 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
3039 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3042 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3043 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3045 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3048 if (S_ISDIR(sbuf.st_mode)) {
3049 if (fsp && fsp->is_directory) {
3050 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3052 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3054 def_acl = free_empty_sys_acl(conn, def_acl);
3057 num_file_acls = count_acl_entries(conn, file_acl);
3058 num_def_acls = count_acl_entries(conn, def_acl);
3060 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3061 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3063 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3064 SMB_POSIX_ACL_HEADER_SIZE) ));
3066 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3069 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3071 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3074 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3075 SSVAL(pdata,2,num_file_acls);
3076 SSVAL(pdata,4,num_def_acls);
3077 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3079 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3082 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3084 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3086 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3088 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3091 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3093 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3097 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3100 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3102 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3108 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3111 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3116 /****************************************************************************
3117 Deal with the internal needs of setting the delete on close flag. Note that
3118 as the tdb locking is recursive, it is safe to call this from within
3119 open_file_shared. JRA.
3120 ****************************************************************************/
3122 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
3124 if (delete_on_close) {
3126 * Only allow delete on close for writable files.
3129 if (!lp_delete_readonly(SNUM(fsp->conn))) {
3130 if (dosmode & aRONLY) {
3131 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
3133 return NT_STATUS_CANNOT_DELETE;
3138 * Only allow delete on close for writable shares.
3141 if (!CAN_WRITE(fsp->conn)) {
3142 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
3144 return NT_STATUS_ACCESS_DENIED;
3148 * Only allow delete on close for files/directories opened with delete intent.
3151 if (!(fsp->desired_access & DELETE_ACCESS)) {
3152 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
3154 return NT_STATUS_ACCESS_DENIED;
3158 if(fsp->is_directory) {
3159 fsp->directory_delete_on_close = delete_on_close;
3160 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3161 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3163 fsp->delete_on_close = delete_on_close;
3164 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3165 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3168 return NT_STATUS_OK;
3171 /****************************************************************************
3172 Sets the delete on close flag over all share modes on this file.
3173 Modify the share mode entry for all files open
3174 on this device and inode to tell other smbds we have
3175 changed the delete on close flag. This will be noticed
3176 in the close code, the last closer will delete the file
3178 ****************************************************************************/
3180 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3182 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3183 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3185 if (fsp->is_directory || fsp->is_stat)
3186 return NT_STATUS_OK;
3188 if (lock_share_entry_fsp(fsp) == False)
3189 return NT_STATUS_ACCESS_DENIED;
3191 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3192 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3194 unlock_share_entry_fsp(fsp);
3195 return NT_STATUS_ACCESS_DENIED;
3198 unlock_share_entry_fsp(fsp);
3199 return NT_STATUS_OK;
3202 /****************************************************************************
3203 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3205 ****************************************************************************/
3207 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3209 BOOL bad_path_oldname = False;
3210 BOOL bad_path_newname = False;
3211 SMB_STRUCT_STAT sbuf1, sbuf2;
3212 pstring last_component_oldname;
3213 pstring last_component_newname;
3214 NTSTATUS status = NT_STATUS_OK;
3220 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3221 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3224 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3225 if (bad_path_oldname) {
3226 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3229 /* Quick check for "." and ".." */
3230 if (last_component_oldname[0] == '.') {
3231 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3232 return NT_STATUS_OBJECT_NAME_INVALID;
3236 /* source must already exist. */
3237 if (!VALID_STAT(sbuf1)) {
3238 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3241 if (!check_name(oldname,conn)) {
3242 return NT_STATUS_ACCESS_DENIED;
3245 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3246 if (bad_path_newname) {
3247 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3250 /* Quick check for "." and ".." */
3251 if (last_component_newname[0] == '.') {
3252 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3253 return NT_STATUS_OBJECT_NAME_INVALID;
3257 /* Disallow if newname already exists. */
3258 if (VALID_STAT(sbuf2)) {
3259 return NT_STATUS_OBJECT_NAME_COLLISION;
3262 if (!check_name(newname,conn)) {
3263 return NT_STATUS_ACCESS_DENIED;
3266 /* No links from a directory. */
3267 if (S_ISDIR(sbuf1.st_mode)) {
3268 return NT_STATUS_FILE_IS_A_DIRECTORY;
3271 /* Ensure this is within the share. */
3272 if (!reduce_name(conn, oldname) != 0)
3273 return NT_STATUS_ACCESS_DENIED;
3275 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3277 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3278 status = map_nt_error_from_unix(errno);
3279 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3280 nt_errstr(status), newname, oldname));
3286 /****************************************************************************
3287 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3288 ****************************************************************************/
3290 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3291 char **pparams, int total_params, char **ppdata, int total_data,
3292 unsigned int max_data_bytes)
3294 char *params = *pparams;
3295 char *pdata = *ppdata;
3296 uint16 tran_call = SVAL(inbuf, smb_setup0);
3301 SMB_STRUCT_STAT sbuf;
3304 BOOL bad_path = False;
3305 files_struct *fsp = NULL;
3306 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3307 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3308 mode_t unixmode = 0;
3309 NTSTATUS status = NT_STATUS_OK;
3312 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3316 if (tran_call == TRANSACT2_SETFILEINFO) {
3317 if (total_params < 4)
3318 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3320 fsp = file_fsp(params,0);
3321 info_level = SVAL(params,2);
3323 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3325 * This is actually a SETFILEINFO on a directory
3326 * handle (returned from an NT SMB). NT5.0 seems
3327 * to do this call. JRA.
3329 pstrcpy(fname, fsp->fsp_name);
3330 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3331 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3332 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3334 } else if (fsp && fsp->print_file) {
3336 * Doing a DELETE_ON_CLOSE should cancel a print job.
3338 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3339 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3341 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3344 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3347 return (UNIXERROR(ERRDOS,ERRbadpath));
3350 * Original code - this is an open file.
3352 CHECK_FSP(fsp,conn);
3354 pstrcpy(fname, fsp->fsp_name);
3357 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3358 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3359 return(UNIXERROR(ERRDOS,ERRbadfid));
3364 if (total_params < 6)
3365 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3367 info_level = SVAL(params,0);
3368 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3369 if (!NT_STATUS_IS_OK(status)) {
3370 return ERROR_NT(status);
3372 unix_convert(fname,conn,0,&bad_path,&sbuf);
3374 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3378 * For CIFS UNIX extensions the target name may not exist.
3381 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3382 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3383 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3386 if(!check_name(fname, conn)) {
3387 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3392 if (!CAN_WRITE(conn))
3393 return ERROR_DOS(ERRSRV,ERRaccess);
3395 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3396 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3398 if (VALID_STAT(sbuf))
3399 unixmode = sbuf.st_mode;
3401 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3402 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3404 /* Realloc the parameter and data sizes */
3405 params = SMB_REALLOC(*pparams,2);
3407 return ERROR_DOS(ERRDOS,ERRnomem);
3412 if (fsp && fsp->pending_modtime) {
3413 /* the pending modtime overrides the current modtime */
3414 sbuf.st_mtime = fsp->pending_modtime;
3417 size = get_file_size(sbuf);
3418 tvs.modtime = sbuf.st_mtime;
3419 tvs.actime = sbuf.st_atime;
3420 dosmode = dos_mode(conn,fname,&sbuf);
3421 unixmode = sbuf.st_mode;
3423 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3424 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3426 switch (info_level) {
3427 case SMB_INFO_STANDARD:
3429 if (total_data < 12)
3430 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3433 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3435 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3439 case SMB_INFO_SET_EA:
3440 status = set_ea(conn, fsp, fname, pdata, total_data);
3441 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3442 return ERROR_NT(status);
3445 /* XXXX um, i don't think this is right.
3446 it's also not in the cifs6.txt spec.
3448 case SMB_INFO_QUERY_EAS_FROM_LIST:
3449 if (total_data < 28)
3450 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3452 tvs.actime = make_unix_date2(pdata+8);
3453 tvs.modtime = make_unix_date2(pdata+12);
3454 size = IVAL(pdata,16);
3455 dosmode = IVAL(pdata,24);
3458 /* XXXX nor this. not in cifs6.txt, either. */
3459 case SMB_INFO_QUERY_ALL_EAS:
3460 if (total_data < 28)
3461 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3463 tvs.actime = make_unix_date2(pdata+8);
3464 tvs.modtime = make_unix_date2(pdata+12);
3465 size = IVAL(pdata,16);
3466 dosmode = IVAL(pdata,24);
3469 case SMB_SET_FILE_BASIC_INFO:
3470 case SMB_FILE_BASIC_INFORMATION:
3472 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3474 time_t changed_time;
3476 if (total_data < 36)
3477 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3479 /* Ignore create time at offset pdata. */
3482 tvs.actime = interpret_long_date(pdata+8);
3484 write_time = interpret_long_date(pdata+16);
3485 changed_time = interpret_long_date(pdata+24);
3487 tvs.modtime = MIN(write_time, changed_time);
3489 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3490 tvs.modtime = write_time;
3492 /* Prefer a defined time to an undefined one. */
3493 if (null_mtime(tvs.modtime)) {
3494 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3498 dosmode = IVAL(pdata,32);
3502 case SMB_FILE_ALLOCATION_INFORMATION:
3503 case SMB_SET_FILE_ALLOCATION_INFO:
3506 SMB_BIG_UINT allocation_size;
3509 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3511 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3512 #ifdef LARGE_SMB_OFF_T
3513 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3514 #else /* LARGE_SMB_OFF_T */
3515 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3516 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3517 #endif /* LARGE_SMB_OFF_T */
3518 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3519 fname, (double)allocation_size ));
3521 if (allocation_size) {
3522 allocation_size = smb_roundup(conn, allocation_size);
3525 if(allocation_size != get_file_size(sbuf)) {
3526 SMB_STRUCT_STAT new_sbuf;
3528 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3529 fname, (double)allocation_size ));
3532 files_struct *new_fsp = NULL;
3533 int access_mode = 0;
3536 if(global_oplock_break) {
3537 /* Queue this file modify as we are the process of an oplock break. */
3539 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3540 DEBUGADD(2,( "in oplock break state.\n"));
3542 push_oplock_pending_smb_message(inbuf, length);
3546 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3547 SET_OPEN_MODE(DOS_OPEN_RDWR),
3548 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3549 FILE_ATTRIBUTE_NORMAL,
3550 INTERNAL_OPEN_ONLY, &access_mode, &action);
3552 if (new_fsp == NULL)
3553 return(UNIXERROR(ERRDOS,ERRbadpath));
3554 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3555 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3556 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3557 new_fsp->fnum, strerror(errno)));
3560 close_file(new_fsp,True);
3562 ret = vfs_allocate_file_space(fsp, allocation_size);
3563 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3564 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3565 fsp->fnum, strerror(errno)));
3570 return ERROR_NT(NT_STATUS_DISK_FULL);
3572 /* Allocate can truncate size... */
3573 size = get_file_size(new_sbuf);
3579 case SMB_FILE_END_OF_FILE_INFORMATION:
3580 case SMB_SET_FILE_END_OF_FILE_INFO:
3583 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3585 size = IVAL(pdata,0);
3586 #ifdef LARGE_SMB_OFF_T
3587 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3588 #else /* LARGE_SMB_OFF_T */
3589 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3590 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3591 #endif /* LARGE_SMB_OFF_T */
3592 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3596 case SMB_FILE_DISPOSITION_INFORMATION:
3597 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3599 BOOL delete_on_close;
3602 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3604 delete_on_close = (CVAL(pdata,0) ? True : False);
3606 /* Just ignore this set on a path. */
3607 if (tran_call != TRANSACT2_SETFILEINFO)
3611 return(UNIXERROR(ERRDOS,ERRbadfid));
3613 status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3615 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3616 return ERROR_NT(status);
3618 /* The set is across all open files on this dev/inode pair. */
3619 status =set_delete_on_close_over_all(fsp, delete_on_close);
3620 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3621 return ERROR_NT(status);
3626 case SMB_FILE_POSITION_INFORMATION:
3628 SMB_BIG_UINT position_information;
3631 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3633 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3634 #ifdef LARGE_SMB_OFF_T
3635 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3636 #else /* LARGE_SMB_OFF_T */
3637 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3638 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3639 #endif /* LARGE_SMB_OFF_T */
3640 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3641 fname, (double)position_information ));
3643 fsp->position_information = position_information;
3648 * CIFS UNIX extensions.
3651 case SMB_SET_FILE_UNIX_BASIC:
3653 uint32 raw_unixmode;
3655 if (total_data < 100)
3656 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3658 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3659 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3660 size=IVAL(pdata,0); /* first 8 Bytes are size */
3661 #ifdef LARGE_SMB_OFF_T
3662 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3663 #else /* LARGE_SMB_OFF_T */
3664 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3665 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3666 #endif /* LARGE_SMB_OFF_T */
3668 pdata+=24; /* ctime & st_blocks are not changed */
3669 tvs.actime = interpret_long_date(pdata); /* access_time */
3670 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
3672 set_owner = (uid_t)IVAL(pdata,0);
3674 set_grp = (gid_t)IVAL(pdata,0);
3676 raw_unixmode = IVAL(pdata,28);
3677 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3678 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3680 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3681 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3682 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3684 if (!VALID_STAT(sbuf)) {
3687 * The only valid use of this is to create character and block
3688 * devices, and named pipes. This is deprecated (IMHO) and
3689 * a new info level should be used for mknod. JRA.
3692 uint32 file_type = IVAL(pdata,0);
3693 #if defined(HAVE_MAKEDEV)
3694 uint32 dev_major = IVAL(pdata,4);
3695 uint32 dev_minor = IVAL(pdata,12);
3698 uid_t myuid = geteuid();
3699 gid_t mygid = getegid();
3700 SMB_DEV_T dev = (SMB_DEV_T)0;
3702 if (tran_call == TRANSACT2_SETFILEINFO)
3703 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3705 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3706 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3708 #if defined(HAVE_MAKEDEV)
3709 dev = makedev(dev_major, dev_minor);
3712 /* We can only create as the owner/group we are. */
3714 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3715 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3716 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3717 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3719 switch (file_type) {
3720 #if defined(S_IFIFO)
3721 case UNIX_TYPE_FIFO:
3722 unixmode |= S_IFIFO;
3725 #if defined(S_IFSOCK)
3726 case UNIX_TYPE_SOCKET:
3727 unixmode |= S_IFSOCK;
3730 #if defined(S_IFCHR)
3731 case UNIX_TYPE_CHARDEV:
3732 unixmode |= S_IFCHR;
3735 #if defined(S_IFBLK)
3736 case UNIX_TYPE_BLKDEV:
3737 unixmode |= S_IFBLK;
3741 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3744 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3745 0%o for file %s\n", (double)dev, unixmode, fname ));
3747 /* Ok - do the mknod. */
3748 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
3749 return(UNIXERROR(ERRDOS,ERRnoaccess));
3751 inherit_access_acl(conn, fname, unixmode);
3754 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3759 * Deal with the UNIX specific mode set.
3762 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3763 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3764 (unsigned int)unixmode, fname ));
3765 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3766 return(UNIXERROR(ERRDOS,ERRnoaccess));
3770 * Deal with the UNIX specific uid set.
3773 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3774 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3775 (unsigned int)set_owner, fname ));
3776 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3777 return(UNIXERROR(ERRDOS,ERRnoaccess));
3781 * Deal with the UNIX specific gid set.
3784 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3785 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3786 (unsigned int)set_owner, fname ));
3787 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3788 return(UNIXERROR(ERRDOS,ERRnoaccess));
3793 case SMB_SET_FILE_UNIX_LINK:
3795 pstring link_target;
3796 char *newname = fname;
3798 /* Set a symbolic link. */
3799 /* Don't allow this if follow links is false. */
3801 if (!lp_symlinks(SNUM(conn)))
3802 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3804 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
3806 /* !widelinks forces the target path to be within the share. */
3807 /* This means we can interpret the target as a pathname. */
3808 if (!lp_widelinks(SNUM(conn))) {
3810 char *last_dirp = NULL;
3812 unix_format(link_target);
3813 if (*link_target == '/') {
3814 /* No absolute paths allowed. */
3815 return(UNIXERROR(ERRDOS,ERRnoaccess));
3817 pstrcpy(rel_name, newname);
3818 last_dirp = strrchr_m(rel_name, '/');
3820 last_dirp[1] = '\0';
3822 pstrcpy(rel_name, "./");
3824 pstrcat(rel_name, link_target);
3826 if (!check_name(rel_name, conn)) {
3827 return(UNIXERROR(ERRDOS,ERRnoaccess));
3831 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3832 fname, link_target ));
3834 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
3835 return(UNIXERROR(ERRDOS,ERRnoaccess));
3837 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3841 case SMB_SET_FILE_UNIX_HLINK:
3844 char *newname = fname;
3846 /* Set a hard link. */
3847 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
3848 if (!NT_STATUS_IS_OK(status)) {
3849 return ERROR_NT(status);
3852 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3855 status = hardlink_internals(conn, oldname, newname);
3856 if (!NT_STATUS_IS_OK(status)) {
3857 return ERROR_NT(status);
3861 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3865 case SMB_FILE_RENAME_INFORMATION:
3874 if (total_data < 12)
3875 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3877 overwrite = (CVAL(pdata,0) ? True : False);
3878 root_fid = IVAL(pdata,4);
3879 len = IVAL(pdata,8);
3880 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
3881 if (!NT_STATUS_IS_OK(status)) {
3882 return ERROR_NT(status);
3885 /* Check the new name has no '/' characters. */
3886 if (strchr_m(newname, '/'))
3887 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3889 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3891 /* Create the base directory. */
3892 pstrcpy(base_name, fname);
3893 p = strrchr_m(base_name, '/');
3896 /* Append the new name. */
3897 pstrcat(base_name, "/");
3898 pstrcat(base_name, newname);
3901 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3902 fsp->fnum, fsp->fsp_name, base_name ));
3903 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
3905 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3907 status = rename_internals(conn, fname, base_name, 0, overwrite);
3909 if (!NT_STATUS_IS_OK(status)) {
3910 return ERROR_NT(status);
3912 process_pending_change_notify_queue((time_t)0);
3914 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3918 #if defined(HAVE_POSIX_ACLS)
3919 case SMB_SET_POSIX_ACL:
3921 uint16 posix_acl_version;
3922 uint16 num_file_acls;
3923 uint16 num_def_acls;
3924 BOOL valid_file_acls = True;
3925 BOOL valid_def_acls = True;
3927 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
3928 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3930 posix_acl_version = SVAL(pdata,0);
3931 num_file_acls = SVAL(pdata,2);
3932 num_def_acls = SVAL(pdata,4);
3934 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3935 valid_file_acls = False;
3939 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3940 valid_def_acls = False;
3944 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
3945 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3948 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
3949 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
3950 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3953 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
3954 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
3955 return(UNIXERROR(ERRDOS,ERRnoaccess));
3958 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
3959 pdata + SMB_POSIX_ACL_HEADER_SIZE +
3960 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
3961 return(UNIXERROR(ERRDOS,ERRnoaccess));
3965 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3971 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3974 /* get some defaults (no modifications) if any info is zero or -1. */
3975 if (null_mtime(tvs.actime)) {
3976 tvs.actime = sbuf.st_atime;
3979 if (null_mtime(tvs.modtime)) {
3980 tvs.modtime = sbuf.st_mtime;
3983 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3984 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3985 DEBUG(6,("size: %.0f ", (double)size));
3988 if (S_ISDIR(sbuf.st_mode))
3994 DEBUG(6,("dosmode: %x\n" , dosmode));
3996 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3997 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3998 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3999 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4002 * Only do this test if we are not explicitly
4003 * changing the size of a file.
4006 size = get_file_size(sbuf);
4010 * Try and set the times, size and mode of this file -
4011 * if they are different from the current values
4014 /* check the mode isn't different, before changing it */
4015 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4017 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4019 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4020 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4021 return(UNIXERROR(ERRDOS,ERRnoaccess));
4026 if (size != get_file_size(sbuf)) {
4030 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4031 fname, (double)size ));
4034 files_struct *new_fsp = NULL;
4035 int access_mode = 0;
4038 if(global_oplock_break) {
4039 /* Queue this file modify as we are the process of an oplock break. */
4041 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
4042 DEBUGADD(2,( "in oplock break state.\n"));
4044 push_oplock_pending_smb_message(inbuf, length);
4048 new_fsp = open_file_shared(conn, fname, &sbuf,
4049 SET_OPEN_MODE(DOS_OPEN_RDWR),
4050 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
4051 FILE_ATTRIBUTE_NORMAL,
4052 INTERNAL_OPEN_ONLY, &access_mode, &action);
4054 if (new_fsp == NULL)
4055 return(UNIXERROR(ERRDOS,ERRbadpath));
4056 ret = vfs_set_filelen(new_fsp, size);
4057 close_file(new_fsp,True);
4059 ret = vfs_set_filelen(fsp, size);
4063 return (UNIXERROR(ERRHRD,ERRdiskfull));
4067 * Finally the times.
4069 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4072 * This was a setfileinfo on an open file.
4073 * NT does this a lot. We also need to
4074 * set the time here, as it can be read by
4075 * FindFirst/FindNext and with the patch for bug #2045
4076 * in smbd/fileio.c it ensures that this timestamp is
4077 * kept sticky even after a write. We save the request
4078 * away and will set it on file close and after a write. JRA.
4081 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4082 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4083 fsp_set_pending_modtime(fsp, tvs.modtime);
4087 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4089 if(file_utime(conn, fname, &tvs)!=0) {
4090 return(UNIXERROR(ERRDOS,ERRnoaccess));
4095 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4100 /****************************************************************************
4101 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4102 ****************************************************************************/
4104 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4105 char **pparams, int total_params, char **ppdata, int total_data,
4106 unsigned int max_data_bytes)
4108 char *params = *pparams;
4111 SMB_STRUCT_STAT sbuf;
4112 BOOL bad_path = False;
4113 NTSTATUS status = NT_STATUS_OK;
4115 if (!CAN_WRITE(conn))
4116 return ERROR_DOS(ERRSRV,ERRaccess);
4118 if (total_params < 4)
4119 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4121 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4122 if (!NT_STATUS_IS_OK(status)) {
4123 return ERROR_NT(status);
4126 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4128 unix_convert(directory,conn,0,&bad_path,&sbuf);
4130 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4132 if (check_name(directory,conn))
4133 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4136 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4137 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4140 /* Realloc the parameter and data sizes */
4141 params = SMB_REALLOC(*pparams,2);
4143 return ERROR_DOS(ERRDOS,ERRnomem);
4148 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4153 /****************************************************************************
4154 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4155 We don't actually do this - we just send a null response.
4156 ****************************************************************************/
4158 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4159 char **pparams, int total_params, char **ppdata, int total_data,
4160 unsigned int max_data_bytes)
4162 static uint16 fnf_handle = 257;
4163 char *params = *pparams;
4166 if (total_params < 6)
4167 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4169 info_level = SVAL(params,4);
4170 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4172 switch (info_level) {
4177 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4180 /* Realloc the parameter and data sizes */
4181 params = SMB_REALLOC(*pparams,6);
4183 return ERROR_DOS(ERRDOS,ERRnomem);
4186 SSVAL(params,0,fnf_handle);
4187 SSVAL(params,2,0); /* No changes */
4188 SSVAL(params,4,0); /* No EA errors */
4195 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4200 /****************************************************************************
4201 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4202 changes). Currently this does nothing.
4203 ****************************************************************************/
4205 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4206 char **pparams, int total_params, char **ppdata, int total_data,
4207 unsigned int max_data_bytes)
4209 char *params = *pparams;
4211 DEBUG(3,("call_trans2findnotifynext\n"));
4213 /* Realloc the parameter and data sizes */
4214 params = SMB_REALLOC(*pparams,4);
4216 return ERROR_DOS(ERRDOS,ERRnomem);
4219 SSVAL(params,0,0); /* No changes */
4220 SSVAL(params,2,0); /* No EA errors */
4222 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4227 /****************************************************************************
4228 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4229 ****************************************************************************/
4231 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4232 char **pparams, int total_params, char **ppdata, int total_data,
4233 unsigned int max_data_bytes)
4235 char *params = *pparams;
4238 int max_referral_level;
4240 DEBUG(10,("call_trans2getdfsreferral\n"));
4242 if (total_params < 2)
4243 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4245 max_referral_level = SVAL(params,0);
4247 if(!lp_host_msdfs())
4248 return ERROR_DOS(ERRDOS,ERRbadfunc);
4250 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4251 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4252 return UNIXERROR(ERRDOS,ERRbadfile);
4254 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4255 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4260 #define LMCAT_SPL 0x53
4261 #define LMFUNC_GETJOBID 0x60
4263 /****************************************************************************
4264 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4265 ****************************************************************************/
4267 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4268 char **pparams, int total_params, char **ppdata, int total_data,
4269 unsigned int max_data_bytes)
4271 char *pdata = *ppdata;
4272 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4274 /* check for an invalid fid before proceeding */
4277 return(ERROR_DOS(ERRDOS,ERRbadfid));
4279 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4280 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4281 pdata = SMB_REALLOC(*ppdata, 32);
4283 return ERROR_DOS(ERRDOS,ERRnomem);
4286 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4287 CAN ACCEPT THIS IN UNICODE. JRA. */
4289 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4290 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4291 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4292 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4295 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4296 return ERROR_DOS(ERRSRV,ERRerror);
4300 /****************************************************************************
4301 Reply to a SMBfindclose (stop trans2 directory search).
4302 ****************************************************************************/
4304 int reply_findclose(connection_struct *conn,
4305 char *inbuf,char *outbuf,int length,int bufsize)
4308 int dptr_num=SVALS(inbuf,smb_vwv0);
4309 START_PROFILE(SMBfindclose);
4311 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4313 dptr_close(&dptr_num);
4315 outsize = set_message(outbuf,0,0,True);
4317 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4319 END_PROFILE(SMBfindclose);
4323 /****************************************************************************
4324 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4325 ****************************************************************************/
4327 int reply_findnclose(connection_struct *conn,
4328 char *inbuf,char *outbuf,int length,int bufsize)
4332 START_PROFILE(SMBfindnclose);
4334 dptr_num = SVAL(inbuf,smb_vwv0);
4336 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4338 /* We never give out valid handles for a
4339 findnotifyfirst - so any dptr_num is ok here.
4342 outsize = set_message(outbuf,0,0,True);
4344 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4346 END_PROFILE(SMBfindnclose);
4350 /****************************************************************************
4351 Reply to a SMBtranss2 - just ignore it!
4352 ****************************************************************************/
4354 int reply_transs2(connection_struct *conn,
4355 char *inbuf,char *outbuf,int length,int bufsize)
4357 START_PROFILE(SMBtranss2);
4358 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4359 END_PROFILE(SMBtranss2);
4363 /****************************************************************************
4364 Reply to a SMBtrans2.
4365 ****************************************************************************/
4367 int reply_trans2(connection_struct *conn,
4368 char *inbuf,char *outbuf,int length,int bufsize)
4371 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4372 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4373 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4375 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4376 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4377 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4378 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4379 int32 timeout = IVALS(inbuf,smb_timeout);
4381 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4382 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4383 char *params = NULL, *data = NULL;
4384 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4385 START_PROFILE(SMBtrans2);
4387 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4388 /* Queue this open message as we are the process of an
4391 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4392 DEBUGADD(2,( "in oplock break state.\n"));
4394 push_oplock_pending_smb_message(inbuf, length);
4395 END_PROFILE(SMBtrans2);
4399 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4400 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4401 END_PROFILE(SMBtrans2);
4402 return ERROR_DOS(ERRSRV,ERRaccess);
4405 outsize = set_message(outbuf,0,0,True);
4407 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4408 is so as a sanity check */
4411 * Need to have rc=0 for ioctl to get job id for OS/2.
4412 * Network printing will fail if function is not successful.
4413 * Similar function in reply.c will be used if protocol
4414 * is LANMAN1.0 instead of LM1.2X002.
4415 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4416 * outbuf doesn't have to be set(only job id is used).
4418 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4419 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4420 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4421 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4423 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4424 DEBUG(2,("Transaction is %d\n",tran_call));
4425 END_PROFILE(SMBtrans2);
4426 ERROR_DOS(ERRDOS,ERRinvalidparam);
4430 /* Allocate the space for the maximum needed parameters and data */
4431 if (total_params > 0)
4432 params = (char *)SMB_MALLOC(total_params);
4434 data = (char *)SMB_MALLOC(total_data);
4436 if ((total_params && !params) || (total_data && !data)) {
4437 DEBUG(2,("Out of memory in reply_trans2\n"));
4440 END_PROFILE(SMBtrans2);
4441 return ERROR_DOS(ERRDOS,ERRnomem);
4444 /* Copy the param and data bytes sent with this request into
4445 the params buffer */
4446 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4447 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4449 if (num_params > total_params || num_data > total_data)
4450 exit_server("invalid params in reply_trans2");
4453 unsigned int psoff = SVAL(inbuf, smb_psoff);
4454 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4456 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4457 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4459 memcpy( params, smb_base(inbuf) + psoff, num_params);
4462 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4463 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4465 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4466 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4468 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4471 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4473 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4474 /* We need to send an interim response then receive the rest
4475 of the parameter/data bytes */
4476 outsize = set_message(outbuf,0,0,True);
4477 srv_signing_trans_stop();
4478 if (!send_smb(smbd_server_fd(),outbuf))
4479 exit_server("reply_trans2: send_smb failed.");
4481 while (num_data_sofar < total_data ||
4482 num_params_sofar < total_params) {
4484 unsigned int param_disp;
4485 unsigned int param_off;
4486 unsigned int data_disp;
4487 unsigned int data_off;
4489 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4492 * The sequence number for the trans reply is always
4493 * based on the last secondary received.
4496 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4499 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4500 outsize = set_message(outbuf,0,0,True);
4502 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4504 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4505 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4509 /* Revise total_params and total_data in case
4510 they have changed downwards */
4511 if (SVAL(inbuf, smb_tpscnt) < total_params)
4512 total_params = SVAL(inbuf, smb_tpscnt);
4513 if (SVAL(inbuf, smb_tdscnt) < total_data)
4514 total_data = SVAL(inbuf, smb_tdscnt);
4516 num_params = SVAL(inbuf,smb_spscnt);
4517 param_off = SVAL(inbuf, smb_spsoff);
4518 param_disp = SVAL(inbuf, smb_spsdisp);
4519 num_params_sofar += num_params;
4521 num_data = SVAL(inbuf, smb_sdscnt);
4522 data_off = SVAL(inbuf, smb_sdsoff);
4523 data_disp = SVAL(inbuf, smb_sdsdisp);
4524 num_data_sofar += num_data;
4526 if (num_params_sofar > total_params || num_data_sofar > total_data)
4530 if (param_disp + num_params > total_params)
4532 if ((param_disp + num_params < param_disp) ||
4533 (param_disp + num_params < num_params))
4535 if (param_disp > total_params)
4537 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4538 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4540 if (params + param_disp < params)
4543 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
4546 if (data_disp + num_data > total_data)
4548 if ((data_disp + num_data < data_disp) ||
4549 (data_disp + num_data < num_data))
4551 if (data_disp > total_data)
4553 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4554 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4556 if (data + data_disp < data)
4559 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4564 if (Protocol >= PROTOCOL_NT1) {
4565 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4568 /* Now we must call the relevant TRANS2 function */
4570 case TRANSACT2_OPEN:
4571 START_PROFILE_NESTED(Trans2_open);
4572 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4573 ¶ms, total_params, &data, total_data, max_data_bytes);
4574 END_PROFILE_NESTED(Trans2_open);
4577 case TRANSACT2_FINDFIRST:
4578 START_PROFILE_NESTED(Trans2_findfirst);
4579 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4580 ¶ms, total_params, &data, total_data, max_data_bytes);
4581 END_PROFILE_NESTED(Trans2_findfirst);
4584 case TRANSACT2_FINDNEXT:
4585 START_PROFILE_NESTED(Trans2_findnext);
4586 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4587 ¶ms, total_params, &data, total_data, max_data_bytes);
4588 END_PROFILE_NESTED(Trans2_findnext);
4591 case TRANSACT2_QFSINFO:
4592 START_PROFILE_NESTED(Trans2_qfsinfo);
4593 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4594 ¶ms, total_params, &data, total_data, max_data_bytes);
4595 END_PROFILE_NESTED(Trans2_qfsinfo);
4598 #ifdef HAVE_SYS_QUOTAS
4599 case TRANSACT2_SETFSINFO:
4600 START_PROFILE_NESTED(Trans2_setfsinfo);
4601 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4602 ¶ms, total_params, &data, total_data, max_data_bytes);
4603 END_PROFILE_NESTED(Trans2_setfsinfo);
4606 case TRANSACT2_QPATHINFO:
4607 case TRANSACT2_QFILEINFO:
4608 START_PROFILE_NESTED(Trans2_qpathinfo);
4609 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4610 ¶ms, total_params, &data, total_data, max_data_bytes);
4611 END_PROFILE_NESTED(Trans2_qpathinfo);
4613 case TRANSACT2_SETPATHINFO:
4614 case TRANSACT2_SETFILEINFO:
4615 START_PROFILE_NESTED(Trans2_setpathinfo);
4616 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4617 ¶ms, total_params, &data, total_data, max_data_bytes);
4618 END_PROFILE_NESTED(Trans2_setpathinfo);
4621 case TRANSACT2_FINDNOTIFYFIRST:
4622 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4623 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4624 ¶ms, total_params, &data, total_data, max_data_bytes);
4625 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4628 case TRANSACT2_FINDNOTIFYNEXT:
4629 START_PROFILE_NESTED(Trans2_findnotifynext);
4630 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4631 ¶ms, total_params, &data, total_data, max_data_bytes);
4632 END_PROFILE_NESTED(Trans2_findnotifynext);
4634 case TRANSACT2_MKDIR:
4635 START_PROFILE_NESTED(Trans2_mkdir);
4636 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4637 ¶ms, total_params, &data, total_data, max_data_bytes);
4638 END_PROFILE_NESTED(Trans2_mkdir);
4641 case TRANSACT2_GET_DFS_REFERRAL:
4642 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4643 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4644 ¶ms, total_params, &data, total_data, max_data_bytes);
4645 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4647 case TRANSACT2_IOCTL:
4648 START_PROFILE_NESTED(Trans2_ioctl);
4649 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4650 ¶ms, total_params, &data, total_data, max_data_bytes);
4651 END_PROFILE_NESTED(Trans2_ioctl);
4654 /* Error in request */
4655 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4658 END_PROFILE(SMBtrans2);
4659 srv_signing_trans_stop();
4660 return ERROR_DOS(ERRSRV,ERRerror);
4663 /* As we do not know how many data packets will need to be
4664 returned here the various call_trans2xxxx calls
4665 must send their own. Thus a call_trans2xxx routine only
4666 returns a value other than -1 when it wants to send
4670 srv_signing_trans_stop();
4674 END_PROFILE(SMBtrans2);
4675 return outsize; /* If a correct response was needed the
4676 call_trans2xxx calls have already sent
4677 it. If outsize != -1 then it is returning */
4681 srv_signing_trans_stop();
4684 END_PROFILE(SMBtrans2);
4685 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);