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_NT(NT_STATUS_INVALID_PARAMETER);
683 open_mode = SVAL(params, 2);
684 open_attr = SVAL(params,6);
685 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
687 return_additional_info = BITSETW(params,0);
688 open_sattr = SVAL(params, 4);
689 open_time = make_unix_date3(params+8);
691 open_ofun = SVAL(params,12);
692 open_size = IVAL(params,14);
696 return(ERROR_DOS(ERRSRV,ERRaccess));
698 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
699 if (!NT_STATUS_IS_OK(status)) {
700 return ERROR_NT(status);
703 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
704 fname,open_mode, open_attr, open_ofun, open_size));
706 /* XXXX we need to handle passed times, sattr and flags */
708 unix_convert(fname,conn,0,&bad_path,&sbuf);
710 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
713 if (!check_name(fname,conn)) {
714 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
717 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
718 oplock_request, &rmode,&smb_action);
721 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
722 /* We have re-scheduled this call. */
723 clear_cached_errors();
726 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
729 size = get_file_size(sbuf);
730 fmode = dos_mode(conn,fname,&sbuf);
731 mtime = sbuf.st_mtime;
734 close_file(fsp,False);
735 return(ERROR_DOS(ERRDOS,ERRnoaccess));
738 /* Realloc the size of parameters and data we will return */
739 params = SMB_REALLOC(*pparams, 28);
741 return(ERROR_DOS(ERRDOS,ERRnomem));
744 memset((char *)params,'\0',28);
745 SSVAL(params,0,fsp->fnum);
746 SSVAL(params,2,fmode);
747 put_dos_date2(params,4, mtime);
748 SIVAL(params,8, (uint32)size);
749 SSVAL(params,12,rmode);
751 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
752 smb_action |= EXTENDED_OPLOCK_GRANTED;
754 SSVAL(params,18,smb_action);
757 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
759 SIVAL(params,20,inode);
761 /* Send the required number of replies */
762 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
767 /*********************************************************
768 Routine to check if a given string matches exactly.
769 as a special case a mask of "." does NOT match. That
770 is required for correct wildcard semantics
771 Case can be significant or not.
772 **********************************************************/
774 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
776 if (mask[0] == '.' && mask[1] == 0)
779 return strcmp(str,mask)==0;
780 if (StrCaseCmp(str,mask) != 0) {
783 if (ms_has_wild(str)) {
789 /****************************************************************************
790 Return the filetype for UNIX extensions.
791 ****************************************************************************/
793 static uint32 unix_filetype(mode_t mode)
796 return UNIX_TYPE_FILE;
797 else if(S_ISDIR(mode))
798 return UNIX_TYPE_DIR;
800 else if(S_ISLNK(mode))
801 return UNIX_TYPE_SYMLINK;
804 else if(S_ISCHR(mode))
805 return UNIX_TYPE_CHARDEV;
808 else if(S_ISBLK(mode))
809 return UNIX_TYPE_BLKDEV;
812 else if(S_ISFIFO(mode))
813 return UNIX_TYPE_FIFO;
816 else if(S_ISSOCK(mode))
817 return UNIX_TYPE_SOCKET;
820 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
821 return UNIX_TYPE_UNKNOWN;
824 /****************************************************************************
825 Map wire perms onto standard UNIX permissions. Obey share restrictions.
826 ****************************************************************************/
828 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
832 if (perms == SMB_MODE_NO_CHANGE)
835 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
836 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
837 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
838 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
839 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
840 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
841 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
842 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
843 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
845 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
848 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
851 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
854 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
855 ret &= lp_dir_mask(SNUM(conn));
856 /* Add in force bits */
857 ret |= lp_force_dir_mode(SNUM(conn));
859 /* Apply mode mask */
860 ret &= lp_create_mask(SNUM(conn));
861 /* Add in force bits */
862 ret |= lp_force_create_mode(SNUM(conn));
868 /****************************************************************************
869 Get a level dependent lanman2 dir entry.
870 ****************************************************************************/
872 static BOOL get_lanman2_dir_entry(connection_struct *conn,
873 void *inbuf, void *outbuf,
874 char *path_mask,int dirtype,int info_level,
875 int requires_resume_key,
876 BOOL dont_descend,char **ppdata,
877 char *base_data, int space_remaining,
878 BOOL *out_of_space, BOOL *got_exact_match,
883 SMB_STRUCT_STAT sbuf;
887 char *p, *q, *pdata = *ppdata;
891 SMB_OFF_T file_size = 0;
892 SMB_BIG_UINT allocation_size = 0;
894 time_t mdate=0, adate=0, cdate=0;
896 char *last_entry_ptr;
898 int nt_extmode; /* Used for NT connections instead of mode */
899 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
902 *out_of_space = False;
903 *got_exact_match = False;
908 p = strrchr_m(path_mask,'/');
915 pstrcpy(mask, path_mask);
920 /* Needed if we run out of space */
921 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
922 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
925 * Due to bugs in NT client redirectors we are not using
926 * resume keys any more - set them to zero.
927 * Check out the related comments in findfirst/findnext.
933 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
934 (long)conn->dirptr,curr_dirpos));
939 pstrcpy(fname,dname);
941 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
942 got_match = mask_match(fname, mask, conn->case_sensitive);
944 if(!got_match && !mangle_is_8_3(fname, False)) {
947 * It turns out that NT matches wildcards against
948 * both long *and* short names. This may explain some
949 * of the wildcard wierdness from old DOS clients
950 * that some people have been seeing.... JRA.
954 pstrcpy( newname, fname);
955 mangle_map( newname, True, False, SNUM(conn));
956 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
957 got_match = mask_match(newname, mask, conn->case_sensitive);
961 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
962 if (dont_descend && !isdots)
965 pstrcpy(pathreal,conn->dirpath);
967 pstrcat(pathreal,"/");
968 pstrcat(pathreal,dname);
970 if (INFO_LEVEL_IS_UNIX(info_level)) {
971 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
972 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
973 pathreal,strerror(errno)));
976 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
978 /* Needed to show the msdfs symlinks as
981 if(lp_host_msdfs() &&
982 lp_msdfs_root(SNUM(conn)) &&
983 is_msdfs_link(conn, pathreal, NULL, NULL,
986 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
987 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
991 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
992 pathreal,strerror(errno)));
997 mode = dos_mode(conn,pathreal,&sbuf);
999 if (!dir_check_ftype(conn,mode,dirtype)) {
1000 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1004 file_size = get_file_size(sbuf);
1005 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1006 mdate = sbuf.st_mtime;
1007 adate = sbuf.st_atime;
1008 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1010 if (lp_dos_filetime_resolution(SNUM(conn))) {
1017 /* This is necessary, as otherwise the
1018 * desktop.ini file in this folder is
1020 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
1024 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1030 mangle_map(fname,False,True,SNUM(conn));
1035 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1037 switch (info_level) {
1038 case SMB_FIND_INFO_STANDARD:
1039 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1040 if(requires_resume_key) {
1044 put_dos_date2(p,l1_fdateCreation,cdate);
1045 put_dos_date2(p,l1_fdateLastAccess,adate);
1046 put_dos_date2(p,l1_fdateLastWrite,mdate);
1047 SIVAL(p,l1_cbFile,(uint32)file_size);
1048 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
1049 SSVAL(p,l1_attrFile,mode);
1052 p += align_string(outbuf, p, 0);
1053 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1054 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1056 SCVAL(nameptr, -1, len - 2);
1058 SCVAL(nameptr, -1, 0);
1062 SCVAL(nameptr, -1, len - 1);
1064 SCVAL(nameptr, -1, 0);
1070 case SMB_FIND_EA_SIZE:
1071 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1072 if(requires_resume_key) {
1076 put_dos_date2(p,l2_fdateCreation,cdate);
1077 put_dos_date2(p,l2_fdateLastAccess,adate);
1078 put_dos_date2(p,l2_fdateLastWrite,mdate);
1079 SIVAL(p,l2_cbFile,(uint32)file_size);
1080 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1081 SSVAL(p,l2_attrFile,mode);
1083 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1084 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1088 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1089 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1102 SCVAL(nameptr,0,len);
1104 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1108 case SMB_FIND_EA_LIST:
1109 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1110 if(requires_resume_key) {
1116 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1117 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1118 was_8_3 = mangle_is_8_3(fname, True);
1120 SIVAL(p,0,reskey); p += 4;
1121 put_long_date(p,cdate); p += 8;
1122 put_long_date(p,adate); p += 8;
1123 put_long_date(p,mdate); p += 8;
1124 put_long_date(p,mdate); p += 8;
1125 SOFF_T(p,0,file_size); p += 8;
1126 SOFF_T(p,0,allocation_size); p += 8;
1127 SIVAL(p,0,nt_extmode); p += 4;
1128 q = p; p += 4; /* q is placeholder for name length. */
1130 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1131 SIVAL(p,0,ea_size); /* Extended attributes */
1134 /* Clear the short name buffer. This is
1135 * IMPORTANT as not doing so will trigger
1136 * a Win2k client bug. JRA.
1139 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1140 pstring mangled_name;
1141 pstrcpy(mangled_name, fname);
1142 mangle_map(mangled_name,True,True,SNUM(conn));
1143 mangled_name[12] = 0;
1144 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1151 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1154 len = PTR_DIFF(p, pdata);
1155 len = (len + 3) & ~3;
1160 case SMB_FIND_FILE_DIRECTORY_INFO:
1161 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1163 SIVAL(p,0,reskey); p += 4;
1164 put_long_date(p,cdate); p += 8;
1165 put_long_date(p,adate); p += 8;
1166 put_long_date(p,mdate); p += 8;
1167 put_long_date(p,mdate); p += 8;
1168 SOFF_T(p,0,file_size); p += 8;
1169 SOFF_T(p,0,allocation_size); p += 8;
1170 SIVAL(p,0,nt_extmode); p += 4;
1171 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1174 len = PTR_DIFF(p, pdata);
1175 len = (len + 3) & ~3;
1180 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1181 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1183 SIVAL(p,0,reskey); p += 4;
1184 put_long_date(p,cdate); p += 8;
1185 put_long_date(p,adate); p += 8;
1186 put_long_date(p,mdate); p += 8;
1187 put_long_date(p,mdate); p += 8;
1188 SOFF_T(p,0,file_size); p += 8;
1189 SOFF_T(p,0,allocation_size); p += 8;
1190 SIVAL(p,0,nt_extmode); p += 4;
1191 q = p; p += 4; /* q is placeholder for name length. */
1193 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1194 SIVAL(p,0,ea_size); /* Extended attributes */
1197 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1201 len = PTR_DIFF(p, pdata);
1202 len = (len + 3) & ~3;
1207 case SMB_FIND_FILE_NAMES_INFO:
1208 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1210 SIVAL(p,0,reskey); p += 4;
1212 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1213 acl on a dir (tridge) */
1214 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1217 len = PTR_DIFF(p, pdata);
1218 len = (len + 3) & ~3;
1223 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1224 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1226 SIVAL(p,0,reskey); p += 4;
1227 put_long_date(p,cdate); p += 8;
1228 put_long_date(p,adate); p += 8;
1229 put_long_date(p,mdate); p += 8;
1230 put_long_date(p,mdate); p += 8;
1231 SOFF_T(p,0,file_size); p += 8;
1232 SOFF_T(p,0,allocation_size); p += 8;
1233 SIVAL(p,0,nt_extmode); p += 4;
1234 q = p; p += 4; /* q is placeholder for name length. */
1236 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1237 SIVAL(p,0,ea_size); /* Extended attributes */
1240 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1241 SIVAL(p,0,sbuf.st_dev); p += 4;
1242 SIVAL(p,0,sbuf.st_ino); p += 4;
1243 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1246 len = PTR_DIFF(p, pdata);
1247 len = (len + 3) & ~3;
1252 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1253 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1254 was_8_3 = mangle_is_8_3(fname, True);
1256 SIVAL(p,0,reskey); p += 4;
1257 put_long_date(p,cdate); p += 8;
1258 put_long_date(p,adate); p += 8;
1259 put_long_date(p,mdate); p += 8;
1260 put_long_date(p,mdate); p += 8;
1261 SOFF_T(p,0,file_size); p += 8;
1262 SOFF_T(p,0,allocation_size); p += 8;
1263 SIVAL(p,0,nt_extmode); p += 4;
1264 q = p; p += 4; /* q is placeholder for name length */
1266 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1267 SIVAL(p,0,ea_size); /* Extended attributes */
1270 /* Clear the short name buffer. This is
1271 * IMPORTANT as not doing so will trigger
1272 * a Win2k client bug. JRA.
1275 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1276 pstring mangled_name;
1277 pstrcpy(mangled_name, fname);
1278 mangle_map(mangled_name,True,True,SNUM(conn));
1279 mangled_name[12] = 0;
1280 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1287 SSVAL(p,0,0); p += 2; /* Reserved ? */
1288 SIVAL(p,0,sbuf.st_dev); p += 4;
1289 SIVAL(p,0,sbuf.st_ino); p += 4;
1290 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1293 len = PTR_DIFF(p, pdata);
1294 len = (len + 3) & ~3;
1299 /* CIFS UNIX Extension. */
1301 case SMB_FIND_FILE_UNIX:
1302 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1304 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1306 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1307 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1310 SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1313 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1314 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1315 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1318 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1322 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1326 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1329 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1333 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1337 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1340 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1344 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1348 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1351 len = PTR_DIFF(p, pdata);
1352 len = (len + 3) & ~3;
1353 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1355 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1364 if (PTR_DIFF(p,pdata) > space_remaining) {
1365 /* Move the dirptr back to prev_dirpos */
1366 dptr_SeekDir(conn->dirptr, prev_dirpos);
1367 *out_of_space = True;
1368 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1369 return False; /* Not finished - just out of space */
1372 /* Setup the last entry pointer, as an offset from base_data */
1373 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1374 /* Advance the data pointer to the next slot */
1380 /****************************************************************************
1381 Reply to a TRANS2_FINDFIRST.
1382 ****************************************************************************/
1384 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1385 char **pparams, int total_params, char **ppdata, int total_data,
1386 unsigned int max_data_bytes)
1388 /* We must be careful here that we don't return more than the
1389 allowed number of data bytes. If this means returning fewer than
1390 maxentries then so be it. We assume that the redirector has
1391 enough room for the fixed number of parameter bytes it has
1393 char *params = *pparams;
1394 char *pdata = *ppdata;
1395 int dirtype = SVAL(params,0);
1396 int maxentries = SVAL(params,2);
1397 uint16 findfirst_flags = SVAL(params,4);
1398 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1399 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1400 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1401 int info_level = SVAL(params,6);
1405 int last_entry_off=0;
1409 BOOL finished = False;
1410 BOOL dont_descend = False;
1411 BOOL out_of_space = False;
1412 int space_remaining;
1413 BOOL bad_path = False;
1414 SMB_STRUCT_STAT sbuf;
1415 NTSTATUS ntstatus = NT_STATUS_OK;
1417 if (total_params < 12) {
1418 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1421 *directory = *mask = 0;
1423 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1424 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1425 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1426 info_level, max_data_bytes));
1429 /* W2K3 seems to treat zero as 1. */
1433 switch (info_level) {
1434 case SMB_FIND_INFO_STANDARD:
1435 case SMB_FIND_EA_SIZE:
1436 case SMB_FIND_FILE_DIRECTORY_INFO:
1437 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1438 case SMB_FIND_FILE_NAMES_INFO:
1439 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1440 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1441 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1443 case SMB_FIND_FILE_UNIX:
1444 if (!lp_unix_extensions())
1445 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1448 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1451 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1452 if (!NT_STATUS_IS_OK(ntstatus)) {
1453 return ERROR_NT(ntstatus);
1456 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
1458 unix_convert(directory,conn,0,&bad_path,&sbuf);
1460 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1462 if(!check_name(directory,conn)) {
1463 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1466 p = strrchr_m(directory,'/');
1468 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1469 if((directory[0] == '.') && (directory[1] == '\0'))
1472 pstrcpy(mask,directory);
1473 pstrcpy(directory,"./");
1479 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1481 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1483 return(ERROR_DOS(ERRDOS,ERRnomem));
1486 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1488 /* Realloc the params space */
1489 params = SMB_REALLOC(*pparams, 10);
1491 return ERROR_DOS(ERRDOS,ERRnomem);
1494 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1496 return(UNIXERROR(ERRDOS,ERRbadfile));
1498 /* Save the wildcard match and attribs we are using on this directory -
1499 needed as lanman2 assumes these are being saved between calls */
1501 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1502 dptr_close(&dptr_num);
1503 return ERROR_DOS(ERRDOS,ERRnomem);
1506 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1508 /* We don't need to check for VOL here as this is returned by
1509 a different TRANS2 call. */
1511 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1512 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1513 dont_descend = True;
1516 space_remaining = max_data_bytes;
1517 out_of_space = False;
1519 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1520 BOOL got_exact_match = False;
1522 /* this is a heuristic to avoid seeking the dirptr except when
1523 absolutely necessary. It allows for a filename of about 40 chars */
1524 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1525 out_of_space = True;
1528 finished = !get_lanman2_dir_entry(conn,
1530 mask,dirtype,info_level,
1531 requires_resume_key,dont_descend,
1532 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1536 if (finished && out_of_space)
1539 if (!finished && !out_of_space)
1543 * As an optimisation if we know we aren't looking
1544 * for a wildcard name (ie. the name matches the wildcard exactly)
1545 * then we can finish on any (first) match.
1546 * This speeds up large directory searches. JRA.
1552 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1555 /* Check if we can close the dirptr */
1556 if(close_after_first || (finished && close_if_end)) {
1557 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1558 dptr_close(&dptr_num);
1562 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1563 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1564 * the protocol level is less than NT1. Tested with smbclient. JRA.
1565 * This should fix the OS/2 client bug #2335.
1568 if(numentries == 0) {
1569 dptr_close(&dptr_num);
1570 if (Protocol < PROTOCOL_NT1) {
1571 return ERROR_DOS(ERRDOS,ERRnofiles);
1573 return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1577 /* At this point pdata points to numentries directory entries. */
1579 /* Set up the return parameter block */
1580 SSVAL(params,0,dptr_num);
1581 SSVAL(params,2,numentries);
1582 SSVAL(params,4,finished);
1583 SSVAL(params,6,0); /* Never an EA error */
1584 SSVAL(params,8,last_entry_off);
1586 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1588 if ((! *directory) && dptr_path(dptr_num))
1589 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1591 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1592 smb_fn_name(CVAL(inbuf,smb_com)),
1593 mask, directory, dirtype, numentries ) );
1596 * Force a name mangle here to ensure that the
1597 * mask as an 8.3 name is top of the mangled cache.
1598 * The reasons for this are subtle. Don't remove
1599 * this code unless you know what you are doing
1600 * (see PR#13758). JRA.
1603 if(!mangle_is_8_3_wildcards( mask, False))
1604 mangle_map(mask, True, True, SNUM(conn));
1609 /****************************************************************************
1610 Reply to a TRANS2_FINDNEXT.
1611 ****************************************************************************/
1613 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1614 char **pparams, int total_params, char **ppdata, int total_data,
1615 unsigned int max_data_bytes)
1617 /* We must be careful here that we don't return more than the
1618 allowed number of data bytes. If this means returning fewer than
1619 maxentries then so be it. We assume that the redirector has
1620 enough room for the fixed number of parameter bytes it has
1622 char *params = *pparams;
1623 char *pdata = *ppdata;
1624 int dptr_num = SVAL(params,0);
1625 int maxentries = SVAL(params,2);
1626 uint16 info_level = SVAL(params,4);
1627 uint32 resume_key = IVAL(params,6);
1628 uint16 findnext_flags = SVAL(params,10);
1629 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1630 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1631 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1632 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1633 pstring resume_name;
1639 int i, last_entry_off=0;
1640 BOOL finished = False;
1641 BOOL dont_descend = False;
1642 BOOL out_of_space = False;
1643 int space_remaining;
1644 NTSTATUS ntstatus = NT_STATUS_OK;
1646 if (total_params < 12) {
1647 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1650 *mask = *directory = *resume_name = 0;
1652 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1653 if (!NT_STATUS_IS_OK(ntstatus)) {
1654 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1655 complain (it thinks we're asking for the directory above the shared
1656 path or an invalid name). Catch this as the resume name is only compared, never used in
1657 a file access. JRA. */
1658 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1659 pstrcpy(resume_name, "..");
1660 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1661 pstrcpy(resume_name, ".");
1663 return ERROR_NT(ntstatus);
1667 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1668 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1669 resume_key = %d resume name = %s continue=%d level = %d\n",
1670 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1671 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1674 /* W2K3 seems to treat zero as 1. */
1678 switch (info_level) {
1679 case SMB_FIND_INFO_STANDARD:
1680 case SMB_FIND_EA_SIZE:
1681 case SMB_FIND_FILE_DIRECTORY_INFO:
1682 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1683 case SMB_FIND_FILE_NAMES_INFO:
1684 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1686 case SMB_FIND_FILE_UNIX:
1687 if (!lp_unix_extensions())
1688 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1691 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1694 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1696 return ERROR_DOS(ERRDOS,ERRnomem);
1699 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1701 /* Realloc the params space */
1702 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1703 if( params == NULL )
1704 return ERROR_DOS(ERRDOS,ERRnomem);
1708 /* Check that the dptr is valid */
1709 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1710 return ERROR_DOS(ERRDOS,ERRnofiles);
1712 string_set(&conn->dirpath,dptr_path(dptr_num));
1714 /* Get the wildcard mask from the dptr */
1715 if((p = dptr_wcard(dptr_num))== NULL) {
1716 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1717 return ERROR_DOS(ERRDOS,ERRnofiles);
1721 pstrcpy(directory,conn->dirpath);
1723 /* Get the attr mask from the dptr */
1724 dirtype = dptr_attr(dptr_num);
1726 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
1727 dptr_num, mask, dirtype,
1729 dptr_TellDir(conn->dirptr)));
1731 /* We don't need to check for VOL here as this is returned by
1732 a different TRANS2 call. */
1734 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1735 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1736 dont_descend = True;
1739 space_remaining = max_data_bytes;
1740 out_of_space = False;
1743 * Seek to the correct position. We no longer use the resume key but
1744 * depend on the last file name instead.
1747 if(*resume_name && !continue_bit) {
1750 long current_pos = 0;
1752 * Remember, mangle_map is called by
1753 * get_lanman2_dir_entry(), so the resume name
1754 * could be mangled. Ensure we check the unmangled name.
1757 if (mangle_is_mangled(resume_name)) {
1758 mangle_check_cache(resume_name, sizeof(resume_name)-1);
1762 * Fix for NT redirector problem triggered by resume key indexes
1763 * changing between directory scans. We now return a resume key of 0
1764 * and instead look for the filename to continue from (also given
1765 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1766 * findfirst/findnext (as is usual) then the directory pointer
1767 * should already be at the correct place.
1770 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
1771 } /* end if resume_name && !continue_bit */
1773 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1774 BOOL got_exact_match = False;
1776 /* this is a heuristic to avoid seeking the dirptr except when
1777 absolutely necessary. It allows for a filename of about 40 chars */
1778 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1779 out_of_space = True;
1782 finished = !get_lanman2_dir_entry(conn,
1784 mask,dirtype,info_level,
1785 requires_resume_key,dont_descend,
1786 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1790 if (finished && out_of_space)
1793 if (!finished && !out_of_space)
1797 * As an optimisation if we know we aren't looking
1798 * for a wildcard name (ie. the name matches the wildcard exactly)
1799 * then we can finish on any (first) match.
1800 * This speeds up large directory searches. JRA.
1806 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1809 /* Check if we can close the dirptr */
1810 if(close_after_request || (finished && close_if_end)) {
1811 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1812 dptr_close(&dptr_num); /* This frees up the saved mask */
1815 /* Set up the return parameter block */
1816 SSVAL(params,0,numentries);
1817 SSVAL(params,2,finished);
1818 SSVAL(params,4,0); /* Never an EA error */
1819 SSVAL(params,6,last_entry_off);
1821 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1823 if ((! *directory) && dptr_path(dptr_num))
1824 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1826 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1827 smb_fn_name(CVAL(inbuf,smb_com)),
1828 mask, directory, dirtype, numentries ) );
1833 /****************************************************************************
1834 Reply to a TRANS2_QFSINFO (query filesystem info).
1835 ****************************************************************************/
1837 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1838 char **pparams, int total_params, char **ppdata, int total_data,
1839 unsigned int max_data_bytes)
1841 char *pdata = *ppdata;
1842 char *params = *pparams;
1843 uint16 info_level = SVAL(params,0);
1846 char *vname = volume_label(SNUM(conn));
1847 int snum = SNUM(conn);
1848 char *fstype = lp_fstype(SNUM(conn));
1851 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1853 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1854 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1855 return ERROR_DOS(ERRSRV,ERRinvdevice);
1858 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1859 if ( pdata == NULL )
1860 return ERROR_DOS(ERRDOS,ERRnomem);
1863 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1865 switch (info_level) {
1866 case SMB_INFO_ALLOCATION:
1868 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1870 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1871 return(UNIXERROR(ERRHRD,ERRgeneral));
1874 block_size = lp_block_size(snum);
1875 if (bsize < block_size) {
1876 SMB_BIG_UINT factor = block_size/bsize;
1881 if (bsize > block_size) {
1882 SMB_BIG_UINT factor = bsize/block_size;
1887 bytes_per_sector = 512;
1888 sectors_per_unit = bsize/bytes_per_sector;
1890 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1891 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1892 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1894 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1895 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1896 SIVAL(pdata,l1_cUnit,dsize);
1897 SIVAL(pdata,l1_cUnitAvail,dfree);
1898 SSVAL(pdata,l1_cbSector,bytes_per_sector);
1902 case SMB_INFO_VOLUME:
1903 /* Return volume name */
1905 * Add volume serial number - hash of a combination of
1906 * the called hostname and the service name.
1908 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
1909 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1910 SCVAL(pdata,l2_vol_cch,len);
1911 data_len = l2_vol_szVolLabel + len;
1912 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1913 (unsigned)st.st_ctime, len, vname));
1916 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1917 case SMB_FS_ATTRIBUTE_INFORMATION:
1920 #if defined(HAVE_SYS_QUOTAS)
1921 quota_flag = FILE_VOLUME_QUOTAS;
1924 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1925 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1926 quota_flag); /* FS ATTRIBUTES */
1928 SIVAL(pdata,4,255); /* Max filename component length */
1929 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1930 and will think we can't do long filenames */
1931 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1933 data_len = 12 + len;
1936 case SMB_QUERY_FS_LABEL_INFO:
1937 case SMB_FS_LABEL_INFORMATION:
1938 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1943 case SMB_QUERY_FS_VOLUME_INFO:
1944 case SMB_FS_VOLUME_INFORMATION:
1947 * Add volume serial number - hash of a combination of
1948 * the called hostname and the service name.
1950 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1951 (str_checksum(get_local_machine_name())<<16));
1953 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1954 SIVAL(pdata,12,len);
1956 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1957 (int)strlen(vname),vname, lp_servicename(snum)));
1960 case SMB_QUERY_FS_SIZE_INFO:
1961 case SMB_FS_SIZE_INFORMATION:
1963 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1965 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1966 return(UNIXERROR(ERRHRD,ERRgeneral));
1968 block_size = lp_block_size(snum);
1969 if (bsize < block_size) {
1970 SMB_BIG_UINT factor = block_size/bsize;
1975 if (bsize > block_size) {
1976 SMB_BIG_UINT factor = bsize/block_size;
1981 bytes_per_sector = 512;
1982 sectors_per_unit = bsize/bytes_per_sector;
1983 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1984 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1985 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1986 SBIG_UINT(pdata,0,dsize);
1987 SBIG_UINT(pdata,8,dfree);
1988 SIVAL(pdata,16,sectors_per_unit);
1989 SIVAL(pdata,20,bytes_per_sector);
1993 case SMB_FS_FULL_SIZE_INFORMATION:
1995 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1997 if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1998 return(UNIXERROR(ERRHRD,ERRgeneral));
2000 block_size = lp_block_size(snum);
2001 if (bsize < block_size) {
2002 SMB_BIG_UINT factor = block_size/bsize;
2007 if (bsize > block_size) {
2008 SMB_BIG_UINT factor = bsize/block_size;
2013 bytes_per_sector = 512;
2014 sectors_per_unit = bsize/bytes_per_sector;
2015 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2016 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2017 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2018 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2019 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2020 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2021 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2022 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2026 case SMB_QUERY_FS_DEVICE_INFO:
2027 case SMB_FS_DEVICE_INFORMATION:
2029 SIVAL(pdata,0,0); /* dev type */
2030 SIVAL(pdata,4,0); /* characteristics */
2033 #ifdef HAVE_SYS_QUOTAS
2034 case SMB_FS_QUOTA_INFORMATION:
2036 * what we have to send --metze:
2038 * Unknown1: 24 NULL bytes
2039 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2040 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2041 * Quota Flags: 2 byte :
2042 * Unknown3: 6 NULL bytes
2046 * details for Quota Flags:
2048 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2049 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2050 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2051 * 0x0001 Enable Quotas: enable quota for this fs
2055 /* we need to fake up a fsp here,
2056 * because its not send in this call
2059 SMB_NTQUOTA_STRUCT quotas;
2062 ZERO_STRUCT(quotas);
2069 if (current_user.uid != 0) {
2070 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2071 lp_servicename(SNUM(conn)),conn->user));
2072 return ERROR_DOS(ERRDOS,ERRnoaccess);
2075 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2076 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2077 return ERROR_DOS(ERRSRV,ERRerror);
2082 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2084 /* Unknown1 24 NULL bytes*/
2085 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2086 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2087 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2089 /* Default Soft Quota 8 bytes */
2090 SBIG_UINT(pdata,24,quotas.softlim);
2092 /* Default Hard Quota 8 bytes */
2093 SBIG_UINT(pdata,32,quotas.hardlim);
2095 /* Quota flag 2 bytes */
2096 SSVAL(pdata,40,quotas.qflags);
2098 /* Unknown3 6 NULL bytes */
2104 #endif /* HAVE_SYS_QUOTAS */
2105 case SMB_FS_OBJECTID_INFORMATION:
2110 * Query the version and capabilities of the CIFS UNIX extensions
2114 case SMB_QUERY_CIFS_UNIX_INFO:
2115 if (!lp_unix_extensions())
2116 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2118 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2119 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2120 SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
2123 case SMB_MAC_QUERY_FS_INFO:
2125 * Thursby MAC extension... ONLY on NTFS filesystems
2126 * once we do streams then we don't need this
2128 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2130 SIVAL(pdata,84,0x100); /* Don't support mac... */
2135 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2139 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2141 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2146 #ifdef HAVE_SYS_QUOTAS
2147 /****************************************************************************
2148 Reply to a TRANS2_SETFSINFO (set filesystem info).
2149 ****************************************************************************/
2151 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2152 char **pparams, int total_params, char **ppdata, int total_data,
2153 unsigned int max_data_bytes)
2155 char *pdata = *ppdata;
2156 char *params = *pparams;
2157 files_struct *fsp = NULL;
2160 SMB_NTQUOTA_STRUCT quotas;
2162 ZERO_STRUCT(quotas);
2164 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2167 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2168 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2169 lp_servicename(SNUM(conn)),conn->user));
2170 return ERROR_DOS(ERRSRV,ERRaccess);
2174 if (total_params < 4) {
2175 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2177 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2180 fsp = file_fsp(params,0);
2182 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2183 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2184 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2187 info_level = SVAL(params,2);
2189 switch(info_level) {
2190 case SMB_FS_QUOTA_INFORMATION:
2191 /* note: normaly there're 48 bytes,
2192 * but we didn't use the last 6 bytes for now
2195 if (total_data < 42) {
2196 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2198 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2201 /* unknown_1 24 NULL bytes in pdata*/
2203 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2204 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2205 #ifdef LARGE_SMB_OFF_T
2206 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2207 #else /* LARGE_SMB_OFF_T */
2208 if ((IVAL(pdata,28) != 0)&&
2209 ((quotas.softlim != 0xFFFFFFFF)||
2210 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2211 /* more than 32 bits? */
2212 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2214 #endif /* LARGE_SMB_OFF_T */
2216 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2217 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2218 #ifdef LARGE_SMB_OFF_T
2219 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2220 #else /* LARGE_SMB_OFF_T */
2221 if ((IVAL(pdata,36) != 0)&&
2222 ((quotas.hardlim != 0xFFFFFFFF)||
2223 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2224 /* more than 32 bits? */
2225 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2227 #endif /* LARGE_SMB_OFF_T */
2229 /* quota_flags 2 bytes **/
2230 quotas.qflags = SVAL(pdata,40);
2232 /* unknown_2 6 NULL bytes follow*/
2234 /* now set the quotas */
2235 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2236 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2237 return ERROR_DOS(ERRSRV,ERRerror);
2242 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2244 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2249 * sending this reply works fine,
2250 * but I'm not sure it's the same
2251 * like windows do...
2254 outsize = set_message(outbuf,10,0,True);
2258 #endif /* HAVE_SYS_QUOTAS */
2260 /****************************************************************************
2261 Utility function to set bad path error.
2262 ****************************************************************************/
2264 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2266 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2267 err, (int)bad_path ));
2271 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2273 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2276 return UNIXERROR(def_class,def_code);
2279 #if defined(HAVE_POSIX_ACLS)
2280 /****************************************************************************
2281 Utility function to count the number of entries in a POSIX acl.
2282 ****************************************************************************/
2284 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2286 unsigned int ace_count = 0;
2287 int entry_id = SMB_ACL_FIRST_ENTRY;
2288 SMB_ACL_ENTRY_T entry;
2290 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2292 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2293 entry_id = SMB_ACL_NEXT_ENTRY;
2300 /****************************************************************************
2301 Utility function to marshall a POSIX acl into wire format.
2302 ****************************************************************************/
2304 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2306 int entry_id = SMB_ACL_FIRST_ENTRY;
2307 SMB_ACL_ENTRY_T entry;
2309 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2310 SMB_ACL_TAG_T tagtype;
2311 SMB_ACL_PERMSET_T permset;
2312 unsigned char perms = 0;
2313 unsigned int own_grp;
2316 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2317 entry_id = SMB_ACL_NEXT_ENTRY;
2320 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2321 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2325 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2326 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2330 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2331 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2332 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2334 SCVAL(pdata,1,perms);
2337 case SMB_ACL_USER_OBJ:
2338 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2339 own_grp = (unsigned int)pst->st_uid;
2340 SIVAL(pdata,2,own_grp);
2345 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2347 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2349 own_grp = (unsigned int)*puid;
2350 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2351 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2352 SIVAL(pdata,2,own_grp);
2356 case SMB_ACL_GROUP_OBJ:
2357 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2358 own_grp = (unsigned int)pst->st_gid;
2359 SIVAL(pdata,2,own_grp);
2364 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2366 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2368 own_grp = (unsigned int)*pgid;
2369 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2370 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2371 SIVAL(pdata,2,own_grp);
2376 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2377 SIVAL(pdata,2,0xFFFFFFFF);
2378 SIVAL(pdata,6,0xFFFFFFFF);
2381 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2382 SIVAL(pdata,2,0xFFFFFFFF);
2383 SIVAL(pdata,6,0xFFFFFFFF);
2386 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2389 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2396 /****************************************************************************
2397 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2398 file name or file id).
2399 ****************************************************************************/
2401 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2402 char **pparams, int total_params, char **ppdata, int total_data,
2403 unsigned int max_data_bytes)
2405 char *params = *pparams;
2406 char *pdata = *ppdata;
2407 uint16 tran_call = SVAL(inbuf, smb_setup0);
2410 SMB_OFF_T file_size=0;
2411 SMB_BIG_UINT allocation_size=0;
2412 unsigned int data_size = 0;
2413 unsigned int param_size = 2;
2414 SMB_STRUCT_STAT sbuf;
2415 pstring fname, dos_fname;
2420 BOOL bad_path = False;
2421 BOOL delete_pending = False;
2424 files_struct *fsp = NULL;
2425 TALLOC_CTX *ea_ctx = NULL;
2426 struct ea_list *ea_list = NULL;
2427 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2430 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2434 if (tran_call == TRANSACT2_QFILEINFO) {
2435 if (total_params < 4) {
2436 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2439 fsp = file_fsp(params,0);
2440 info_level = SVAL(params,2);
2442 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2444 if(fsp && (fsp->fake_file_handle)) {
2446 * This is actually for the QUOTA_FAKE_FILE --metze
2449 pstrcpy(fname, fsp->fsp_name);
2450 /* We know this name is ok, it's already passed the checks. */
2452 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2454 * This is actually a QFILEINFO on a directory
2455 * handle (returned from an NT SMB). NT5.0 seems
2456 * to do this call. JRA.
2458 /* We know this name is ok, it's already passed the checks. */
2459 pstrcpy(fname, fsp->fsp_name);
2461 if (INFO_LEVEL_IS_UNIX(info_level)) {
2462 /* Always do lstat for UNIX calls. */
2463 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2464 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2465 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2467 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2468 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2469 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2472 delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2475 * Original code - this is an open file.
2477 CHECK_FSP(fsp,conn);
2479 pstrcpy(fname, fsp->fsp_name);
2480 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2481 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2482 return(UNIXERROR(ERRDOS,ERRbadfid));
2484 pos = fsp->position_information;
2485 delete_pending = fsp->delete_on_close;
2486 desired_access = fsp->desired_access;
2489 NTSTATUS status = NT_STATUS_OK;
2492 if (total_params < 6) {
2493 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2496 info_level = SVAL(params,0);
2498 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2500 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2501 if (!NT_STATUS_IS_OK(status)) {
2502 return ERROR_NT(status);
2505 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2507 unix_convert(fname,conn,0,&bad_path,&sbuf);
2509 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2511 if (!check_name(fname,conn)) {
2512 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2513 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2516 if (INFO_LEVEL_IS_UNIX(info_level)) {
2517 /* Always do lstat for UNIX calls. */
2518 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2519 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2520 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2522 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2523 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2524 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2528 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2529 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2531 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2532 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2534 p = strrchr_m(fname,'/');
2540 mode = dos_mode(conn,fname,&sbuf);
2542 mode = FILE_ATTRIBUTE_NORMAL;
2544 fullpathname = fname;
2545 file_size = get_file_size(sbuf);
2546 allocation_size = get_allocation_size(conn,fsp,&sbuf);
2548 /* This is necessary, as otherwise the desktop.ini file in
2549 * this folder is ignored */
2550 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2554 /* Pull any EA list from the data portion. */
2555 if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2556 uint32 ea_size = IVAL(pdata,0);
2558 if (total_data > 0 && ea_size != total_data) {
2559 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2560 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2561 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2564 if (!lp_ea_support(SNUM(conn))) {
2565 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2568 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2569 return ERROR_NT(NT_STATUS_NO_MEMORY);
2572 /* Pull out the list of names. */
2573 ea_list = read_ea_list(ea_ctx, pdata, ea_size);
2575 talloc_destroy(ea_ctx);
2576 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2580 params = SMB_REALLOC(*pparams,2);
2581 if (params == NULL) {
2582 talloc_destroy(ea_ctx);
2583 return ERROR_NT(NT_STATUS_NO_MEMORY);
2586 memset((char *)params,'\0',2);
2587 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2588 pdata = SMB_REALLOC(*ppdata, data_size);
2589 if ( pdata == NULL ) {
2590 talloc_destroy(ea_ctx);
2591 return ERROR_NT(NT_STATUS_NO_MEMORY);
2595 memset((char *)pdata,'\0',data_size);
2597 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2600 if (fsp->pending_modtime) {
2601 /* the pending modtime overrides the current modtime */
2602 sbuf.st_mtime = fsp->pending_modtime;
2605 /* Do we have this path open ? */
2606 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2607 if (fsp1 && fsp1->pending_modtime) {
2608 /* the pending modtime overrides the current modtime */
2609 sbuf.st_mtime = fsp1->pending_modtime;
2613 if (lp_dos_filetime_resolution(SNUM(conn))) {
2615 sbuf.st_atime &= ~1;
2616 sbuf.st_ctime &= ~1;
2617 sbuf.st_mtime &= ~1;
2620 /* NT expects the name to be in an exact form of the *full*
2621 filename. See the trans2 torture test */
2622 if (strequal(base_name,".")) {
2623 pstrcpy(dos_fname, "\\");
2625 pstr_sprintf(dos_fname, "\\%s", fname);
2626 string_replace(dos_fname, '/', '\\');
2629 switch (info_level) {
2630 case SMB_INFO_STANDARD:
2631 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2633 put_dos_date2(pdata,l1_fdateCreation,c_time);
2634 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2635 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2636 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2637 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2638 SSVAL(pdata,l1_attrFile,mode);
2641 case SMB_INFO_QUERY_EA_SIZE:
2643 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2644 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2646 put_dos_date2(pdata,l1_fdateCreation,c_time);
2647 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2648 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2649 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2650 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2651 SSVAL(pdata,l1_attrFile,mode);
2652 SIVAL(pdata,l1_attrFile+2,ea_size);
2656 case SMB_INFO_IS_NAME_VALID:
2657 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2658 if (tran_call == TRANSACT2_QFILEINFO) {
2659 /* os/2 needs this ? really ?*/
2660 return ERROR_DOS(ERRDOS,ERRbadfunc);
2666 case SMB_INFO_QUERY_EAS_FROM_LIST:
2668 size_t total_ea_len = 0;
2669 struct ea_list *ea_file_list = NULL;
2671 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2672 put_dos_date2(pdata,0,c_time);
2673 put_dos_date2(pdata,4,sbuf.st_atime);
2674 put_dos_date2(pdata,8,sbuf.st_mtime);
2675 SIVAL(pdata,12,(uint32)file_size);
2676 SIVAL(pdata,16,(uint32)allocation_size);
2677 SIVAL(pdata,20,mode);
2679 ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2681 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
2683 if (!ea_list || (total_ea_len > data_size - 24)) {
2684 talloc_destroy(ea_ctx);
2689 data_size = fill_ea_buffer(ea_ctx, pdata + 24, data_size - 24, conn, ea_list);
2691 talloc_destroy(ea_ctx);
2695 case SMB_INFO_QUERY_ALL_EAS:
2697 /* We have data_size bytes to put EA's into. */
2698 size_t total_ea_len = 0;
2700 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2702 ea_ctx = talloc_init("ea_ctx");
2704 return ERROR_NT(NT_STATUS_NO_MEMORY);
2707 ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2708 if (!ea_list || (total_ea_len > data_size)) {
2709 talloc_destroy(ea_ctx);
2714 data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
2715 talloc_destroy(ea_ctx);
2719 case SMB_FILE_BASIC_INFORMATION:
2720 case SMB_QUERY_FILE_BASIC_INFO:
2722 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2723 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2724 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2726 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2730 put_long_date(pdata,c_time);
2731 put_long_date(pdata+8,sbuf.st_atime);
2732 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2733 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2734 SIVAL(pdata,32,mode);
2736 DEBUG(5,("SMB_QFBI - "));
2738 time_t create_time = c_time;
2739 DEBUG(5,("create: %s ", ctime(&create_time)));
2741 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2742 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2743 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2744 DEBUG(5,("mode: %x\n", mode));
2748 case SMB_FILE_STANDARD_INFORMATION:
2749 case SMB_QUERY_FILE_STANDARD_INFO:
2751 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2753 SOFF_T(pdata,0,allocation_size);
2754 SOFF_T(pdata,8,file_size);
2755 if (delete_pending & sbuf.st_nlink)
2756 SIVAL(pdata,16,sbuf.st_nlink - 1);
2758 SIVAL(pdata,16,sbuf.st_nlink);
2760 SCVAL(pdata,21,(mode&aDIR)?1:0);
2763 case SMB_FILE_EA_INFORMATION:
2764 case SMB_QUERY_FILE_EA_INFO:
2766 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2767 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2769 SIVAL(pdata,0,ea_size);
2773 /* Get the 8.3 name - used if NT SMB was negotiated. */
2774 case SMB_QUERY_FILE_ALT_NAME_INFO:
2775 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2779 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2780 pstrcpy(short_name,base_name);
2781 /* Mangle if not already 8.3 */
2782 if(!mangle_is_8_3(short_name, True)) {
2783 mangle_map(short_name,True,True,SNUM(conn));
2785 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2786 data_size = 4 + len;
2791 case SMB_QUERY_FILE_NAME_INFO:
2793 this must be *exactly* right for ACLs on mapped drives to work
2795 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2796 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2797 data_size = 4 + len;
2801 case SMB_FILE_ALLOCATION_INFORMATION:
2802 case SMB_QUERY_FILE_ALLOCATION_INFO:
2803 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2805 SOFF_T(pdata,0,allocation_size);
2808 case SMB_FILE_END_OF_FILE_INFORMATION:
2809 case SMB_QUERY_FILE_END_OF_FILEINFO:
2810 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2812 SOFF_T(pdata,0,file_size);
2815 case SMB_QUERY_FILE_ALL_INFO:
2816 case SMB_FILE_ALL_INFORMATION:
2818 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2819 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2820 put_long_date(pdata,c_time);
2821 put_long_date(pdata+8,sbuf.st_atime);
2822 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2823 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2824 SIVAL(pdata,32,mode);
2826 SOFF_T(pdata,0,allocation_size);
2827 SOFF_T(pdata,8,file_size);
2828 if (delete_pending && sbuf.st_nlink)
2829 SIVAL(pdata,16,sbuf.st_nlink - 1);
2831 SIVAL(pdata,16,sbuf.st_nlink);
2832 SCVAL(pdata,20,delete_pending);
2833 SCVAL(pdata,21,(mode&aDIR)?1:0);
2835 SIVAL(pdata,0,ea_size);
2836 pdata += 4; /* EA info */
2837 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2840 data_size = PTR_DIFF(pdata,(*ppdata));
2843 case SMB_FILE_INTERNAL_INFORMATION:
2844 /* This should be an index number - looks like
2847 I think this causes us to fail the IFSKIT
2848 BasicFileInformationTest. -tpot */
2850 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2851 SIVAL(pdata,0,sbuf.st_dev);
2852 SIVAL(pdata,4,sbuf.st_ino);
2856 case SMB_FILE_ACCESS_INFORMATION:
2857 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2858 SIVAL(pdata,0,desired_access);
2862 case SMB_FILE_NAME_INFORMATION:
2863 /* Pathname with leading '\'. */
2866 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2867 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2868 SIVAL(pdata,0,byte_len);
2869 data_size = 4 + byte_len;
2873 case SMB_FILE_DISPOSITION_INFORMATION:
2874 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2876 SCVAL(pdata,0,delete_pending);
2879 case SMB_FILE_POSITION_INFORMATION:
2880 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2882 SOFF_T(pdata,0,pos);
2885 case SMB_FILE_MODE_INFORMATION:
2886 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2887 SIVAL(pdata,0,mode);
2891 case SMB_FILE_ALIGNMENT_INFORMATION:
2892 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2893 SIVAL(pdata,0,0); /* No alignment needed. */
2899 * NT4 server just returns "invalid query" to this - if we try to answer
2900 * it then NTws gets a BSOD! (tridge).
2901 * W2K seems to want this. JRA.
2903 case SMB_QUERY_FILE_STREAM_INFO:
2905 case SMB_FILE_STREAM_INFORMATION:
2906 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2910 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2911 SIVAL(pdata,0,0); /* ??? */
2912 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2913 SOFF_T(pdata,8,file_size);
2914 SIVAL(pdata,16,allocation_size);
2915 SIVAL(pdata,20,0); /* ??? */
2916 data_size = 24 + byte_len;
2920 case SMB_QUERY_COMPRESSION_INFO:
2921 case SMB_FILE_COMPRESSION_INFORMATION:
2922 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2923 SOFF_T(pdata,0,file_size);
2924 SIVAL(pdata,8,0); /* ??? */
2925 SIVAL(pdata,12,0); /* ??? */
2929 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2930 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2931 put_long_date(pdata,c_time);
2932 put_long_date(pdata+8,sbuf.st_atime);
2933 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2934 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2935 SIVAL(pdata,32,allocation_size);
2936 SOFF_T(pdata,40,file_size);
2937 SIVAL(pdata,48,mode);
2938 SIVAL(pdata,52,0); /* ??? */
2942 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2943 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2944 SIVAL(pdata,0,mode);
2950 * CIFS UNIX Extensions.
2953 case SMB_QUERY_FILE_UNIX_BASIC:
2955 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2956 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2958 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2961 SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2964 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2965 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2966 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2969 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2973 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2977 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2980 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2984 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2988 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2991 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2995 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2998 data_size = PTR_DIFF(pdata,(*ppdata));
3002 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3004 for (i=0; i<100; i++)
3005 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3011 case SMB_QUERY_FILE_UNIX_LINK:
3015 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3017 if(!S_ISLNK(sbuf.st_mode))
3018 return(UNIXERROR(ERRSRV,ERRbadlink));
3020 return(UNIXERROR(ERRDOS,ERRbadlink));
3022 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
3024 return(UNIXERROR(ERRDOS,ERRnoaccess));
3026 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3028 data_size = PTR_DIFF(pdata,(*ppdata));
3033 #if defined(HAVE_POSIX_ACLS)
3034 case SMB_QUERY_POSIX_ACL:
3036 SMB_ACL_T file_acl = NULL;
3037 SMB_ACL_T def_acl = NULL;
3038 uint16 num_file_acls = 0;
3039 uint16 num_def_acls = 0;
3041 if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
3042 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
3044 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3047 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3048 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3050 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3053 if (S_ISDIR(sbuf.st_mode)) {
3054 if (fsp && fsp->is_directory) {
3055 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3057 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3059 def_acl = free_empty_sys_acl(conn, def_acl);
3062 num_file_acls = count_acl_entries(conn, file_acl);
3063 num_def_acls = count_acl_entries(conn, def_acl);
3065 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3066 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3068 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3069 SMB_POSIX_ACL_HEADER_SIZE) ));
3071 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3074 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3076 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3079 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3080 SSVAL(pdata,2,num_file_acls);
3081 SSVAL(pdata,4,num_def_acls);
3082 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3084 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3087 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3089 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3091 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3093 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3096 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3098 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3102 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3105 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3107 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3113 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3116 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3121 /****************************************************************************
3122 Deal with the internal needs of setting the delete on close flag. Note that
3123 as the tdb locking is recursive, it is safe to call this from within
3124 open_file_shared. JRA.
3125 ****************************************************************************/
3127 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
3129 if (delete_on_close) {
3131 * Only allow delete on close for writable files.
3134 if (!lp_delete_readonly(SNUM(fsp->conn))) {
3135 if (dosmode & aRONLY) {
3136 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
3138 return NT_STATUS_CANNOT_DELETE;
3143 * Only allow delete on close for writable shares.
3146 if (!CAN_WRITE(fsp->conn)) {
3147 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
3149 return NT_STATUS_ACCESS_DENIED;
3153 * Only allow delete on close for files/directories opened with delete intent.
3156 if (!(fsp->desired_access & DELETE_ACCESS)) {
3157 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
3159 return NT_STATUS_ACCESS_DENIED;
3163 if(fsp->is_directory) {
3164 fsp->directory_delete_on_close = delete_on_close;
3165 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3166 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3168 fsp->delete_on_close = delete_on_close;
3169 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3170 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3173 return NT_STATUS_OK;
3176 /****************************************************************************
3177 Sets the delete on close flag over all share modes on this file.
3178 Modify the share mode entry for all files open
3179 on this device and inode to tell other smbds we have
3180 changed the delete on close flag. This will be noticed
3181 in the close code, the last closer will delete the file
3183 ****************************************************************************/
3185 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3187 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3188 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3190 if (fsp->is_directory || fsp->is_stat)
3191 return NT_STATUS_OK;
3193 if (lock_share_entry_fsp(fsp) == False)
3194 return NT_STATUS_ACCESS_DENIED;
3196 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3197 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3199 unlock_share_entry_fsp(fsp);
3200 return NT_STATUS_ACCESS_DENIED;
3203 unlock_share_entry_fsp(fsp);
3204 return NT_STATUS_OK;
3207 /****************************************************************************
3208 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3210 ****************************************************************************/
3212 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3214 BOOL bad_path_oldname = False;
3215 BOOL bad_path_newname = False;
3216 SMB_STRUCT_STAT sbuf1, sbuf2;
3217 pstring last_component_oldname;
3218 pstring last_component_newname;
3219 NTSTATUS status = NT_STATUS_OK;
3225 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3226 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3229 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3230 if (bad_path_oldname) {
3231 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3234 /* Quick check for "." and ".." */
3235 if (last_component_oldname[0] == '.') {
3236 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3237 return NT_STATUS_OBJECT_NAME_INVALID;
3241 /* source must already exist. */
3242 if (!VALID_STAT(sbuf1)) {
3243 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3246 if (!check_name(oldname,conn)) {
3247 return NT_STATUS_ACCESS_DENIED;
3250 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3251 if (bad_path_newname) {
3252 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3255 /* Quick check for "." and ".." */
3256 if (last_component_newname[0] == '.') {
3257 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3258 return NT_STATUS_OBJECT_NAME_INVALID;
3262 /* Disallow if newname already exists. */
3263 if (VALID_STAT(sbuf2)) {
3264 return NT_STATUS_OBJECT_NAME_COLLISION;
3267 if (!check_name(newname,conn)) {
3268 return NT_STATUS_ACCESS_DENIED;
3271 /* No links from a directory. */
3272 if (S_ISDIR(sbuf1.st_mode)) {
3273 return NT_STATUS_FILE_IS_A_DIRECTORY;
3276 /* Ensure this is within the share. */
3277 if (!reduce_name(conn, oldname) != 0)
3278 return NT_STATUS_ACCESS_DENIED;
3280 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3282 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3283 status = map_nt_error_from_unix(errno);
3284 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3285 nt_errstr(status), newname, oldname));
3291 /****************************************************************************
3292 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3293 ****************************************************************************/
3295 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3296 char **pparams, int total_params, char **ppdata, int total_data,
3297 unsigned int max_data_bytes)
3299 char *params = *pparams;
3300 char *pdata = *ppdata;
3301 uint16 tran_call = SVAL(inbuf, smb_setup0);
3306 SMB_STRUCT_STAT sbuf;
3309 BOOL bad_path = False;
3310 files_struct *fsp = NULL;
3311 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3312 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3313 mode_t unixmode = 0;
3314 NTSTATUS status = NT_STATUS_OK;
3317 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3321 if (tran_call == TRANSACT2_SETFILEINFO) {
3322 if (total_params < 4) {
3323 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3326 fsp = file_fsp(params,0);
3327 info_level = SVAL(params,2);
3329 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3331 * This is actually a SETFILEINFO on a directory
3332 * handle (returned from an NT SMB). NT5.0 seems
3333 * to do this call. JRA.
3335 pstrcpy(fname, fsp->fsp_name);
3336 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3337 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3338 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3340 } else if (fsp && fsp->print_file) {
3342 * Doing a DELETE_ON_CLOSE should cancel a print job.
3344 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3345 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3347 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3350 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3353 return (UNIXERROR(ERRDOS,ERRbadpath));
3356 * Original code - this is an open file.
3358 CHECK_FSP(fsp,conn);
3360 pstrcpy(fname, fsp->fsp_name);
3363 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3364 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3365 return(UNIXERROR(ERRDOS,ERRbadfid));
3370 if (total_params < 6) {
3371 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3374 info_level = SVAL(params,0);
3375 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3376 if (!NT_STATUS_IS_OK(status)) {
3377 return ERROR_NT(status);
3379 unix_convert(fname,conn,0,&bad_path,&sbuf);
3381 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3385 * For CIFS UNIX extensions the target name may not exist.
3388 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3389 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3390 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3393 if(!check_name(fname, conn)) {
3394 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3399 if (!CAN_WRITE(conn))
3400 return ERROR_DOS(ERRSRV,ERRaccess);
3402 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3403 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3405 if (VALID_STAT(sbuf))
3406 unixmode = sbuf.st_mode;
3408 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3409 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3411 /* Realloc the parameter and data sizes */
3412 params = SMB_REALLOC(*pparams,2);
3414 return ERROR_DOS(ERRDOS,ERRnomem);
3419 if (fsp && fsp->pending_modtime) {
3420 /* the pending modtime overrides the current modtime */
3421 sbuf.st_mtime = fsp->pending_modtime;
3424 size = get_file_size(sbuf);
3425 tvs.modtime = sbuf.st_mtime;
3426 tvs.actime = sbuf.st_atime;
3427 dosmode = dos_mode(conn,fname,&sbuf);
3428 unixmode = sbuf.st_mode;
3430 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3431 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3433 switch (info_level) {
3434 case SMB_INFO_STANDARD:
3436 if (total_data < 12) {
3437 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3441 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3443 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3447 case SMB_INFO_SET_EA:
3448 status = set_ea(conn, fsp, fname, pdata, total_data);
3449 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3450 return ERROR_NT(status);
3454 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3455 /* XXXX um, i don't think this is right.
3456 it's also not in the cifs6.txt spec.
3458 case SMB_INFO_QUERY_EAS_FROM_LIST:
3459 if (total_data < 28)
3460 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3462 tvs.actime = make_unix_date2(pdata+8);
3463 tvs.modtime = make_unix_date2(pdata+12);
3464 size = IVAL(pdata,16);
3465 dosmode = IVAL(pdata,24);
3468 /* XXXX nor this. not in cifs6.txt, either. */
3469 case SMB_INFO_QUERY_ALL_EAS:
3470 if (total_data < 28)
3471 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3473 tvs.actime = make_unix_date2(pdata+8);
3474 tvs.modtime = make_unix_date2(pdata+12);
3475 size = IVAL(pdata,16);
3476 dosmode = IVAL(pdata,24);
3480 case SMB_SET_FILE_BASIC_INFO:
3481 case SMB_FILE_BASIC_INFORMATION:
3483 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3485 time_t changed_time;
3487 if (total_data < 36) {
3488 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3491 /* Ignore create time at offset pdata. */
3494 tvs.actime = interpret_long_date(pdata+8);
3496 write_time = interpret_long_date(pdata+16);
3497 changed_time = interpret_long_date(pdata+24);
3499 tvs.modtime = MIN(write_time, changed_time);
3501 if (write_time > tvs.modtime && write_time != (time_t)-1) {
3502 tvs.modtime = write_time;
3504 /* Prefer a defined time to an undefined one. */
3505 if (null_mtime(tvs.modtime)) {
3506 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3510 dosmode = IVAL(pdata,32);
3514 case SMB_FILE_ALLOCATION_INFORMATION:
3515 case SMB_SET_FILE_ALLOCATION_INFO:
3518 SMB_BIG_UINT allocation_size;
3520 if (total_data < 8) {
3521 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3524 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3525 #ifdef LARGE_SMB_OFF_T
3526 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3527 #else /* LARGE_SMB_OFF_T */
3528 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3529 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3530 #endif /* LARGE_SMB_OFF_T */
3531 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3532 fname, (double)allocation_size ));
3534 if (allocation_size) {
3535 allocation_size = smb_roundup(conn, allocation_size);
3538 if(allocation_size != get_file_size(sbuf)) {
3539 SMB_STRUCT_STAT new_sbuf;
3541 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3542 fname, (double)allocation_size ));
3545 files_struct *new_fsp = NULL;
3546 int access_mode = 0;
3549 if(global_oplock_break) {
3550 /* Queue this file modify as we are the process of an oplock break. */
3552 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3553 DEBUGADD(2,( "in oplock break state.\n"));
3555 push_oplock_pending_smb_message(inbuf, length);
3559 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3560 SET_OPEN_MODE(DOS_OPEN_RDWR),
3561 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3562 FILE_ATTRIBUTE_NORMAL,
3563 INTERNAL_OPEN_ONLY, &access_mode, &action);
3565 if (new_fsp == NULL)
3566 return(UNIXERROR(ERRDOS,ERRbadpath));
3567 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3568 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3569 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3570 new_fsp->fnum, strerror(errno)));
3573 close_file(new_fsp,True);
3575 ret = vfs_allocate_file_space(fsp, allocation_size);
3576 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3577 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3578 fsp->fnum, strerror(errno)));
3583 return ERROR_NT(NT_STATUS_DISK_FULL);
3585 /* Allocate can truncate size... */
3586 size = get_file_size(new_sbuf);
3592 case SMB_FILE_END_OF_FILE_INFORMATION:
3593 case SMB_SET_FILE_END_OF_FILE_INFO:
3595 if (total_data < 8) {
3596 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3599 size = IVAL(pdata,0);
3600 #ifdef LARGE_SMB_OFF_T
3601 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3602 #else /* LARGE_SMB_OFF_T */
3603 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3604 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3605 #endif /* LARGE_SMB_OFF_T */
3606 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3610 case SMB_FILE_DISPOSITION_INFORMATION:
3611 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3613 BOOL delete_on_close;
3615 if (total_data < 1) {
3616 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3619 delete_on_close = (CVAL(pdata,0) ? True : False);
3621 /* Just ignore this set on a path. */
3622 if (tran_call != TRANSACT2_SETFILEINFO)
3626 return(UNIXERROR(ERRDOS,ERRbadfid));
3628 status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3630 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3631 return ERROR_NT(status);
3633 /* The set is across all open files on this dev/inode pair. */
3634 status =set_delete_on_close_over_all(fsp, delete_on_close);
3635 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3636 return ERROR_NT(status);
3641 case SMB_FILE_POSITION_INFORMATION:
3643 SMB_BIG_UINT position_information;
3645 if (total_data < 8) {
3646 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3649 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3650 #ifdef LARGE_SMB_OFF_T
3651 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3652 #else /* LARGE_SMB_OFF_T */
3653 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3654 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3655 #endif /* LARGE_SMB_OFF_T */
3656 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3657 fname, (double)position_information ));
3659 fsp->position_information = position_information;
3663 /* From tridge Samba4 :
3664 * MODE_INFORMATION in setfileinfo (I have no
3665 * idea what "mode information" on a file is - it takes a value of 0,
3666 * 2, 4 or 6. What could it be?).
3669 case SMB_FILE_MODE_INFORMATION:
3673 if (total_data < 4) {
3674 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3676 mode = IVAL(pdata,0);
3677 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
3678 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3684 * CIFS UNIX extensions.
3687 case SMB_SET_FILE_UNIX_BASIC:
3689 uint32 raw_unixmode;
3691 if (total_data < 100) {
3692 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3695 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3696 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3697 size=IVAL(pdata,0); /* first 8 Bytes are size */
3698 #ifdef LARGE_SMB_OFF_T
3699 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3700 #else /* LARGE_SMB_OFF_T */
3701 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3702 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3703 #endif /* LARGE_SMB_OFF_T */
3705 pdata+=24; /* ctime & st_blocks are not changed */
3706 tvs.actime = interpret_long_date(pdata); /* access_time */
3707 tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
3709 set_owner = (uid_t)IVAL(pdata,0);
3711 set_grp = (gid_t)IVAL(pdata,0);
3713 raw_unixmode = IVAL(pdata,28);
3714 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3715 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3717 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3718 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3719 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3721 if (!VALID_STAT(sbuf)) {
3724 * The only valid use of this is to create character and block
3725 * devices, and named pipes. This is deprecated (IMHO) and
3726 * a new info level should be used for mknod. JRA.
3729 uint32 file_type = IVAL(pdata,0);
3730 #if defined(HAVE_MAKEDEV)
3731 uint32 dev_major = IVAL(pdata,4);
3732 uint32 dev_minor = IVAL(pdata,12);
3735 uid_t myuid = geteuid();
3736 gid_t mygid = getegid();
3737 SMB_DEV_T dev = (SMB_DEV_T)0;
3739 if (tran_call == TRANSACT2_SETFILEINFO)
3740 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3742 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
3743 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3746 #if defined(HAVE_MAKEDEV)
3747 dev = makedev(dev_major, dev_minor);
3750 /* We can only create as the owner/group we are. */
3752 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3753 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3754 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3755 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3757 switch (file_type) {
3758 #if defined(S_IFIFO)
3759 case UNIX_TYPE_FIFO:
3760 unixmode |= S_IFIFO;
3763 #if defined(S_IFSOCK)
3764 case UNIX_TYPE_SOCKET:
3765 unixmode |= S_IFSOCK;
3768 #if defined(S_IFCHR)
3769 case UNIX_TYPE_CHARDEV:
3770 unixmode |= S_IFCHR;
3773 #if defined(S_IFBLK)
3774 case UNIX_TYPE_BLKDEV:
3775 unixmode |= S_IFBLK;
3779 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3782 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3783 0%o for file %s\n", (double)dev, unixmode, fname ));
3785 /* Ok - do the mknod. */
3786 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
3787 return(UNIXERROR(ERRDOS,ERRnoaccess));
3789 inherit_access_acl(conn, fname, unixmode);
3792 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3797 * Deal with the UNIX specific mode set.
3800 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3801 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3802 (unsigned int)unixmode, fname ));
3803 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3804 return(UNIXERROR(ERRDOS,ERRnoaccess));
3808 * Deal with the UNIX specific uid set.
3811 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3812 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3813 (unsigned int)set_owner, fname ));
3814 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3815 return(UNIXERROR(ERRDOS,ERRnoaccess));
3819 * Deal with the UNIX specific gid set.
3822 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3823 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3824 (unsigned int)set_owner, fname ));
3825 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3826 return(UNIXERROR(ERRDOS,ERRnoaccess));
3831 case SMB_SET_FILE_UNIX_LINK:
3833 pstring link_target;
3834 char *newname = fname;
3836 /* Set a symbolic link. */
3837 /* Don't allow this if follow links is false. */
3839 if (!lp_symlinks(SNUM(conn)))
3840 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3842 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
3844 /* !widelinks forces the target path to be within the share. */
3845 /* This means we can interpret the target as a pathname. */
3846 if (!lp_widelinks(SNUM(conn))) {
3848 char *last_dirp = NULL;
3850 unix_format(link_target);
3851 if (*link_target == '/') {
3852 /* No absolute paths allowed. */
3853 return(UNIXERROR(ERRDOS,ERRnoaccess));
3855 pstrcpy(rel_name, newname);
3856 last_dirp = strrchr_m(rel_name, '/');
3858 last_dirp[1] = '\0';
3860 pstrcpy(rel_name, "./");
3862 pstrcat(rel_name, link_target);
3864 if (!check_name(rel_name, conn)) {
3865 return(UNIXERROR(ERRDOS,ERRnoaccess));
3869 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3870 fname, link_target ));
3872 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
3873 return(UNIXERROR(ERRDOS,ERRnoaccess));
3875 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3879 case SMB_SET_FILE_UNIX_HLINK:
3882 char *newname = fname;
3884 /* Set a hard link. */
3885 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
3886 if (!NT_STATUS_IS_OK(status)) {
3887 return ERROR_NT(status);
3890 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3893 status = hardlink_internals(conn, oldname, newname);
3894 if (!NT_STATUS_IS_OK(status)) {
3895 return ERROR_NT(status);
3899 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3903 case SMB_FILE_RENAME_INFORMATION:
3912 if (total_data < 12) {
3913 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3916 overwrite = (CVAL(pdata,0) ? True : False);
3917 root_fid = IVAL(pdata,4);
3918 len = IVAL(pdata,8);
3919 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
3920 if (!NT_STATUS_IS_OK(status)) {
3921 return ERROR_NT(status);
3924 /* Check the new name has no '/' characters. */
3925 if (strchr_m(newname, '/'))
3926 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3928 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3930 /* Create the base directory. */
3931 pstrcpy(base_name, fname);
3932 p = strrchr_m(base_name, '/');
3935 /* Append the new name. */
3936 pstrcat(base_name, "/");
3937 pstrcat(base_name, newname);
3940 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3941 fsp->fnum, fsp->fsp_name, base_name ));
3942 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
3944 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3946 status = rename_internals(conn, fname, base_name, 0, overwrite);
3948 if (!NT_STATUS_IS_OK(status)) {
3949 return ERROR_NT(status);
3951 process_pending_change_notify_queue((time_t)0);
3953 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3957 #if defined(HAVE_POSIX_ACLS)
3958 case SMB_SET_POSIX_ACL:
3960 uint16 posix_acl_version;
3961 uint16 num_file_acls;
3962 uint16 num_def_acls;
3963 BOOL valid_file_acls = True;
3964 BOOL valid_def_acls = True;
3966 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
3967 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3969 posix_acl_version = SVAL(pdata,0);
3970 num_file_acls = SVAL(pdata,2);
3971 num_def_acls = SVAL(pdata,4);
3973 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3974 valid_file_acls = False;
3978 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3979 valid_def_acls = False;
3983 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
3984 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3987 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
3988 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
3989 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3992 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
3993 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
3994 return(UNIXERROR(ERRDOS,ERRnoaccess));
3997 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
3998 pdata + SMB_POSIX_ACL_HEADER_SIZE +
3999 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4000 return(UNIXERROR(ERRDOS,ERRnoaccess));
4004 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4010 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4013 /* get some defaults (no modifications) if any info is zero or -1. */
4014 if (null_mtime(tvs.actime)) {
4015 tvs.actime = sbuf.st_atime;
4018 if (null_mtime(tvs.modtime)) {
4019 tvs.modtime = sbuf.st_mtime;
4022 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4023 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4024 DEBUG(6,("size: %.0f ", (double)size));
4027 if (S_ISDIR(sbuf.st_mode))
4033 DEBUG(6,("dosmode: %x\n" , dosmode));
4035 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4036 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4037 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4038 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4041 * Only do this test if we are not explicitly
4042 * changing the size of a file.
4045 size = get_file_size(sbuf);
4049 * Try and set the times, size and mode of this file -
4050 * if they are different from the current values
4053 /* check the mode isn't different, before changing it */
4054 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4056 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4058 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4059 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4060 return(UNIXERROR(ERRDOS,ERRnoaccess));
4065 if (size != get_file_size(sbuf)) {
4069 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4070 fname, (double)size ));
4073 files_struct *new_fsp = NULL;
4074 int access_mode = 0;
4077 if(global_oplock_break) {
4078 /* Queue this file modify as we are the process of an oplock break. */
4080 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
4081 DEBUGADD(2,( "in oplock break state.\n"));
4083 push_oplock_pending_smb_message(inbuf, length);
4087 new_fsp = open_file_shared(conn, fname, &sbuf,
4088 SET_OPEN_MODE(DOS_OPEN_RDWR),
4089 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
4090 FILE_ATTRIBUTE_NORMAL,
4091 INTERNAL_OPEN_ONLY, &access_mode, &action);
4093 if (new_fsp == NULL)
4094 return(UNIXERROR(ERRDOS,ERRbadpath));
4095 ret = vfs_set_filelen(new_fsp, size);
4096 close_file(new_fsp,True);
4098 ret = vfs_set_filelen(fsp, size);
4102 return (UNIXERROR(ERRHRD,ERRdiskfull));
4106 * Finally the times.
4108 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4111 * This was a setfileinfo on an open file.
4112 * NT does this a lot. We also need to
4113 * set the time here, as it can be read by
4114 * FindFirst/FindNext and with the patch for bug #2045
4115 * in smbd/fileio.c it ensures that this timestamp is
4116 * kept sticky even after a write. We save the request
4117 * away and will set it on file close and after a write. JRA.
4120 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4121 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4122 fsp_set_pending_modtime(fsp, tvs.modtime);
4126 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4128 if(file_utime(conn, fname, &tvs)!=0) {
4129 return(UNIXERROR(ERRDOS,ERRnoaccess));
4134 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4139 /****************************************************************************
4140 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4141 ****************************************************************************/
4143 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4144 char **pparams, int total_params, char **ppdata, int total_data,
4145 unsigned int max_data_bytes)
4147 char *params = *pparams;
4150 SMB_STRUCT_STAT sbuf;
4151 BOOL bad_path = False;
4152 NTSTATUS status = NT_STATUS_OK;
4154 if (!CAN_WRITE(conn))
4155 return ERROR_DOS(ERRSRV,ERRaccess);
4157 if (total_params < 4) {
4158 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4161 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4162 if (!NT_STATUS_IS_OK(status)) {
4163 return ERROR_NT(status);
4166 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4168 unix_convert(directory,conn,0,&bad_path,&sbuf);
4170 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4172 if (check_name(directory,conn))
4173 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4176 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4177 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4180 /* Realloc the parameter and data sizes */
4181 params = SMB_REALLOC(*pparams,2);
4183 return ERROR_DOS(ERRDOS,ERRnomem);
4188 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4193 /****************************************************************************
4194 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4195 We don't actually do this - we just send a null response.
4196 ****************************************************************************/
4198 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4199 char **pparams, int total_params, char **ppdata, int total_data,
4200 unsigned int max_data_bytes)
4202 static uint16 fnf_handle = 257;
4203 char *params = *pparams;
4206 if (total_params < 6) {
4207 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4210 info_level = SVAL(params,4);
4211 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4213 switch (info_level) {
4218 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4221 /* Realloc the parameter and data sizes */
4222 params = SMB_REALLOC(*pparams,6);
4224 return ERROR_DOS(ERRDOS,ERRnomem);
4227 SSVAL(params,0,fnf_handle);
4228 SSVAL(params,2,0); /* No changes */
4229 SSVAL(params,4,0); /* No EA errors */
4236 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4241 /****************************************************************************
4242 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4243 changes). Currently this does nothing.
4244 ****************************************************************************/
4246 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4247 char **pparams, int total_params, char **ppdata, int total_data,
4248 unsigned int max_data_bytes)
4250 char *params = *pparams;
4252 DEBUG(3,("call_trans2findnotifynext\n"));
4254 /* Realloc the parameter and data sizes */
4255 params = SMB_REALLOC(*pparams,4);
4257 return ERROR_DOS(ERRDOS,ERRnomem);
4260 SSVAL(params,0,0); /* No changes */
4261 SSVAL(params,2,0); /* No EA errors */
4263 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4268 /****************************************************************************
4269 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4270 ****************************************************************************/
4272 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4273 char **pparams, int total_params, char **ppdata, int total_data,
4274 unsigned int max_data_bytes)
4276 char *params = *pparams;
4279 int max_referral_level;
4281 DEBUG(10,("call_trans2getdfsreferral\n"));
4283 if (total_params < 2) {
4284 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4287 max_referral_level = SVAL(params,0);
4289 if(!lp_host_msdfs())
4290 return ERROR_DOS(ERRDOS,ERRbadfunc);
4292 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4293 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4294 return UNIXERROR(ERRDOS,ERRbadfile);
4296 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4297 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4302 #define LMCAT_SPL 0x53
4303 #define LMFUNC_GETJOBID 0x60
4305 /****************************************************************************
4306 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4307 ****************************************************************************/
4309 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4310 char **pparams, int total_params, char **ppdata, int total_data,
4311 unsigned int max_data_bytes)
4313 char *pdata = *ppdata;
4314 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4316 /* check for an invalid fid before proceeding */
4319 return(ERROR_DOS(ERRDOS,ERRbadfid));
4321 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4322 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4323 pdata = SMB_REALLOC(*ppdata, 32);
4325 return ERROR_DOS(ERRDOS,ERRnomem);
4328 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4329 CAN ACCEPT THIS IN UNICODE. JRA. */
4331 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4332 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4333 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4334 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4337 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4338 return ERROR_DOS(ERRSRV,ERRerror);
4342 /****************************************************************************
4343 Reply to a SMBfindclose (stop trans2 directory search).
4344 ****************************************************************************/
4346 int reply_findclose(connection_struct *conn,
4347 char *inbuf,char *outbuf,int length,int bufsize)
4350 int dptr_num=SVALS(inbuf,smb_vwv0);
4351 START_PROFILE(SMBfindclose);
4353 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4355 dptr_close(&dptr_num);
4357 outsize = set_message(outbuf,0,0,True);
4359 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4361 END_PROFILE(SMBfindclose);
4365 /****************************************************************************
4366 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4367 ****************************************************************************/
4369 int reply_findnclose(connection_struct *conn,
4370 char *inbuf,char *outbuf,int length,int bufsize)
4374 START_PROFILE(SMBfindnclose);
4376 dptr_num = SVAL(inbuf,smb_vwv0);
4378 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4380 /* We never give out valid handles for a
4381 findnotifyfirst - so any dptr_num is ok here.
4384 outsize = set_message(outbuf,0,0,True);
4386 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4388 END_PROFILE(SMBfindnclose);
4392 /****************************************************************************
4393 Reply to a SMBtranss2 - just ignore it!
4394 ****************************************************************************/
4396 int reply_transs2(connection_struct *conn,
4397 char *inbuf,char *outbuf,int length,int bufsize)
4399 START_PROFILE(SMBtranss2);
4400 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4401 END_PROFILE(SMBtranss2);
4405 /****************************************************************************
4406 Reply to a SMBtrans2.
4407 ****************************************************************************/
4409 int reply_trans2(connection_struct *conn,
4410 char *inbuf,char *outbuf,int length,int bufsize)
4413 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4414 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4415 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4417 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4418 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4419 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4420 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4421 int32 timeout = IVALS(inbuf,smb_timeout);
4423 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4424 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4425 char *params = NULL, *data = NULL;
4426 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4427 START_PROFILE(SMBtrans2);
4429 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4430 /* Queue this open message as we are the process of an
4433 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4434 DEBUGADD(2,( "in oplock break state.\n"));
4436 push_oplock_pending_smb_message(inbuf, length);
4437 END_PROFILE(SMBtrans2);
4441 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4442 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4443 END_PROFILE(SMBtrans2);
4444 return ERROR_DOS(ERRSRV,ERRaccess);
4447 outsize = set_message(outbuf,0,0,True);
4449 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4450 is so as a sanity check */
4453 * Need to have rc=0 for ioctl to get job id for OS/2.
4454 * Network printing will fail if function is not successful.
4455 * Similar function in reply.c will be used if protocol
4456 * is LANMAN1.0 instead of LM1.2X002.
4457 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4458 * outbuf doesn't have to be set(only job id is used).
4460 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4461 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4462 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4463 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4465 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4466 DEBUG(2,("Transaction is %d\n",tran_call));
4467 END_PROFILE(SMBtrans2);
4468 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4472 /* Allocate the space for the maximum needed parameters and data */
4473 if (total_params > 0)
4474 params = (char *)SMB_MALLOC(total_params);
4476 data = (char *)SMB_MALLOC(total_data);
4478 if ((total_params && !params) || (total_data && !data)) {
4479 DEBUG(2,("Out of memory in reply_trans2\n"));
4482 END_PROFILE(SMBtrans2);
4483 return ERROR_DOS(ERRDOS,ERRnomem);
4486 /* Copy the param and data bytes sent with this request into
4487 the params buffer */
4488 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4489 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4491 if (num_params > total_params || num_data > total_data)
4492 exit_server("invalid params in reply_trans2");
4495 unsigned int psoff = SVAL(inbuf, smb_psoff);
4496 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4498 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4499 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4501 memcpy( params, smb_base(inbuf) + psoff, num_params);
4504 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4505 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4507 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4508 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4510 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4513 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4515 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4516 /* We need to send an interim response then receive the rest
4517 of the parameter/data bytes */
4518 outsize = set_message(outbuf,0,0,True);
4519 srv_signing_trans_stop();
4520 if (!send_smb(smbd_server_fd(),outbuf))
4521 exit_server("reply_trans2: send_smb failed.");
4523 while (num_data_sofar < total_data ||
4524 num_params_sofar < total_params) {
4526 unsigned int param_disp;
4527 unsigned int param_off;
4528 unsigned int data_disp;
4529 unsigned int data_off;
4531 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4534 * The sequence number for the trans reply is always
4535 * based on the last secondary received.
4538 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4541 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4542 outsize = set_message(outbuf,0,0,True);
4544 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4546 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4547 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4551 /* Revise total_params and total_data in case
4552 they have changed downwards */
4553 if (SVAL(inbuf, smb_tpscnt) < total_params)
4554 total_params = SVAL(inbuf, smb_tpscnt);
4555 if (SVAL(inbuf, smb_tdscnt) < total_data)
4556 total_data = SVAL(inbuf, smb_tdscnt);
4558 num_params = SVAL(inbuf,smb_spscnt);
4559 param_off = SVAL(inbuf, smb_spsoff);
4560 param_disp = SVAL(inbuf, smb_spsdisp);
4561 num_params_sofar += num_params;
4563 num_data = SVAL(inbuf, smb_sdscnt);
4564 data_off = SVAL(inbuf, smb_sdsoff);
4565 data_disp = SVAL(inbuf, smb_sdsdisp);
4566 num_data_sofar += num_data;
4568 if (num_params_sofar > total_params || num_data_sofar > total_data)
4572 if (param_disp + num_params > total_params)
4574 if ((param_disp + num_params < param_disp) ||
4575 (param_disp + num_params < num_params))
4577 if (param_disp > total_params)
4579 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4580 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4582 if (params + param_disp < params)
4585 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
4588 if (data_disp + num_data > total_data)
4590 if ((data_disp + num_data < data_disp) ||
4591 (data_disp + num_data < num_data))
4593 if (data_disp > total_data)
4595 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4596 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4598 if (data + data_disp < data)
4601 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4606 if (Protocol >= PROTOCOL_NT1) {
4607 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4610 /* Now we must call the relevant TRANS2 function */
4612 case TRANSACT2_OPEN:
4613 START_PROFILE_NESTED(Trans2_open);
4614 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4615 ¶ms, total_params, &data, total_data, max_data_bytes);
4616 END_PROFILE_NESTED(Trans2_open);
4619 case TRANSACT2_FINDFIRST:
4620 START_PROFILE_NESTED(Trans2_findfirst);
4621 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4622 ¶ms, total_params, &data, total_data, max_data_bytes);
4623 END_PROFILE_NESTED(Trans2_findfirst);
4626 case TRANSACT2_FINDNEXT:
4627 START_PROFILE_NESTED(Trans2_findnext);
4628 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4629 ¶ms, total_params, &data, total_data, max_data_bytes);
4630 END_PROFILE_NESTED(Trans2_findnext);
4633 case TRANSACT2_QFSINFO:
4634 START_PROFILE_NESTED(Trans2_qfsinfo);
4635 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4636 ¶ms, total_params, &data, total_data, max_data_bytes);
4637 END_PROFILE_NESTED(Trans2_qfsinfo);
4640 #ifdef HAVE_SYS_QUOTAS
4641 case TRANSACT2_SETFSINFO:
4642 START_PROFILE_NESTED(Trans2_setfsinfo);
4643 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4644 ¶ms, total_params, &data, total_data, max_data_bytes);
4645 END_PROFILE_NESTED(Trans2_setfsinfo);
4648 case TRANSACT2_QPATHINFO:
4649 case TRANSACT2_QFILEINFO:
4650 START_PROFILE_NESTED(Trans2_qpathinfo);
4651 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4652 ¶ms, total_params, &data, total_data, max_data_bytes);
4653 END_PROFILE_NESTED(Trans2_qpathinfo);
4655 case TRANSACT2_SETPATHINFO:
4656 case TRANSACT2_SETFILEINFO:
4657 START_PROFILE_NESTED(Trans2_setpathinfo);
4658 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4659 ¶ms, total_params, &data, total_data, max_data_bytes);
4660 END_PROFILE_NESTED(Trans2_setpathinfo);
4663 case TRANSACT2_FINDNOTIFYFIRST:
4664 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4665 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4666 ¶ms, total_params, &data, total_data, max_data_bytes);
4667 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4670 case TRANSACT2_FINDNOTIFYNEXT:
4671 START_PROFILE_NESTED(Trans2_findnotifynext);
4672 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4673 ¶ms, total_params, &data, total_data, max_data_bytes);
4674 END_PROFILE_NESTED(Trans2_findnotifynext);
4676 case TRANSACT2_MKDIR:
4677 START_PROFILE_NESTED(Trans2_mkdir);
4678 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4679 ¶ms, total_params, &data, total_data, max_data_bytes);
4680 END_PROFILE_NESTED(Trans2_mkdir);
4683 case TRANSACT2_GET_DFS_REFERRAL:
4684 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4685 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4686 ¶ms, total_params, &data, total_data, max_data_bytes);
4687 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4689 case TRANSACT2_IOCTL:
4690 START_PROFILE_NESTED(Trans2_ioctl);
4691 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4692 ¶ms, total_params, &data, total_data, max_data_bytes);
4693 END_PROFILE_NESTED(Trans2_ioctl);
4696 /* Error in request */
4697 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4700 END_PROFILE(SMBtrans2);
4701 srv_signing_trans_stop();
4702 return ERROR_DOS(ERRSRV,ERRerror);
4705 /* As we do not know how many data packets will need to be
4706 returned here the various call_trans2xxxx calls
4707 must send their own. Thus a call_trans2xxx routine only
4708 returns a value other than -1 when it wants to send
4712 srv_signing_trans_stop();
4716 END_PROFILE(SMBtrans2);
4717 return outsize; /* If a correct response was needed the
4718 call_trans2xxx calls have already sent
4719 it. If outsize != -1 then it is returning */
4723 srv_signing_trans_stop();
4726 END_PROFILE(SMBtrans2);
4727 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);