2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2003
5 Copyright (C) Stefan (metze) Metzmacher 2003
7 Extensively modified by Andrew Tridgell, 1995
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 extern int smb_read_error;
28 extern fstring local_machine;
29 extern int global_oplock_break;
30 extern uint32 global_client_caps;
31 extern struct current_user current_user;
33 #define get_file_size(sbuf) ((sbuf).st_size)
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
36 /********************************************************************
37 Roundup a value to the nearest SMB_ROUNDUP_ALLOCATION_SIZE boundary.
38 Only do this for Windows clients.
39 ********************************************************************/
41 SMB_BIG_UINT smb_roundup(SMB_BIG_UINT val)
43 /* Only roundup for Windows clients. */
44 enum remote_arch_types ra_type = get_remote_arch();
45 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
46 val = SMB_ROUNDUP(val,SMB_ROUNDUP_ALLOCATION_SIZE);
51 /********************************************************************
52 Given a stat buffer return the allocated size on disk, taking into
54 ********************************************************************/
56 SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
60 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
61 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
63 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
66 if (!ret && fsp && fsp->initial_allocation_size)
67 ret = fsp->initial_allocation_size;
69 ret = smb_roundup(ret);
74 /****************************************************************************
75 Utility functions for dealing with extended attributes.
76 ****************************************************************************/
78 static const char *prohibited_ea_names[] = {
79 SAMBA_POSIX_INHERITANCE_EA_NAME,
80 SAMBA_XATTR_DOS_ATTRIB,
84 /****************************************************************************
85 Refuse to allow clients to overwrite our private xattrs.
86 ****************************************************************************/
88 static BOOL samba_private_attr_name(const char *unix_ea_name)
92 for (i = 0; prohibited_ea_names[i]; i++) {
93 if (strequal( prohibited_ea_names[i], unix_ea_name))
100 struct ea_list *next, *prev;
104 /****************************************************************************
105 Get one EA value. Fill in a struct ea_struct.
106 ****************************************************************************/
108 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
109 const char *fname, char *ea_name, struct ea_struct *pea)
111 /* Get the value of this xattr. Max size is 64k. */
112 size_t attr_size = 256;
118 val = talloc_realloc(mem_ctx, val, attr_size);
123 if (fsp && fsp->fd != -1) {
124 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
126 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
129 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
138 DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
139 dump_data(10, val, sizeret);
142 if (strnequal(ea_name, "user.", 5)) {
143 pea->name = &ea_name[5];
147 pea->value.data = val;
148 pea->value.length = (size_t)sizeret;
152 /****************************************************************************
153 Return a linked list of the total EA's. Plus the total size
154 ****************************************************************************/
156 static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, 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(mem_ctx, ea_namelist, 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: 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(mem_ctx, sizeof(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: 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: 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(char *pdata, unsigned int total_data_size,
233 connection_struct *conn, files_struct *fsp, const char *fname)
235 unsigned int ret_data_size = 4;
239 struct ea_list *ea_list;
241 SMB_ASSERT(total_data_size >= 4);
244 if (!lp_ea_support(SNUM(conn))) {
247 mem_ctx = talloc_init("fill_ea_buffer");
252 ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
254 talloc_destroy(mem_ctx);
258 if (total_ea_len > total_data_size) {
259 talloc_destroy(mem_ctx);
263 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
266 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
267 dos_namelen = strlen(dos_ea_name);
268 if (dos_namelen > 255 || dos_namelen == 0) {
271 if (ea_list->ea.value.length > 65535) {
274 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
278 /* We know we have room. */
279 SCVAL(p,0,ea_list->ea.flags);
280 SCVAL(p,1,dos_namelen);
281 SSVAL(p,2,ea_list->ea.value.length);
282 fstrcpy(p+4, dos_ea_name);
283 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
285 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
286 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
289 ret_data_size = PTR_DIFF(p, pdata);
290 DEBUG(10,("fill_ea_buffer: data_size = %u, total_ea_len = %u\n",
291 ret_data_size, total_ea_len ));
292 talloc_destroy(mem_ctx);
293 SIVAL(pdata,0,ret_data_size);
294 return ret_data_size;
297 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
299 size_t total_ea_len = 0;
300 TALLOC_CTX *mem_ctx = NULL;
302 if (!lp_ea_support(SNUM(conn))) {
305 mem_ctx = talloc_init("estimate_ea_size");
306 (void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
307 talloc_destroy(mem_ctx);
311 /****************************************************************************
312 Ensure the EA name is case insensitive by matching any existing EA name.
313 ****************************************************************************/
315 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
318 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
319 struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
321 for (; ea_list; ea_list = ea_list->next) {
322 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
323 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
324 &unix_ea_name[5], ea_list->ea.name));
325 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
329 talloc_destroy(mem_ctx);
332 /****************************************************************************
333 Set or delete an extended attribute.
334 ****************************************************************************/
336 static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname,
337 char *pdata, int total_data)
339 unsigned int namelen;
342 fstring unix_ea_name;
344 if (!lp_ea_support(SNUM(conn))) {
345 return NT_STATUS_EAS_NOT_SUPPORTED;
348 if (total_data < 8) {
349 return NT_STATUS_INVALID_PARAMETER;
352 if (IVAL(pdata,0) > total_data) {
353 DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data));
354 return NT_STATUS_INVALID_PARAMETER;
358 namelen = CVAL(pdata,1);
359 ealen = SVAL(pdata,2);
361 if (total_data < 8 + namelen + 1 + ealen) {
362 DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n",
363 (unsigned int)total_data, namelen, ealen));
364 return NT_STATUS_INVALID_PARAMETER;
367 if (pdata[namelen] != '\0') {
368 DEBUG(10,("set_ea: ea name not null terminated\n"));
369 return NT_STATUS_INVALID_PARAMETER;
372 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
373 pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE);
374 pdata += (namelen + 1);
376 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
378 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen));
380 DEBUG(10,("set_ea: data :\n"));
381 dump_data(10, pdata, ealen);
384 if (samba_private_attr_name(unix_ea_name)) {
385 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
386 return NT_STATUS_ACCESS_DENIED;
390 /* Remove the attribute. */
391 if (fsp && (fsp->fd != -1)) {
392 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
393 unix_ea_name, fsp->fsp_name));
394 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
396 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
397 unix_ea_name, fname));
398 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
401 /* Removing a non existent attribute always succeeds. */
402 if (ret == -1 && errno == ENOATTR) {
403 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name));
408 if (fsp && (fsp->fd != -1)) {
409 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
410 unix_ea_name, fsp->fsp_name));
411 ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0);
413 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
414 unix_ea_name, fname));
415 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0);
421 if (errno == ENOTSUP) {
422 return NT_STATUS_EAS_NOT_SUPPORTED;
425 return map_nt_error_from_unix(errno);
431 /****************************************************************************
432 Send the required number of replies back.
433 We assume all fields other than the data fields are
434 set correctly for the type of call.
435 HACK ! Always assumes smb_setup field is zero.
436 ****************************************************************************/
438 static int send_trans2_replies(char *outbuf,
445 /* As we are using a protocol > LANMAN1 then the max_send
446 variable must have been set in the sessetupX call.
447 This takes precedence over the max_xmit field in the
448 global struct. These different max_xmit variables should
449 be merged as this is now too confusing */
452 int data_to_send = datasize;
453 int params_to_send = paramsize;
457 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
458 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
459 int data_alignment_offset = 0;
461 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
463 set_message(outbuf,10,0,True);
465 /* If there genuinely are no parameters or data to send just send the empty packet */
467 if(params_to_send == 0 && data_to_send == 0) {
468 if (!send_smb(smbd_server_fd(),outbuf))
469 exit_server("send_trans2_replies: send_smb failed.");
473 /* When sending params and data ensure that both are nicely aligned */
474 /* Only do this alignment when there is also data to send - else
475 can cause NT redirector problems. */
477 if (((params_to_send % 4) != 0) && (data_to_send != 0))
478 data_alignment_offset = 4 - (params_to_send % 4);
480 /* Space is bufsize minus Netbios over TCP header minus SMB header */
481 /* The alignment_offset is to align the param bytes on an even byte
482 boundary. NT 4.0 Beta needs this to work correctly. */
484 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
486 /* useable_space can never be more than max_send minus the alignment offset. */
488 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
490 while (params_to_send || data_to_send) {
491 /* Calculate whether we will totally or partially fill this packet */
493 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
495 /* We can never send more than useable_space */
497 * Note that 'useable_space' does not include the alignment offsets,
498 * but we must include the alignment offsets in the calculation of
499 * the length of the data we send over the wire, as the alignment offsets
500 * are sent here. Fix from Marc_Jacobsen@hp.com.
503 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
505 set_message(outbuf, 10, total_sent_thistime, True);
507 /* Set total params and data to be sent */
508 SSVAL(outbuf,smb_tprcnt,paramsize);
509 SSVAL(outbuf,smb_tdrcnt,datasize);
511 /* Calculate how many parameters and data we can fit into
512 * this packet. Parameters get precedence
515 params_sent_thistime = MIN(params_to_send,useable_space);
516 data_sent_thistime = useable_space - params_sent_thistime;
517 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
519 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
521 /* smb_proff is the offset from the start of the SMB header to the
522 parameter bytes, however the first 4 bytes of outbuf are
523 the Netbios over TCP header. Thus use smb_base() to subtract
524 them from the calculation */
526 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
528 if(params_sent_thistime == 0)
529 SSVAL(outbuf,smb_prdisp,0);
531 /* Absolute displacement of param bytes sent in this packet */
532 SSVAL(outbuf,smb_prdisp,pp - params);
534 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
535 if(data_sent_thistime == 0) {
536 SSVAL(outbuf,smb_droff,0);
537 SSVAL(outbuf,smb_drdisp, 0);
539 /* The offset of the data bytes is the offset of the
540 parameter bytes plus the number of parameters being sent this time */
541 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
542 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
543 SSVAL(outbuf,smb_drdisp, pd - pdata);
546 /* Copy the param bytes into the packet */
548 if(params_sent_thistime)
549 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
551 /* Copy in the data bytes */
552 if(data_sent_thistime)
553 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
554 data_alignment_offset,pd,data_sent_thistime);
556 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
557 params_sent_thistime, data_sent_thistime, useable_space));
558 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
559 params_to_send, data_to_send, paramsize, datasize));
561 /* Send the packet */
562 if (!send_smb(smbd_server_fd(),outbuf))
563 exit_server("send_trans2_replies: send_smb failed.");
565 pp += params_sent_thistime;
566 pd += data_sent_thistime;
568 params_to_send -= params_sent_thistime;
569 data_to_send -= data_sent_thistime;
572 if(params_to_send < 0 || data_to_send < 0) {
573 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
574 params_to_send, data_to_send));
582 /****************************************************************************
583 Reply to a TRANSACT2_OPEN.
584 ****************************************************************************/
586 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
587 char **pparams, int total_params, char **ppdata, int total_data,
588 unsigned int max_data_bytes)
590 char *params = *pparams;
595 BOOL return_additional_info;
604 int fmode=0,mtime=0,rmode;
606 SMB_STRUCT_STAT sbuf;
608 BOOL bad_path = False;
613 * Ensure we have enough parameters to perform the operation.
616 if (total_params < 29)
617 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
619 open_mode = SVAL(params, 2);
620 open_attr = SVAL(params,6);
621 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
623 return_additional_info = BITSETW(params,0);
624 open_sattr = SVAL(params, 4);
625 open_time = make_unix_date3(params+8);
627 open_ofun = SVAL(params,12);
628 open_size = IVAL(params,14);
632 return(ERROR_DOS(ERRSRV,ERRaccess));
634 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
635 if (!NT_STATUS_IS_OK(status)) {
636 return ERROR_NT(status);
639 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
640 fname,open_mode, open_attr, open_ofun, open_size));
642 /* XXXX we need to handle passed times, sattr and flags */
644 unix_convert(fname,conn,0,&bad_path,&sbuf);
646 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
649 if (!check_name(fname,conn)) {
650 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
653 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
654 oplock_request, &rmode,&smb_action);
657 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
658 /* We have re-scheduled this call. */
659 clear_cached_errors();
662 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
665 size = get_file_size(sbuf);
666 fmode = dos_mode(conn,fname,&sbuf);
667 mtime = sbuf.st_mtime;
670 close_file(fsp,False);
671 return(ERROR_DOS(ERRDOS,ERRnoaccess));
674 /* Realloc the size of parameters and data we will return */
675 params = Realloc(*pparams, 28);
677 return(ERROR_DOS(ERRDOS,ERRnomem));
680 memset((char *)params,'\0',28);
681 SSVAL(params,0,fsp->fnum);
682 SSVAL(params,2,fmode);
683 put_dos_date2(params,4, mtime);
684 SIVAL(params,8, (uint32)size);
685 SSVAL(params,12,rmode);
687 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
688 smb_action |= EXTENDED_OPLOCK_GRANTED;
690 SSVAL(params,18,smb_action);
693 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
695 SIVAL(params,20,inode);
697 /* Send the required number of replies */
698 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
703 /*********************************************************
704 Routine to check if a given string matches exactly.
705 as a special case a mask of "." does NOT match. That
706 is required for correct wildcard semantics
707 Case can be significant or not.
708 **********************************************************/
710 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
712 if (mask[0] == '.' && mask[1] == 0)
715 return strcmp(str,mask)==0;
716 if (StrCaseCmp(str,mask) != 0) {
719 if (ms_has_wild(str)) {
725 /****************************************************************************
726 Return the filetype for UNIX extensions.
727 ****************************************************************************/
729 static uint32 unix_filetype(mode_t mode)
732 return UNIX_TYPE_FILE;
733 else if(S_ISDIR(mode))
734 return UNIX_TYPE_DIR;
736 else if(S_ISLNK(mode))
737 return UNIX_TYPE_SYMLINK;
740 else if(S_ISCHR(mode))
741 return UNIX_TYPE_CHARDEV;
744 else if(S_ISBLK(mode))
745 return UNIX_TYPE_BLKDEV;
748 else if(S_ISFIFO(mode))
749 return UNIX_TYPE_FIFO;
752 else if(S_ISSOCK(mode))
753 return UNIX_TYPE_SOCKET;
756 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
757 return UNIX_TYPE_UNKNOWN;
760 /****************************************************************************
761 Map wire perms onto standard UNIX permissions. Obey share restrictions.
762 ****************************************************************************/
764 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
768 if (perms == SMB_MODE_NO_CHANGE)
771 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
772 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
773 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
774 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
775 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
776 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
777 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
778 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
779 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
781 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
784 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
787 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
790 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
791 ret &= lp_dir_mask(SNUM(conn));
792 /* Add in force bits */
793 ret |= lp_force_dir_mode(SNUM(conn));
795 /* Apply mode mask */
796 ret &= lp_create_mask(SNUM(conn));
797 /* Add in force bits */
798 ret |= lp_force_create_mode(SNUM(conn));
804 /****************************************************************************
805 Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
806 ****************************************************************************/
808 time_t interpret_long_unix_date(char *p)
810 DEBUG(10,("interpret_long_unix_date\n"));
811 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
812 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
815 return interpret_long_date(p);
819 /****************************************************************************
820 Get a level dependent lanman2 dir entry.
821 ****************************************************************************/
823 static BOOL get_lanman2_dir_entry(connection_struct *conn,
824 void *inbuf, void *outbuf,
825 char *path_mask,int dirtype,int info_level,
826 int requires_resume_key,
827 BOOL dont_descend,char **ppdata,
828 char *base_data, int space_remaining,
829 BOOL *out_of_space, BOOL *got_exact_match,
834 SMB_STRUCT_STAT sbuf;
838 char *p, *q, *pdata = *ppdata;
842 SMB_OFF_T file_size = 0;
843 SMB_BIG_UINT allocation_size = 0;
845 time_t mdate=0, adate=0, cdate=0;
848 int nt_extmode; /* Used for NT connections instead of mode */
849 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
852 *out_of_space = False;
853 *got_exact_match = False;
858 p = strrchr_m(path_mask,'/');
865 pstrcpy(mask, path_mask);
870 /* Needed if we run out of space */
871 prev_dirpos = TellDir(conn->dirptr);
872 dname = ReadDirName(conn->dirptr);
875 * Due to bugs in NT client redirectors we are not using
876 * resume keys any more - set them to zero.
877 * Check out the related comments in findfirst/findnext.
883 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
884 (long)conn->dirptr,TellDir(conn->dirptr)));
889 pstrcpy(fname,dname);
891 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
892 got_match = mask_match(fname, mask, conn->case_sensitive);
894 if(!got_match && !mangle_is_8_3(fname, False)) {
897 * It turns out that NT matches wildcards against
898 * both long *and* short names. This may explain some
899 * of the wildcard wierdness from old DOS clients
900 * that some people have been seeing.... JRA.
904 pstrcpy( newname, fname);
905 mangle_map( newname, True, False, SNUM(conn));
906 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
907 got_match = mask_match(newname, mask, conn->case_sensitive);
911 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
912 if (dont_descend && !isdots)
915 pstrcpy(pathreal,conn->dirpath);
917 pstrcat(pathreal,"/");
918 pstrcat(pathreal,dname);
920 if (INFO_LEVEL_IS_UNIX(info_level)) {
921 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
922 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
923 pathreal,strerror(errno)));
926 } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
928 /* Needed to show the msdfs symlinks as
931 if(lp_host_msdfs() &&
932 lp_msdfs_root(SNUM(conn)) &&
933 is_msdfs_link(conn, pathreal, NULL, NULL,
936 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
937 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
941 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
942 pathreal,strerror(errno)));
947 mode = dos_mode(conn,pathreal,&sbuf);
949 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
950 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
954 file_size = get_file_size(sbuf);
955 allocation_size = get_allocation_size(NULL,&sbuf);
956 mdate = sbuf.st_mtime;
957 adate = sbuf.st_atime;
958 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
960 if (lp_dos_filetime_resolution(SNUM(conn))) {
967 /* This is necessary, as otherwise the
968 * desktop.ini file in this folder is
970 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
974 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
980 mangle_map(fname,False,True,SNUM(conn));
985 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
987 switch (info_level) {
988 case SMB_INFO_STANDARD:
989 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_STANDARD\n"));
990 if(requires_resume_key) {
994 put_dos_date2(p,l1_fdateCreation,cdate);
995 put_dos_date2(p,l1_fdateLastAccess,adate);
996 put_dos_date2(p,l1_fdateLastWrite,mdate);
997 SIVAL(p,l1_cbFile,(uint32)file_size);
998 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
999 SSVAL(p,l1_attrFile,mode);
1002 p += align_string(outbuf, p, 0);
1003 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1004 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1006 SCVAL(nameptr, -1, len - 2);
1008 SCVAL(nameptr, -1, 0);
1012 SCVAL(nameptr, -1, len - 1);
1014 SCVAL(nameptr, -1, 0);
1020 case SMB_INFO_QUERY_EA_SIZE:
1021 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_QUERY_EA_SIZE\n"));
1022 if(requires_resume_key) {
1026 put_dos_date2(p,l2_fdateCreation,cdate);
1027 put_dos_date2(p,l2_fdateLastAccess,adate);
1028 put_dos_date2(p,l2_fdateLastWrite,mdate);
1029 SIVAL(p,l2_cbFile,(uint32)file_size);
1030 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1031 SSVAL(p,l2_attrFile,mode);
1033 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1034 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1038 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1039 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1052 SCVAL(nameptr,0,len);
1054 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1057 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1058 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1059 was_8_3 = mangle_is_8_3(fname, True);
1061 SIVAL(p,0,reskey); p += 4;
1062 put_long_date(p,cdate); p += 8;
1063 put_long_date(p,adate); p += 8;
1064 put_long_date(p,mdate); p += 8;
1065 put_long_date(p,mdate); p += 8;
1066 SOFF_T(p,0,file_size); p += 8;
1067 SOFF_T(p,0,allocation_size); p += 8;
1068 SIVAL(p,0,nt_extmode); p += 4;
1069 q = p; p += 4; /* q is placeholder for name length. */
1071 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1072 SIVAL(p,0,ea_size); /* Extended attributes */
1075 /* Clear the short name buffer. This is
1076 * IMPORTANT as not doing so will trigger
1077 * a Win2k client bug. JRA.
1080 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1081 pstring mangled_name;
1082 pstrcpy(mangled_name, fname);
1083 mangle_map(mangled_name,True,True,SNUM(conn));
1084 mangled_name[12] = 0;
1085 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1092 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1095 len = PTR_DIFF(p, pdata);
1096 len = (len + 3) & ~3;
1101 case SMB_FIND_FILE_DIRECTORY_INFO:
1102 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1104 SIVAL(p,0,reskey); p += 4;
1105 put_long_date(p,cdate); p += 8;
1106 put_long_date(p,adate); p += 8;
1107 put_long_date(p,mdate); p += 8;
1108 put_long_date(p,mdate); p += 8;
1109 SOFF_T(p,0,file_size); p += 8;
1110 SOFF_T(p,0,allocation_size); p += 8;
1111 SIVAL(p,0,nt_extmode); p += 4;
1112 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1115 len = PTR_DIFF(p, pdata);
1116 len = (len + 3) & ~3;
1121 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1122 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1124 SIVAL(p,0,reskey); p += 4;
1125 put_long_date(p,cdate); p += 8;
1126 put_long_date(p,adate); p += 8;
1127 put_long_date(p,mdate); p += 8;
1128 put_long_date(p,mdate); p += 8;
1129 SOFF_T(p,0,file_size); p += 8;
1130 SOFF_T(p,0,allocation_size); p += 8;
1131 SIVAL(p,0,nt_extmode); p += 4;
1132 q = p; p += 4; /* q is placeholder for name length. */
1134 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1135 SIVAL(p,0,ea_size); /* Extended attributes */
1138 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1142 len = PTR_DIFF(p, pdata);
1143 len = (len + 3) & ~3;
1148 case SMB_FIND_FILE_NAMES_INFO:
1149 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1151 SIVAL(p,0,reskey); p += 4;
1153 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1154 acl on a dir (tridge) */
1155 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1158 len = PTR_DIFF(p, pdata);
1159 len = (len + 3) & ~3;
1164 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1165 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1167 SIVAL(p,0,reskey); p += 4;
1168 put_long_date(p,cdate); p += 8;
1169 put_long_date(p,adate); p += 8;
1170 put_long_date(p,mdate); p += 8;
1171 put_long_date(p,mdate); p += 8;
1172 SOFF_T(p,0,file_size); p += 8;
1173 SOFF_T(p,0,allocation_size); p += 8;
1174 SIVAL(p,0,nt_extmode); p += 4;
1175 q = p; p += 4; /* q is placeholder for name length. */
1177 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1178 SIVAL(p,0,ea_size); /* Extended attributes */
1181 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1182 SIVAL(p,0,sbuf.st_dev); p += 4;
1183 SIVAL(p,0,sbuf.st_ino); p += 4;
1184 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1187 len = PTR_DIFF(p, pdata);
1188 len = (len + 3) & ~3;
1193 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1194 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1195 was_8_3 = mangle_is_8_3(fname, True);
1197 SIVAL(p,0,reskey); p += 4;
1198 put_long_date(p,cdate); p += 8;
1199 put_long_date(p,adate); p += 8;
1200 put_long_date(p,mdate); p += 8;
1201 put_long_date(p,mdate); p += 8;
1202 SOFF_T(p,0,file_size); p += 8;
1203 SOFF_T(p,0,allocation_size); p += 8;
1204 SIVAL(p,0,nt_extmode); p += 4;
1205 q = p; p += 4; /* q is placeholder for name length */
1207 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1208 SIVAL(p,0,ea_size); /* Extended attributes */
1211 /* Clear the short name buffer. This is
1212 * IMPORTANT as not doing so will trigger
1213 * a Win2k client bug. JRA.
1216 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1217 pstring mangled_name;
1218 pstrcpy(mangled_name, fname);
1219 mangle_map(mangled_name,True,True,SNUM(conn));
1220 mangled_name[12] = 0;
1221 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1228 SSVAL(p,0,0); p += 2; /* Reserved ? */
1229 SIVAL(p,0,sbuf.st_dev); p += 4;
1230 SIVAL(p,0,sbuf.st_ino); p += 4;
1231 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1234 len = PTR_DIFF(p, pdata);
1235 len = (len + 3) & ~3;
1240 /* CIFS UNIX Extension. */
1242 case SMB_FIND_FILE_UNIX:
1243 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1245 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1247 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1248 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1251 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1254 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1255 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1256 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1259 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1263 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1267 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1270 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1274 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1278 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1281 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1285 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1289 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1292 len = PTR_DIFF(p, pdata);
1293 len = (len + 3) & ~3;
1294 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1296 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1305 if (PTR_DIFF(p,pdata) > space_remaining) {
1306 /* Move the dirptr back to prev_dirpos */
1307 SeekDir(conn->dirptr, prev_dirpos);
1308 *out_of_space = True;
1309 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1310 return False; /* Not finished - just out of space */
1313 /* Setup the last_filename pointer, as an offset from base_data */
1314 *last_name_off = PTR_DIFF(nameptr,base_data);
1315 /* Advance the data pointer to the next slot */
1321 /****************************************************************************
1322 Reply to a TRANS2_FINDFIRST.
1323 ****************************************************************************/
1325 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1326 char **pparams, int total_params, char **ppdata, int total_data,
1327 unsigned int max_data_bytes)
1329 /* We must be careful here that we don't return more than the
1330 allowed number of data bytes. If this means returning fewer than
1331 maxentries then so be it. We assume that the redirector has
1332 enough room for the fixed number of parameter bytes it has
1334 char *params = *pparams;
1335 char *pdata = *ppdata;
1336 int dirtype = SVAL(params,0);
1337 int maxentries = SVAL(params,2);
1338 uint16 findfirst_flags = SVAL(params,4);
1339 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1340 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1341 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1342 int info_level = SVAL(params,6);
1346 int last_name_off=0;
1350 BOOL finished = False;
1351 BOOL dont_descend = False;
1352 BOOL out_of_space = False;
1353 int space_remaining;
1354 BOOL bad_path = False;
1355 SMB_STRUCT_STAT sbuf;
1356 NTSTATUS ntstatus = NT_STATUS_OK;
1358 if (total_params < 12)
1359 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1361 *directory = *mask = 0;
1363 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1364 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1365 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1366 info_level, max_data_bytes));
1369 /* W2K3 seems to treat zero as 1. */
1373 switch (info_level) {
1374 case SMB_INFO_STANDARD:
1375 case SMB_INFO_QUERY_EA_SIZE:
1376 case SMB_FIND_FILE_DIRECTORY_INFO:
1377 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1378 case SMB_FIND_FILE_NAMES_INFO:
1379 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1380 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1381 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1383 case SMB_FIND_FILE_UNIX:
1384 if (!lp_unix_extensions())
1385 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1388 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1391 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1392 if (!NT_STATUS_IS_OK(ntstatus)) {
1393 return ERROR_NT(ntstatus);
1396 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
1398 unix_convert(directory,conn,0,&bad_path,&sbuf);
1400 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1402 if(!check_name(directory,conn)) {
1403 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1406 p = strrchr_m(directory,'/');
1408 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1409 if((directory[0] == '.') && (directory[1] == '\0'))
1412 pstrcpy(mask,directory);
1413 pstrcpy(directory,"./");
1419 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1421 pdata = Realloc(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1423 return(ERROR_DOS(ERRDOS,ERRnomem));
1426 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1428 /* Realloc the params space */
1429 params = Realloc(*pparams, 10);
1431 return ERROR_DOS(ERRDOS,ERRnomem);
1434 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1436 return(UNIXERROR(ERRDOS,ERRbadfile));
1438 /* Save the wildcard match and attribs we are using on this directory -
1439 needed as lanman2 assumes these are being saved between calls */
1441 if(!(wcard = strdup(mask))) {
1442 dptr_close(&dptr_num);
1443 return ERROR_DOS(ERRDOS,ERRnomem);
1446 dptr_set_wcard(dptr_num, wcard);
1447 dptr_set_attr(dptr_num, dirtype);
1449 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
1451 /* We don't need to check for VOL here as this is returned by
1452 a different TRANS2 call. */
1454 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1455 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1456 dont_descend = True;
1459 space_remaining = max_data_bytes;
1460 out_of_space = False;
1462 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1463 BOOL got_exact_match = False;
1465 /* this is a heuristic to avoid seeking the dirptr except when
1466 absolutely necessary. It allows for a filename of about 40 chars */
1467 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1468 out_of_space = True;
1471 finished = !get_lanman2_dir_entry(conn,
1473 mask,dirtype,info_level,
1474 requires_resume_key,dont_descend,
1475 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1479 if (finished && out_of_space)
1482 if (!finished && !out_of_space)
1486 * As an optimisation if we know we aren't looking
1487 * for a wildcard name (ie. the name matches the wildcard exactly)
1488 * then we can finish on any (first) match.
1489 * This speeds up large directory searches. JRA.
1495 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1498 /* Check if we can close the dirptr */
1499 if(close_after_first || (finished && close_if_end)) {
1500 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1501 dptr_close(&dptr_num);
1505 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1506 * from observation of NT.
1509 if(numentries == 0) {
1510 dptr_close(&dptr_num);
1511 return ERROR_DOS(ERRDOS,ERRbadfile);
1514 /* At this point pdata points to numentries directory entries. */
1516 /* Set up the return parameter block */
1517 SSVAL(params,0,dptr_num);
1518 SSVAL(params,2,numentries);
1519 SSVAL(params,4,finished);
1520 SSVAL(params,6,0); /* Never an EA error */
1521 SSVAL(params,8,last_name_off);
1523 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1525 if ((! *directory) && dptr_path(dptr_num))
1526 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1528 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1529 smb_fn_name(CVAL(inbuf,smb_com)),
1530 mask, directory, dirtype, numentries ) );
1533 * Force a name mangle here to ensure that the
1534 * mask as an 8.3 name is top of the mangled cache.
1535 * The reasons for this are subtle. Don't remove
1536 * this code unless you know what you are doing
1537 * (see PR#13758). JRA.
1540 if(!mangle_is_8_3_wildcards( mask, False))
1541 mangle_map(mask, True, True, SNUM(conn));
1546 /****************************************************************************
1547 Reply to a TRANS2_FINDNEXT.
1548 ****************************************************************************/
1550 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1551 char **pparams, int total_params, char **ppdata, int total_data,
1552 unsigned int max_data_bytes)
1554 /* We must be careful here that we don't return more than the
1555 allowed number of data bytes. If this means returning fewer than
1556 maxentries then so be it. We assume that the redirector has
1557 enough room for the fixed number of parameter bytes it has
1559 char *params = *pparams;
1560 char *pdata = *ppdata;
1561 int dptr_num = SVAL(params,0);
1562 int maxentries = SVAL(params,2);
1563 uint16 info_level = SVAL(params,4);
1564 uint32 resume_key = IVAL(params,6);
1565 uint16 findnext_flags = SVAL(params,10);
1566 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1567 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1568 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1569 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1570 pstring resume_name;
1576 int i, last_name_off=0;
1577 BOOL finished = False;
1578 BOOL dont_descend = False;
1579 BOOL out_of_space = False;
1580 int space_remaining;
1581 NTSTATUS ntstatus = NT_STATUS_OK;
1583 if (total_params < 12)
1584 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1586 *mask = *directory = *resume_name = 0;
1588 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1589 if (!NT_STATUS_IS_OK(ntstatus)) {
1590 return ERROR_NT(ntstatus);
1593 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1594 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1595 resume_key = %d resume name = %s continue=%d level = %d\n",
1596 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1597 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1600 /* W2K3 seems to treat zero as 1. */
1604 switch (info_level) {
1605 case SMB_INFO_STANDARD:
1606 case SMB_INFO_QUERY_EA_SIZE:
1607 case SMB_FIND_FILE_DIRECTORY_INFO:
1608 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1609 case SMB_FIND_FILE_NAMES_INFO:
1610 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1612 case SMB_FIND_FILE_UNIX:
1613 if (!lp_unix_extensions())
1614 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1617 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1620 pdata = Realloc( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1622 return ERROR_DOS(ERRDOS,ERRnomem);
1625 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1627 /* Realloc the params space */
1628 params = Realloc(*pparams, 6*SIZEOFWORD);
1629 if( params == NULL )
1630 return ERROR_DOS(ERRDOS,ERRnomem);
1634 /* Check that the dptr is valid */
1635 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1636 return ERROR_DOS(ERRDOS,ERRnofiles);
1638 string_set(&conn->dirpath,dptr_path(dptr_num));
1640 /* Get the wildcard mask from the dptr */
1641 if((p = dptr_wcard(dptr_num))== NULL) {
1642 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1643 return ERROR_DOS(ERRDOS,ERRnofiles);
1647 pstrcpy(directory,conn->dirpath);
1649 /* Get the attr mask from the dptr */
1650 dirtype = dptr_attr(dptr_num);
1652 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1653 dptr_num, mask, dirtype,
1655 TellDir(conn->dirptr)));
1657 /* We don't need to check for VOL here as this is returned by
1658 a different TRANS2 call. */
1660 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1661 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1662 dont_descend = True;
1665 space_remaining = max_data_bytes;
1666 out_of_space = False;
1669 * Seek to the correct position. We no longer use the resume key but
1670 * depend on the last file name instead.
1673 if(*resume_name && !continue_bit) {
1676 * Fix for NT redirector problem triggered by resume key indexes
1677 * changing between directory scans. We now return a resume key of 0
1678 * and instead look for the filename to continue from (also given
1679 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1680 * findfirst/findnext (as is usual) then the directory pointer
1681 * should already be at the correct place. Check this by scanning
1682 * backwards looking for an exact (ie. case sensitive) filename match.
1683 * If we get to the beginning of the directory and haven't found it then scan
1684 * forwards again looking for a match. JRA.
1687 int current_pos, start_pos;
1688 const char *dname = NULL;
1689 pstring dname_pstring;
1690 void *dirptr = conn->dirptr;
1691 start_pos = TellDir(dirptr);
1692 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1693 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1695 SeekDir(dirptr, current_pos);
1696 dname = ReadDirName(dirptr);
1699 * Remember, mangle_map is called by
1700 * get_lanman2_dir_entry(), so the resume name
1701 * could be mangled. Ensure we do the same
1705 /* make sure we get a copy that mangle_map can modify */
1707 pstrcpy(dname_pstring, dname);
1708 mangle_map( dname_pstring, False, True, SNUM(conn));
1710 if(strcsequal( resume_name, dname_pstring)) {
1711 SeekDir(dirptr, current_pos+1);
1712 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1719 * Scan forward from start if not found going backwards.
1722 if(current_pos < 0) {
1723 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1724 SeekDir(dirptr, start_pos);
1725 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; ++current_pos) {
1728 * Remember, mangle_map is called by
1729 * get_lanman2_dir_entry(), so the resume name
1730 * could be mangled. Ensure we do the same
1735 /* make sure we get a copy that mangle_map can modify */
1737 pstrcpy(dname_pstring, dname);
1738 mangle_map(dname_pstring, False, True, SNUM(conn));
1740 if(strcsequal( resume_name, dname_pstring)) {
1741 SeekDir(dirptr, current_pos+1);
1742 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1747 } /* end if current_pos */
1748 /* Can't find the name. Just resume from where we were... */
1750 SeekDir(dirptr, start_pos);
1752 } /* end if resume_name && !continue_bit */
1754 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1755 BOOL got_exact_match = False;
1757 /* this is a heuristic to avoid seeking the dirptr except when
1758 absolutely necessary. It allows for a filename of about 40 chars */
1759 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1760 out_of_space = True;
1763 finished = !get_lanman2_dir_entry(conn,
1765 mask,dirtype,info_level,
1766 requires_resume_key,dont_descend,
1767 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1771 if (finished && out_of_space)
1774 if (!finished && !out_of_space)
1778 * As an optimisation if we know we aren't looking
1779 * for a wildcard name (ie. the name matches the wildcard exactly)
1780 * then we can finish on any (first) match.
1781 * This speeds up large directory searches. JRA.
1787 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1790 /* Check if we can close the dirptr */
1791 if(close_after_request || (finished && close_if_end)) {
1792 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1793 dptr_close(&dptr_num); /* This frees up the saved mask */
1796 /* Set up the return parameter block */
1797 SSVAL(params,0,numentries);
1798 SSVAL(params,2,finished);
1799 SSVAL(params,4,0); /* Never an EA error */
1800 SSVAL(params,6,last_name_off);
1802 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1804 if ((! *directory) && dptr_path(dptr_num))
1805 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1807 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1808 smb_fn_name(CVAL(inbuf,smb_com)),
1809 mask, directory, dirtype, numentries ) );
1814 /****************************************************************************
1815 Reply to a TRANS2_QFSINFO (query filesystem info).
1816 ****************************************************************************/
1818 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1819 char **pparams, int total_params, char **ppdata, int total_data,
1820 unsigned int max_data_bytes)
1822 char *pdata = *ppdata;
1823 char *params = *pparams;
1824 uint16 info_level = SVAL(params,0);
1827 char *vname = volume_label(SNUM(conn));
1828 int snum = SNUM(conn);
1829 char *fstype = lp_fstype(SNUM(conn));
1832 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1834 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1835 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1836 return ERROR_DOS(ERRSRV,ERRinvdevice);
1839 pdata = Realloc(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1840 if ( pdata == NULL )
1841 return ERROR_DOS(ERRDOS,ERRnomem);
1844 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1846 switch (info_level) {
1847 case SMB_INFO_ALLOCATION:
1849 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1851 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1852 block_size = lp_block_size(snum);
1853 if (bsize < block_size) {
1854 SMB_BIG_UINT factor = block_size/bsize;
1859 if (bsize > block_size) {
1860 SMB_BIG_UINT factor = bsize/block_size;
1865 bytes_per_sector = 512;
1866 sectors_per_unit = bsize/bytes_per_sector;
1868 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1869 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1870 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1872 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1873 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1874 SIVAL(pdata,l1_cUnit,dsize);
1875 SIVAL(pdata,l1_cUnitAvail,dfree);
1876 SSVAL(pdata,l1_cbSector,bytes_per_sector);
1880 case SMB_INFO_VOLUME:
1881 /* Return volume name */
1883 * Add volume serial number - hash of a combination of
1884 * the called hostname and the service name.
1886 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1887 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1888 SCVAL(pdata,l2_vol_cch,len);
1889 data_len = l2_vol_szVolLabel + len;
1890 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1891 (unsigned)st.st_ctime, len, vname));
1894 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1895 case SMB_FS_ATTRIBUTE_INFORMATION:
1898 #if defined(HAVE_SYS_QUOTAS)
1899 quota_flag = FILE_VOLUME_QUOTAS;
1902 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1903 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1904 quota_flag); /* FS ATTRIBUTES */
1906 SIVAL(pdata,4,255); /* Max filename component length */
1907 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1908 and will think we can't do long filenames */
1909 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1911 data_len = 12 + len;
1914 case SMB_QUERY_FS_LABEL_INFO:
1915 case SMB_FS_LABEL_INFORMATION:
1916 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1921 case SMB_QUERY_FS_VOLUME_INFO:
1922 case SMB_FS_VOLUME_INFORMATION:
1925 * Add volume serial number - hash of a combination of
1926 * the called hostname and the service name.
1928 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1929 (str_checksum(local_machine)<<16));
1931 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1932 SIVAL(pdata,12,len);
1934 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1935 (int)strlen(vname),vname, lp_servicename(snum)));
1938 case SMB_QUERY_FS_SIZE_INFO:
1939 case SMB_FS_SIZE_INFORMATION:
1941 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1943 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1944 block_size = lp_block_size(snum);
1945 if (bsize < block_size) {
1946 SMB_BIG_UINT factor = block_size/bsize;
1951 if (bsize > block_size) {
1952 SMB_BIG_UINT factor = bsize/block_size;
1957 bytes_per_sector = 512;
1958 sectors_per_unit = bsize/bytes_per_sector;
1959 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1960 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1961 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1962 SBIG_UINT(pdata,0,dsize);
1963 SBIG_UINT(pdata,8,dfree);
1964 SIVAL(pdata,16,sectors_per_unit);
1965 SIVAL(pdata,20,bytes_per_sector);
1969 case SMB_FS_FULL_SIZE_INFORMATION:
1971 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1973 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1974 block_size = lp_block_size(snum);
1975 if (bsize < block_size) {
1976 SMB_BIG_UINT factor = block_size/bsize;
1981 if (bsize > block_size) {
1982 SMB_BIG_UINT factor = bsize/block_size;
1987 bytes_per_sector = 512;
1988 sectors_per_unit = bsize/bytes_per_sector;
1989 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1990 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1991 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1992 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1993 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1994 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1995 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1996 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2000 case SMB_QUERY_FS_DEVICE_INFO:
2001 case SMB_FS_DEVICE_INFORMATION:
2003 SIVAL(pdata,0,0); /* dev type */
2004 SIVAL(pdata,4,0); /* characteristics */
2007 #ifdef HAVE_SYS_QUOTAS
2008 case SMB_FS_QUOTA_INFORMATION:
2010 * what we have to send --metze:
2012 * Unknown1: 24 NULL bytes
2013 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2014 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2015 * Quota Flags: 2 byte :
2016 * Unknown3: 6 NULL bytes
2020 * details for Quota Flags:
2022 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2023 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2024 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2025 * 0x0001 Enable Quotas: enable quota for this fs
2029 /* we need to fake up a fsp here,
2030 * because its not send in this call
2033 SMB_NTQUOTA_STRUCT quotas;
2036 ZERO_STRUCT(quotas);
2043 if (current_user.uid != 0) {
2044 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2045 lp_servicename(SNUM(conn)),conn->user));
2046 return ERROR_DOS(ERRDOS,ERRnoaccess);
2049 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2050 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2051 return ERROR_DOS(ERRSRV,ERRerror);
2056 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2058 /* Unknown1 24 NULL bytes*/
2059 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2060 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2061 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2063 /* Default Soft Quota 8 bytes */
2064 SBIG_UINT(pdata,24,quotas.softlim);
2066 /* Default Hard Quota 8 bytes */
2067 SBIG_UINT(pdata,32,quotas.hardlim);
2069 /* Quota flag 2 bytes */
2070 SSVAL(pdata,40,quotas.qflags);
2072 /* Unknown3 6 NULL bytes */
2078 #endif /* HAVE_SYS_QUOTAS */
2079 case SMB_FS_OBJECTID_INFORMATION:
2084 * Query the version and capabilities of the CIFS UNIX extensions
2088 case SMB_QUERY_CIFS_UNIX_INFO:
2089 if (!lp_unix_extensions())
2090 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2092 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2093 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2094 SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
2097 case SMB_MAC_QUERY_FS_INFO:
2099 * Thursby MAC extension... ONLY on NTFS filesystems
2100 * once we do streams then we don't need this
2102 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2104 SIVAL(pdata,84,0x100); /* Don't support mac... */
2109 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2113 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2115 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2120 #ifdef HAVE_SYS_QUOTAS
2121 /****************************************************************************
2122 Reply to a TRANS2_SETFSINFO (set filesystem info).
2123 ****************************************************************************/
2125 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2126 char **pparams, int total_params, char **ppdata, int total_data,
2127 unsigned int max_data_bytes)
2129 char *pdata = *ppdata;
2130 char *params = *pparams;
2131 files_struct *fsp = NULL;
2134 SMB_NTQUOTA_STRUCT quotas;
2136 ZERO_STRUCT(quotas);
2138 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2141 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2142 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2143 lp_servicename(SNUM(conn)),conn->user));
2144 return ERROR_DOS(ERRSRV,ERRaccess);
2148 if (total_params < 4) {
2149 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2151 return ERROR_DOS(ERRDOS,ERRinvalidparam);
2154 fsp = file_fsp(params,0);
2156 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2157 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2158 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2161 info_level = SVAL(params,2);
2163 switch(info_level) {
2164 case SMB_FS_QUOTA_INFORMATION:
2165 /* note: normaly there're 48 bytes,
2166 * but we didn't use the last 6 bytes for now
2169 if (total_data < 42) {
2170 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2172 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2175 /* unknown_1 24 NULL bytes in pdata*/
2177 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2178 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2179 #ifdef LARGE_SMB_OFF_T
2180 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2181 #else /* LARGE_SMB_OFF_T */
2182 if ((IVAL(pdata,28) != 0)&&
2183 ((quotas.softlim != 0xFFFFFFFF)||
2184 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2185 /* more than 32 bits? */
2186 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2188 #endif /* LARGE_SMB_OFF_T */
2190 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2191 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2192 #ifdef LARGE_SMB_OFF_T
2193 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2194 #else /* LARGE_SMB_OFF_T */
2195 if ((IVAL(pdata,36) != 0)&&
2196 ((quotas.hardlim != 0xFFFFFFFF)||
2197 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2198 /* more than 32 bits? */
2199 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2201 #endif /* LARGE_SMB_OFF_T */
2203 /* quota_flags 2 bytes **/
2204 quotas.qflags = SVAL(pdata,40);
2206 /* unknown_2 6 NULL bytes follow*/
2208 /* now set the quotas */
2209 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2210 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2211 return ERROR_DOS(ERRSRV,ERRerror);
2216 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2218 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2223 * sending this reply works fine,
2224 * but I'm not sure it's the same
2225 * like windows do...
2228 outsize = set_message(outbuf,10,0,True);
2232 #endif /* HAVE_SYS_QUOTAS */
2234 /****************************************************************************
2235 Utility function to set bad path error.
2236 ****************************************************************************/
2238 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2240 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2241 err, (int)bad_path ));
2245 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2247 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2250 return UNIXERROR(def_class,def_code);
2253 /****************************************************************************
2254 Utility function to count the number of entries in a POSIX acl.
2255 ****************************************************************************/
2257 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2259 unsigned int ace_count = 0;
2260 int entry_id = SMB_ACL_FIRST_ENTRY;
2261 SMB_ACL_ENTRY_T entry;
2263 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2265 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2266 entry_id = SMB_ACL_NEXT_ENTRY;
2273 /****************************************************************************
2274 Utility function to marshall a POSIX acl into wire format.
2275 ****************************************************************************/
2277 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2279 int entry_id = SMB_ACL_FIRST_ENTRY;
2280 SMB_ACL_ENTRY_T entry;
2282 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2283 SMB_ACL_TAG_T tagtype;
2284 SMB_ACL_PERMSET_T permset;
2285 unsigned char perms = 0;
2286 unsigned int own_grp;
2289 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2290 entry_id = SMB_ACL_NEXT_ENTRY;
2293 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2294 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2298 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2299 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2303 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2304 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2305 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2307 SCVAL(pdata,1,perms);
2310 case SMB_ACL_USER_OBJ:
2311 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2312 own_grp = (unsigned int)pst->st_uid;
2313 SIVAL(pdata,2,own_grp);
2318 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2320 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2322 own_grp = (unsigned int)*puid;
2323 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2324 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2325 SIVAL(pdata,2,own_grp);
2329 case SMB_ACL_GROUP_OBJ:
2330 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2331 own_grp = (unsigned int)pst->st_gid;
2332 SIVAL(pdata,2,own_grp);
2337 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2339 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2341 own_grp = (unsigned int)*pgid;
2342 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2343 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2344 SIVAL(pdata,2,own_grp);
2349 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2350 SIVAL(pdata,2,0xFFFFFFFF);
2351 SIVAL(pdata,6,0xFFFFFFFF);
2354 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2355 SIVAL(pdata,2,0xFFFFFFFF);
2356 SIVAL(pdata,6,0xFFFFFFFF);
2359 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2362 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2368 /****************************************************************************
2369 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2370 file name or file id).
2371 ****************************************************************************/
2373 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2374 char **pparams, int total_params, char **ppdata, int total_data,
2375 unsigned int max_data_bytes)
2377 char *params = *pparams;
2378 char *pdata = *ppdata;
2379 uint16 tran_call = SVAL(inbuf, smb_setup0);
2382 SMB_OFF_T file_size=0;
2383 SMB_BIG_UINT allocation_size=0;
2384 unsigned int data_size;
2385 unsigned int param_size = 2;
2386 SMB_STRUCT_STAT sbuf;
2387 pstring fname, dos_fname;
2392 BOOL bad_path = False;
2393 BOOL delete_pending = False;
2396 files_struct *fsp = NULL;
2397 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2400 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2404 if (tran_call == TRANSACT2_QFILEINFO) {
2405 if (total_params < 4)
2406 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2408 fsp = file_fsp(params,0);
2409 info_level = SVAL(params,2);
2411 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2413 if(fsp && (fsp->fake_file_handle)) {
2415 * This is actually for the QUOTA_FAKE_FILE --metze
2418 pstrcpy(fname, fsp->fsp_name);
2419 /* We know this name is ok, it's already passed the checks. */
2421 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2423 * This is actually a QFILEINFO on a directory
2424 * handle (returned from an NT SMB). NT5.0 seems
2425 * to do this call. JRA.
2427 /* We know this name is ok, it's already passed the checks. */
2428 pstrcpy(fname, fsp->fsp_name);
2430 if (INFO_LEVEL_IS_UNIX(info_level)) {
2431 /* Always do lstat for UNIX calls. */
2432 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2433 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2434 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2436 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2437 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2438 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2441 delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2444 * Original code - this is an open file.
2446 CHECK_FSP(fsp,conn);
2448 pstrcpy(fname, fsp->fsp_name);
2449 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2450 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2451 return(UNIXERROR(ERRDOS,ERRbadfid));
2453 pos = fsp->position_information;
2454 delete_pending = fsp->delete_on_close;
2455 desired_access = fsp->desired_access;
2458 NTSTATUS status = NT_STATUS_OK;
2461 if (total_params < 6)
2462 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2464 info_level = SVAL(params,0);
2466 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2468 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2469 if (!NT_STATUS_IS_OK(status)) {
2470 return ERROR_NT(status);
2473 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2475 unix_convert(fname,conn,0,&bad_path,&sbuf);
2477 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2479 if (!check_name(fname,conn)) {
2480 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2481 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2484 if (INFO_LEVEL_IS_UNIX(info_level)) {
2485 /* Always do lstat for UNIX calls. */
2486 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2487 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2488 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2490 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2491 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2492 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2496 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2497 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2499 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2500 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2502 p = strrchr_m(fname,'/');
2508 mode = dos_mode(conn,fname,&sbuf);
2510 mode = FILE_ATTRIBUTE_NORMAL;
2512 fullpathname = fname;
2513 file_size = get_file_size(sbuf);
2514 allocation_size = get_allocation_size(fsp,&sbuf);
2516 /* This is necessary, as otherwise the desktop.ini file in
2517 * this folder is ignored */
2518 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2522 params = Realloc(*pparams,2);
2524 return ERROR_DOS(ERRDOS,ERRnomem);
2526 memset((char *)params,'\0',2);
2527 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2528 pdata = Realloc(*ppdata, data_size);
2529 if ( pdata == NULL )
2530 return ERROR_DOS(ERRDOS,ERRnomem);
2533 if (total_data > 0 && IVAL(pdata,0) == total_data) {
2534 /* uggh, EAs for OS2 */
2535 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2536 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2539 memset((char *)pdata,'\0',data_size);
2541 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2543 if (lp_dos_filetime_resolution(SNUM(conn))) {
2545 sbuf.st_atime &= ~1;
2546 sbuf.st_ctime &= ~1;
2547 sbuf.st_mtime &= ~1;
2550 /* NT expects the name to be in an exact form of the *full*
2551 filename. See the trans2 torture test */
2552 if (strequal(base_name,".")) {
2553 pstrcpy(dos_fname, "\\");
2555 pstr_sprintf(dos_fname, "\\%s", fname);
2556 string_replace(dos_fname, '/', '\\');
2559 switch (info_level) {
2560 case SMB_INFO_STANDARD:
2561 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2563 put_dos_date2(pdata,l1_fdateCreation,c_time);
2564 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2565 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2566 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2567 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2568 SSVAL(pdata,l1_attrFile,mode);
2571 case SMB_INFO_QUERY_EA_SIZE:
2573 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2574 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2576 put_dos_date2(pdata,l1_fdateCreation,c_time);
2577 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2578 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2579 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2580 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2581 SSVAL(pdata,l1_attrFile,mode);
2582 SIVAL(pdata,l1_attrFile+2,ea_size);
2586 case SMB_INFO_IS_NAME_VALID:
2587 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2588 if (tran_call == TRANSACT2_QFILEINFO) {
2589 /* os/2 needs this ? really ?*/
2590 return ERROR_DOS(ERRDOS,ERRbadfunc);
2596 case SMB_INFO_QUERY_EAS_FROM_LIST:
2597 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2599 put_dos_date2(pdata,0,c_time);
2600 put_dos_date2(pdata,4,sbuf.st_atime);
2601 put_dos_date2(pdata,8,sbuf.st_mtime);
2602 SIVAL(pdata,12,(uint32)file_size);
2603 SIVAL(pdata,16,(uint32)allocation_size);
2604 SIVAL(pdata,20,mode);
2607 case SMB_INFO_QUERY_ALL_EAS:
2608 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2609 /* We have data_size bytes to put EA's into. */
2610 data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname);
2613 case SMB_FILE_BASIC_INFORMATION:
2614 case SMB_QUERY_FILE_BASIC_INFO:
2616 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2617 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2618 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2620 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2624 put_long_date(pdata,c_time);
2625 put_long_date(pdata+8,sbuf.st_atime);
2626 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2627 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2628 SIVAL(pdata,32,mode);
2630 DEBUG(5,("SMB_QFBI - "));
2632 time_t create_time = c_time;
2633 DEBUG(5,("create: %s ", ctime(&create_time)));
2635 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2636 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2637 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2638 DEBUG(5,("mode: %x\n", mode));
2642 case SMB_FILE_STANDARD_INFORMATION:
2643 case SMB_QUERY_FILE_STANDARD_INFO:
2645 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2647 SOFF_T(pdata,0,allocation_size);
2648 SOFF_T(pdata,8,file_size);
2649 if (delete_pending & sbuf.st_nlink)
2650 SIVAL(pdata,16,sbuf.st_nlink - 1);
2652 SIVAL(pdata,16,sbuf.st_nlink);
2654 SCVAL(pdata,21,(mode&aDIR)?1:0);
2657 case SMB_FILE_EA_INFORMATION:
2658 case SMB_QUERY_FILE_EA_INFO:
2660 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2661 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2663 SIVAL(pdata,0,ea_size);
2667 /* Get the 8.3 name - used if NT SMB was negotiated. */
2668 case SMB_QUERY_FILE_ALT_NAME_INFO:
2669 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2673 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2674 pstrcpy(short_name,base_name);
2675 /* Mangle if not already 8.3 */
2676 if(!mangle_is_8_3(short_name, True)) {
2677 mangle_map(short_name,True,True,SNUM(conn));
2679 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2680 data_size = 4 + len;
2685 case SMB_QUERY_FILE_NAME_INFO:
2687 this must be *exactly* right for ACLs on mapped drives to work
2689 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2690 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2691 data_size = 4 + len;
2695 case SMB_FILE_ALLOCATION_INFORMATION:
2696 case SMB_QUERY_FILE_ALLOCATION_INFO:
2697 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2699 SOFF_T(pdata,0,allocation_size);
2702 case SMB_FILE_END_OF_FILE_INFORMATION:
2703 case SMB_QUERY_FILE_END_OF_FILEINFO:
2704 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2706 SOFF_T(pdata,0,file_size);
2709 case SMB_QUERY_FILE_ALL_INFO:
2710 case SMB_FILE_ALL_INFORMATION:
2712 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2713 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2714 put_long_date(pdata,c_time);
2715 put_long_date(pdata+8,sbuf.st_atime);
2716 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2717 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2718 SIVAL(pdata,32,mode);
2720 SOFF_T(pdata,0,allocation_size);
2721 SOFF_T(pdata,8,file_size);
2722 if (delete_pending && sbuf.st_nlink)
2723 SIVAL(pdata,16,sbuf.st_nlink - 1);
2725 SIVAL(pdata,16,sbuf.st_nlink);
2726 SCVAL(pdata,20,delete_pending);
2727 SCVAL(pdata,21,(mode&aDIR)?1:0);
2729 SIVAL(pdata,0,ea_size);
2730 pdata += 4; /* EA info */
2731 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2734 data_size = PTR_DIFF(pdata,(*ppdata));
2737 case SMB_FILE_INTERNAL_INFORMATION:
2738 /* This should be an index number - looks like
2741 I think this causes us to fail the IFSKIT
2742 BasicFileInformationTest. -tpot */
2744 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2745 SIVAL(pdata,0,sbuf.st_dev);
2746 SIVAL(pdata,4,sbuf.st_ino);
2750 case SMB_FILE_ACCESS_INFORMATION:
2751 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2752 SIVAL(pdata,0,desired_access);
2756 case SMB_FILE_NAME_INFORMATION:
2757 /* Pathname with leading '\'. */
2760 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2761 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2762 SIVAL(pdata,0,byte_len);
2763 data_size = 4 + byte_len;
2767 case SMB_FILE_DISPOSITION_INFORMATION:
2768 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2770 SCVAL(pdata,0,delete_pending);
2773 case SMB_FILE_POSITION_INFORMATION:
2774 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2776 SOFF_T(pdata,0,pos);
2779 case SMB_FILE_MODE_INFORMATION:
2780 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2781 SIVAL(pdata,0,mode);
2785 case SMB_FILE_ALIGNMENT_INFORMATION:
2786 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2787 SIVAL(pdata,0,0); /* No alignment needed. */
2793 * NT4 server just returns "invalid query" to this - if we try to answer
2794 * it then NTws gets a BSOD! (tridge).
2795 * W2K seems to want this. JRA.
2797 case SMB_QUERY_FILE_STREAM_INFO:
2799 case SMB_FILE_STREAM_INFORMATION:
2800 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2804 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2805 SIVAL(pdata,0,0); /* ??? */
2806 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2807 SOFF_T(pdata,8,file_size);
2808 SIVAL(pdata,16,allocation_size);
2809 SIVAL(pdata,20,0); /* ??? */
2810 data_size = 24 + byte_len;
2814 case SMB_QUERY_COMPRESSION_INFO:
2815 case SMB_FILE_COMPRESSION_INFORMATION:
2816 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2817 SOFF_T(pdata,0,file_size);
2818 SIVAL(pdata,8,0); /* ??? */
2819 SIVAL(pdata,12,0); /* ??? */
2823 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2824 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2825 put_long_date(pdata,c_time);
2826 put_long_date(pdata+8,sbuf.st_atime);
2827 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2828 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2829 SIVAL(pdata,32,allocation_size);
2830 SOFF_T(pdata,40,file_size);
2831 SIVAL(pdata,48,mode);
2832 SIVAL(pdata,52,0); /* ??? */
2836 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2837 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2838 SIVAL(pdata,0,mode);
2844 * CIFS UNIX Extensions.
2847 case SMB_QUERY_FILE_UNIX_BASIC:
2849 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2850 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2852 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2855 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2858 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2859 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2860 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2863 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2867 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2871 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2874 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2878 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2882 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2885 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2889 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2892 data_size = PTR_DIFF(pdata,(*ppdata));
2896 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2898 for (i=0; i<100; i++)
2899 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2905 case SMB_QUERY_FILE_UNIX_LINK:
2909 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
2911 if(!S_ISLNK(sbuf.st_mode))
2912 return(UNIXERROR(ERRSRV,ERRbadlink));
2914 return(UNIXERROR(ERRDOS,ERRbadlink));
2916 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2918 return(UNIXERROR(ERRDOS,ERRnoaccess));
2920 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2922 data_size = PTR_DIFF(pdata,(*ppdata));
2927 case SMB_QUERY_POSIX_ACL:
2929 SMB_ACL_T file_acl = NULL;
2930 SMB_ACL_T def_acl = NULL;
2931 uint16 num_file_acls = 0;
2932 uint16 num_def_acls = 0;
2934 if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
2935 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
2937 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
2940 if (file_acl == NULL && no_acl_syscall_error(errno)) {
2941 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
2943 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
2946 if (S_ISDIR(sbuf.st_mode)) {
2947 if (fsp && fsp->is_directory) {
2948 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
2950 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
2952 def_acl = free_empty_sys_acl(conn, def_acl);
2955 num_file_acls = count_acl_entries(conn, file_acl);
2956 num_def_acls = count_acl_entries(conn, def_acl);
2958 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
2959 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
2961 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
2962 SMB_POSIX_ACL_HEADER_SIZE) ));
2964 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2967 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2969 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2972 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
2973 SSVAL(pdata,2,num_file_acls);
2974 SSVAL(pdata,4,num_def_acls);
2975 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
2977 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2980 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2982 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
2984 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
2986 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2989 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2991 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
2995 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2998 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3000 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3005 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3008 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3013 /****************************************************************************
3014 Deal with the internal needs of setting the delete on close flag. Note that
3015 as the tdb locking is recursive, it is safe to call this from within
3016 open_file_shared. JRA.
3017 ****************************************************************************/
3019 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
3021 if (delete_on_close) {
3023 * Only allow delete on close for writable files.
3026 if (dosmode & aRONLY) {
3027 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
3029 return NT_STATUS_CANNOT_DELETE;
3033 * Only allow delete on close for writable shares.
3036 if (!CAN_WRITE(fsp->conn)) {
3037 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
3039 return NT_STATUS_ACCESS_DENIED;
3043 * Only allow delete on close for files/directories opened with delete intent.
3046 if (!(fsp->desired_access & DELETE_ACCESS)) {
3047 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
3049 return NT_STATUS_ACCESS_DENIED;
3053 if(fsp->is_directory) {
3054 fsp->directory_delete_on_close = delete_on_close;
3055 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3056 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3058 fsp->delete_on_close = delete_on_close;
3059 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3060 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3063 return NT_STATUS_OK;
3066 /****************************************************************************
3067 Sets the delete on close flag over all share modes on this file.
3068 Modify the share mode entry for all files open
3069 on this device and inode to tell other smbds we have
3070 changed the delete on close flag. This will be noticed
3071 in the close code, the last closer will delete the file
3073 ****************************************************************************/
3075 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3077 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3078 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3080 if (fsp->is_directory || fsp->is_stat)
3081 return NT_STATUS_OK;
3083 if (lock_share_entry_fsp(fsp) == False)
3084 return NT_STATUS_ACCESS_DENIED;
3086 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3087 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3089 unlock_share_entry_fsp(fsp);
3090 return NT_STATUS_ACCESS_DENIED;
3093 unlock_share_entry_fsp(fsp);
3094 return NT_STATUS_OK;
3097 /****************************************************************************
3098 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3100 ****************************************************************************/
3102 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3104 BOOL bad_path_oldname = False;
3105 BOOL bad_path_newname = False;
3106 SMB_STRUCT_STAT sbuf1, sbuf2;
3107 pstring last_component_oldname;
3108 pstring last_component_newname;
3109 NTSTATUS status = NT_STATUS_OK;
3115 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3116 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3119 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3120 if (bad_path_oldname) {
3121 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3124 /* Quick check for "." and ".." */
3125 if (last_component_oldname[0] == '.') {
3126 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3127 return NT_STATUS_OBJECT_NAME_INVALID;
3131 /* source must already exist. */
3132 if (!VALID_STAT(sbuf1)) {
3133 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3136 if (!check_name(oldname,conn)) {
3137 return NT_STATUS_ACCESS_DENIED;
3140 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3141 if (bad_path_newname) {
3142 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3145 /* Quick check for "." and ".." */
3146 if (last_component_newname[0] == '.') {
3147 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3148 return NT_STATUS_OBJECT_NAME_INVALID;
3152 /* Disallow if newname already exists. */
3153 if (VALID_STAT(sbuf2)) {
3154 return NT_STATUS_OBJECT_NAME_COLLISION;
3157 if (!check_name(newname,conn)) {
3158 return NT_STATUS_ACCESS_DENIED;
3161 /* No links from a directory. */
3162 if (S_ISDIR(sbuf1.st_mode)) {
3163 return NT_STATUS_FILE_IS_A_DIRECTORY;
3166 /* Ensure this is within the share. */
3167 if (!reduce_name(conn, oldname) != 0)
3168 return NT_STATUS_ACCESS_DENIED;
3170 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3172 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3173 status = map_nt_error_from_unix(errno);
3174 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3175 nt_errstr(status), newname, oldname));
3181 /****************************************************************************
3182 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3183 ****************************************************************************/
3185 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3186 char **pparams, int total_params, char **ppdata, int total_data,
3187 unsigned int max_data_bytes)
3189 char *params = *pparams;
3190 char *pdata = *ppdata;
3191 uint16 tran_call = SVAL(inbuf, smb_setup0);
3196 SMB_STRUCT_STAT sbuf;
3199 BOOL bad_path = False;
3200 files_struct *fsp = NULL;
3201 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3202 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3203 mode_t unixmode = 0;
3204 NTSTATUS status = NT_STATUS_OK;
3207 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3211 if (tran_call == TRANSACT2_SETFILEINFO) {
3212 if (total_params < 4)
3213 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3215 fsp = file_fsp(params,0);
3216 info_level = SVAL(params,2);
3218 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3220 * This is actually a SETFILEINFO on a directory
3221 * handle (returned from an NT SMB). NT5.0 seems
3222 * to do this call. JRA.
3224 pstrcpy(fname, fsp->fsp_name);
3225 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3226 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3227 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3229 } else if (fsp && fsp->print_file) {
3231 * Doing a DELETE_ON_CLOSE should cancel a print job.
3233 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3234 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3236 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3239 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3242 return (UNIXERROR(ERRDOS,ERRbadpath));
3245 * Original code - this is an open file.
3247 CHECK_FSP(fsp,conn);
3249 pstrcpy(fname, fsp->fsp_name);
3252 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3253 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3254 return(UNIXERROR(ERRDOS,ERRbadfid));
3259 if (total_params < 6)
3260 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3262 info_level = SVAL(params,0);
3263 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3264 if (!NT_STATUS_IS_OK(status)) {
3265 return ERROR_NT(status);
3267 unix_convert(fname,conn,0,&bad_path,&sbuf);
3269 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3273 * For CIFS UNIX extensions the target name may not exist.
3276 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3277 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3278 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3281 if(!check_name(fname, conn)) {
3282 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3287 if (!CAN_WRITE(conn))
3288 return ERROR_DOS(ERRSRV,ERRaccess);
3290 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3291 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3293 if (VALID_STAT(sbuf))
3294 unixmode = sbuf.st_mode;
3296 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3297 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3299 /* Realloc the parameter and data sizes */
3300 params = Realloc(*pparams,2);
3302 return ERROR_DOS(ERRDOS,ERRnomem);
3307 if (fsp && fsp->pending_modtime) {
3308 /* the pending modtime overrides the current modtime */
3309 sbuf.st_mtime = fsp->pending_modtime;
3312 size = get_file_size(sbuf);
3313 tvs.modtime = sbuf.st_mtime;
3314 tvs.actime = sbuf.st_atime;
3315 dosmode = dos_mode(conn,fname,&sbuf);
3316 unixmode = sbuf.st_mode;
3318 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3319 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3321 switch (info_level) {
3322 case SMB_INFO_STANDARD:
3324 if (total_data < 12)
3325 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3328 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3330 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3334 case SMB_INFO_SET_EA:
3335 status = set_ea(conn, fsp, fname, pdata, total_data);
3336 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3337 return ERROR_NT(status);
3340 /* XXXX um, i don't think this is right.
3341 it's also not in the cifs6.txt spec.
3343 case SMB_INFO_QUERY_EAS_FROM_LIST:
3344 if (total_data < 28)
3345 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3347 tvs.actime = make_unix_date2(pdata+8);
3348 tvs.modtime = make_unix_date2(pdata+12);
3349 size = IVAL(pdata,16);
3350 dosmode = IVAL(pdata,24);
3353 /* XXXX nor this. not in cifs6.txt, either. */
3354 case SMB_INFO_QUERY_ALL_EAS:
3355 if (total_data < 28)
3356 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3358 tvs.actime = make_unix_date2(pdata+8);
3359 tvs.modtime = make_unix_date2(pdata+12);
3360 size = IVAL(pdata,16);
3361 dosmode = IVAL(pdata,24);
3364 case SMB_SET_FILE_BASIC_INFO:
3365 case SMB_FILE_BASIC_INFORMATION:
3367 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3369 time_t changed_time;
3371 if (total_data < 36)
3372 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3374 /* Ignore create time at offset pdata. */
3377 tvs.actime = interpret_long_date(pdata+8);
3379 write_time = interpret_long_date(pdata+16);
3380 changed_time = interpret_long_date(pdata+24);
3382 tvs.modtime = MIN(write_time, changed_time);
3384 if (write_time > tvs.modtime && write_time != 0xffffffff) {
3385 tvs.modtime = write_time;
3387 /* Prefer a defined time to an undefined one. */
3388 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3389 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
3390 ? changed_time : write_time);
3393 dosmode = IVAL(pdata,32);
3397 case SMB_FILE_ALLOCATION_INFORMATION:
3398 case SMB_SET_FILE_ALLOCATION_INFO:
3401 SMB_BIG_UINT allocation_size;
3404 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3406 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3407 #ifdef LARGE_SMB_OFF_T
3408 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3409 #else /* LARGE_SMB_OFF_T */
3410 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3411 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3412 #endif /* LARGE_SMB_OFF_T */
3413 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3414 fname, (double)allocation_size ));
3416 if (allocation_size)
3417 allocation_size = smb_roundup(allocation_size);
3419 if(allocation_size != get_file_size(sbuf)) {
3420 SMB_STRUCT_STAT new_sbuf;
3422 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3423 fname, (double)allocation_size ));
3426 files_struct *new_fsp = NULL;
3427 int access_mode = 0;
3430 if(global_oplock_break) {
3431 /* Queue this file modify as we are the process of an oplock break. */
3433 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3434 DEBUGADD(2,( "in oplock break state.\n"));
3436 push_oplock_pending_smb_message(inbuf, length);
3440 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3441 SET_OPEN_MODE(DOS_OPEN_RDWR),
3442 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3443 FILE_ATTRIBUTE_NORMAL,
3444 INTERNAL_OPEN_ONLY, &access_mode, &action);
3446 if (new_fsp == NULL)
3447 return(UNIXERROR(ERRDOS,ERRbadpath));
3448 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3449 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3450 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3451 new_fsp->fnum, strerror(errno)));
3454 close_file(new_fsp,True);
3456 ret = vfs_allocate_file_space(fsp, allocation_size);
3457 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3458 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3459 fsp->fnum, strerror(errno)));
3464 return ERROR_NT(NT_STATUS_DISK_FULL);
3466 /* Allocate can truncate size... */
3467 size = get_file_size(new_sbuf);
3473 case SMB_FILE_END_OF_FILE_INFORMATION:
3474 case SMB_SET_FILE_END_OF_FILE_INFO:
3477 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3479 size = IVAL(pdata,0);
3480 #ifdef LARGE_SMB_OFF_T
3481 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3482 #else /* LARGE_SMB_OFF_T */
3483 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3484 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3485 #endif /* LARGE_SMB_OFF_T */
3486 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3490 case SMB_FILE_DISPOSITION_INFORMATION:
3491 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3493 BOOL delete_on_close;
3496 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3498 delete_on_close = (CVAL(pdata,0) ? True : False);
3500 /* Just ignore this set on a path. */
3501 if (tran_call != TRANSACT2_SETFILEINFO)
3505 return(UNIXERROR(ERRDOS,ERRbadfid));
3507 status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3509 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3510 return ERROR_NT(status);
3512 /* The set is across all open files on this dev/inode pair. */
3513 status =set_delete_on_close_over_all(fsp, delete_on_close);
3514 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3515 return ERROR_NT(status);
3520 case SMB_FILE_POSITION_INFORMATION:
3522 SMB_BIG_UINT position_information;
3525 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3527 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3528 #ifdef LARGE_SMB_OFF_T
3529 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3530 #else /* LARGE_SMB_OFF_T */
3531 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3532 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3533 #endif /* LARGE_SMB_OFF_T */
3534 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3535 fname, (double)position_information ));
3537 fsp->position_information = position_information;
3542 * CIFS UNIX extensions.
3545 case SMB_SET_FILE_UNIX_BASIC:
3547 uint32 raw_unixmode;
3549 if (total_data < 100)
3550 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3552 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3553 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3554 size=IVAL(pdata,0); /* first 8 Bytes are size */
3555 #ifdef LARGE_SMB_OFF_T
3556 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3557 #else /* LARGE_SMB_OFF_T */
3558 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3559 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3560 #endif /* LARGE_SMB_OFF_T */
3562 pdata+=24; /* ctime & st_blocks are not changed */
3563 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
3564 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
3566 set_owner = (uid_t)IVAL(pdata,0);
3568 set_grp = (gid_t)IVAL(pdata,0);
3570 raw_unixmode = IVAL(pdata,28);
3571 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3572 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3574 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3575 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3576 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3578 if (!VALID_STAT(sbuf)) {
3581 * The only valid use of this is to create character and block
3582 * devices, and named pipes. This is deprecated (IMHO) and
3583 * a new info level should be used for mknod. JRA.
3586 uint32 file_type = IVAL(pdata,0);
3587 #if defined(HAVE_MAKEDEV)
3588 uint32 dev_major = IVAL(pdata,4);
3589 uint32 dev_minor = IVAL(pdata,12);
3592 uid_t myuid = geteuid();
3593 gid_t mygid = getegid();
3594 SMB_DEV_T dev = (SMB_DEV_T)0;
3596 if (tran_call == TRANSACT2_SETFILEINFO)
3597 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3599 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3600 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3602 #if defined(HAVE_MAKEDEV)
3603 dev = makedev(dev_major, dev_minor);
3606 /* We can only create as the owner/group we are. */
3608 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3609 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3610 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3611 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3613 switch (file_type) {
3614 #if defined(S_IFIFO)
3615 case UNIX_TYPE_FIFO:
3616 unixmode |= S_IFIFO;
3619 #if defined(S_IFSOCK)
3620 case UNIX_TYPE_SOCKET:
3621 unixmode |= S_IFSOCK;
3624 #if defined(S_IFCHR)
3625 case UNIX_TYPE_CHARDEV:
3626 unixmode |= S_IFCHR;
3629 #if defined(S_IFBLK)
3630 case UNIX_TYPE_BLKDEV:
3631 unixmode |= S_IFBLK;
3635 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3638 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3639 0%o for file %s\n", (double)dev, unixmode, fname ));
3641 /* Ok - do the mknod. */
3642 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
3643 return(UNIXERROR(ERRDOS,ERRnoaccess));
3645 inherit_access_acl(conn, fname, unixmode);
3648 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3653 * Deal with the UNIX specific mode set.
3656 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3657 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3658 (unsigned int)unixmode, fname ));
3659 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3660 return(UNIXERROR(ERRDOS,ERRnoaccess));
3664 * Deal with the UNIX specific uid set.
3667 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3668 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3669 (unsigned int)set_owner, fname ));
3670 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3671 return(UNIXERROR(ERRDOS,ERRnoaccess));
3675 * Deal with the UNIX specific gid set.
3678 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3679 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3680 (unsigned int)set_owner, fname ));
3681 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3682 return(UNIXERROR(ERRDOS,ERRnoaccess));
3687 case SMB_SET_FILE_UNIX_LINK:
3689 pstring link_target;
3690 char *newname = fname;
3692 /* Set a symbolic link. */
3693 /* Don't allow this if follow links is false. */
3695 if (!lp_symlinks(SNUM(conn)))
3696 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3698 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
3700 /* !widelinks forces the target path to be within the share. */
3701 /* This means we can interpret the target as a pathname. */
3702 if (!lp_widelinks(SNUM(conn))) {
3704 char *last_dirp = NULL;
3706 unix_format(link_target);
3707 if (*link_target == '/') {
3708 /* No absolute paths allowed. */
3709 return(UNIXERROR(ERRDOS,ERRnoaccess));
3711 pstrcpy(rel_name, newname);
3712 last_dirp = strrchr_m(rel_name, '/');
3714 last_dirp[1] = '\0';
3716 pstrcpy(rel_name, "./");
3718 pstrcat(rel_name, link_target);
3720 if (!check_name(rel_name, conn)) {
3721 return(UNIXERROR(ERRDOS,ERRnoaccess));
3725 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3726 fname, link_target ));
3728 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
3729 return(UNIXERROR(ERRDOS,ERRnoaccess));
3731 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3735 case SMB_SET_FILE_UNIX_HLINK:
3738 char *newname = fname;
3740 /* Set a hard link. */
3741 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
3742 if (!NT_STATUS_IS_OK(status)) {
3743 return ERROR_NT(status);
3746 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3749 status = hardlink_internals(conn, oldname, newname);
3750 if (!NT_STATUS_IS_OK(status)) {
3751 return ERROR_NT(status);
3755 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3759 case SMB_FILE_RENAME_INFORMATION:
3768 if (total_data < 12)
3769 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3771 overwrite = (CVAL(pdata,0) ? True : False);
3772 root_fid = IVAL(pdata,4);
3773 len = IVAL(pdata,8);
3774 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
3775 if (!NT_STATUS_IS_OK(status)) {
3776 return ERROR_NT(status);
3779 /* Check the new name has no '/' characters. */
3780 if (strchr_m(newname, '/'))
3781 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3783 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3785 /* Create the base directory. */
3786 pstrcpy(base_name, fname);
3787 p = strrchr_m(base_name, '/');
3790 /* Append the new name. */
3791 pstrcat(base_name, "/");
3792 pstrcat(base_name, newname);
3795 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3796 fsp->fnum, fsp->fsp_name, base_name ));
3797 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
3799 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3801 status = rename_internals(conn, fname, base_name, 0, overwrite);
3803 if (!NT_STATUS_IS_OK(status)) {
3804 return ERROR_NT(status);
3806 process_pending_change_notify_queue((time_t)0);
3808 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3812 case SMB_SET_POSIX_ACL:
3814 uint16 posix_acl_version;
3815 uint16 num_file_acls;
3816 uint16 num_def_acls;
3817 BOOL valid_file_acls = True;
3818 BOOL valid_def_acls = True;
3820 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
3821 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3823 posix_acl_version = SVAL(pdata,0);
3824 num_file_acls = SVAL(pdata,2);
3825 num_def_acls = SVAL(pdata,4);
3827 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3828 valid_file_acls = False;
3832 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3833 valid_def_acls = False;
3837 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
3838 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3841 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
3842 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
3843 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3846 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
3847 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
3848 return(UNIXERROR(ERRDOS,ERRnoaccess));
3851 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
3852 pdata + SMB_POSIX_ACL_HEADER_SIZE +
3853 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
3854 return(UNIXERROR(ERRDOS,ERRnoaccess));
3858 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3863 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3866 /* get some defaults (no modifications) if any info is zero or -1. */
3867 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
3868 tvs.actime = sbuf.st_atime;
3870 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3871 tvs.modtime = sbuf.st_mtime;
3873 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3874 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3875 DEBUG(6,("size: %.0f ", (double)size));
3878 if (S_ISDIR(sbuf.st_mode))
3884 DEBUG(6,("dosmode: %x\n" , dosmode));
3886 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3887 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3888 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3889 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3892 * Only do this test if we are not explicitly
3893 * changing the size of a file.
3896 size = get_file_size(sbuf);
3900 * Try and set the times, size and mode of this file -
3901 * if they are different from the current values
3903 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3906 * This was a setfileinfo on an open file.
3907 * NT does this a lot. It's actually pointless
3908 * setting the time here, as it will be overwritten
3909 * on the next write, so we save the request
3910 * away and will set it on file close. JRA.
3913 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3914 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3915 fsp->pending_modtime = tvs.modtime;
3920 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3922 if(file_utime(conn, fname, &tvs)!=0)
3923 return(UNIXERROR(ERRDOS,ERRnoaccess));
3927 /* check the mode isn't different, before changing it */
3928 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3930 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3932 if(file_set_dosmode(conn, fname, dosmode, NULL)) {
3933 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
3934 return(UNIXERROR(ERRDOS,ERRnoaccess));
3938 if (size != get_file_size(sbuf)) {
3942 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3943 fname, (double)size ));
3946 files_struct *new_fsp = NULL;
3947 int access_mode = 0;
3950 if(global_oplock_break) {
3951 /* Queue this file modify as we are the process of an oplock break. */
3953 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3954 DEBUGADD(2,( "in oplock break state.\n"));
3956 push_oplock_pending_smb_message(inbuf, length);
3960 new_fsp = open_file_shared(conn, fname, &sbuf,
3961 SET_OPEN_MODE(DOS_OPEN_RDWR),
3962 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3963 FILE_ATTRIBUTE_NORMAL,
3964 INTERNAL_OPEN_ONLY, &access_mode, &action);
3966 if (new_fsp == NULL)
3967 return(UNIXERROR(ERRDOS,ERRbadpath));
3968 ret = vfs_set_filelen(new_fsp, size);
3969 close_file(new_fsp,True);
3971 ret = vfs_set_filelen(fsp, size);
3975 return (UNIXERROR(ERRHRD,ERRdiskfull));
3979 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3984 /****************************************************************************
3985 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3986 ****************************************************************************/
3988 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3989 char **pparams, int total_params, char **ppdata, int total_data,
3990 unsigned int max_data_bytes)
3992 char *params = *pparams;
3995 SMB_STRUCT_STAT sbuf;
3996 BOOL bad_path = False;
3997 NTSTATUS status = NT_STATUS_OK;
3999 if (!CAN_WRITE(conn))
4000 return ERROR_DOS(ERRSRV,ERRaccess);
4002 if (total_params < 4)
4003 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4005 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4006 if (!NT_STATUS_IS_OK(status)) {
4007 return ERROR_NT(status);
4010 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4012 unix_convert(directory,conn,0,&bad_path,&sbuf);
4014 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4016 if (check_name(directory,conn))
4017 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
4020 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4021 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4024 /* Realloc the parameter and data sizes */
4025 params = Realloc(*pparams,2);
4027 return ERROR_DOS(ERRDOS,ERRnomem);
4032 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4037 /****************************************************************************
4038 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4039 We don't actually do this - we just send a null response.
4040 ****************************************************************************/
4042 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4043 char **pparams, int total_params, char **ppdata, int total_data,
4044 unsigned int max_data_bytes)
4046 static uint16 fnf_handle = 257;
4047 char *params = *pparams;
4050 if (total_params < 6)
4051 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4053 info_level = SVAL(params,4);
4054 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4056 switch (info_level) {
4061 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4064 /* Realloc the parameter and data sizes */
4065 params = Realloc(*pparams,6);
4067 return ERROR_DOS(ERRDOS,ERRnomem);
4070 SSVAL(params,0,fnf_handle);
4071 SSVAL(params,2,0); /* No changes */
4072 SSVAL(params,4,0); /* No EA errors */
4079 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4084 /****************************************************************************
4085 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4086 changes). Currently this does nothing.
4087 ****************************************************************************/
4089 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4090 char **pparams, int total_params, char **ppdata, int total_data,
4091 unsigned int max_data_bytes)
4093 char *params = *pparams;
4095 DEBUG(3,("call_trans2findnotifynext\n"));
4097 /* Realloc the parameter and data sizes */
4098 params = Realloc(*pparams,4);
4100 return ERROR_DOS(ERRDOS,ERRnomem);
4103 SSVAL(params,0,0); /* No changes */
4104 SSVAL(params,2,0); /* No EA errors */
4106 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4111 /****************************************************************************
4112 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4113 ****************************************************************************/
4115 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4116 char **pparams, int total_params, char **ppdata, int total_data,
4117 unsigned int max_data_bytes)
4119 char *params = *pparams;
4122 int max_referral_level;
4124 DEBUG(10,("call_trans2getdfsreferral\n"));
4126 if (total_params < 2)
4127 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4129 max_referral_level = SVAL(params,0);
4131 if(!lp_host_msdfs())
4132 return ERROR_DOS(ERRDOS,ERRbadfunc);
4134 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4135 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4136 return UNIXERROR(ERRDOS,ERRbadfile);
4138 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4139 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4144 #define LMCAT_SPL 0x53
4145 #define LMFUNC_GETJOBID 0x60
4147 /****************************************************************************
4148 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4149 ****************************************************************************/
4151 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4152 char **pparams, int total_params, char **ppdata, int total_data,
4153 unsigned int max_data_bytes)
4155 char *pdata = *ppdata;
4156 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4158 /* check for an invalid fid before proceeding */
4161 return(ERROR_DOS(ERRDOS,ERRbadfid));
4163 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4164 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4165 pdata = Realloc(*ppdata, 32);
4167 return ERROR_DOS(ERRDOS,ERRnomem);
4170 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4171 CAN ACCEPT THIS IN UNICODE. JRA. */
4173 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4174 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4175 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4176 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4179 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4180 return ERROR_DOS(ERRSRV,ERRerror);
4184 /****************************************************************************
4185 Reply to a SMBfindclose (stop trans2 directory search).
4186 ****************************************************************************/
4188 int reply_findclose(connection_struct *conn,
4189 char *inbuf,char *outbuf,int length,int bufsize)
4192 int dptr_num=SVALS(inbuf,smb_vwv0);
4193 START_PROFILE(SMBfindclose);
4195 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4197 dptr_close(&dptr_num);
4199 outsize = set_message(outbuf,0,0,True);
4201 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4203 END_PROFILE(SMBfindclose);
4207 /****************************************************************************
4208 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4209 ****************************************************************************/
4211 int reply_findnclose(connection_struct *conn,
4212 char *inbuf,char *outbuf,int length,int bufsize)
4216 START_PROFILE(SMBfindnclose);
4218 dptr_num = SVAL(inbuf,smb_vwv0);
4220 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4222 /* We never give out valid handles for a
4223 findnotifyfirst - so any dptr_num is ok here.
4226 outsize = set_message(outbuf,0,0,True);
4228 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4230 END_PROFILE(SMBfindnclose);
4234 /****************************************************************************
4235 Reply to a SMBtranss2 - just ignore it!
4236 ****************************************************************************/
4238 int reply_transs2(connection_struct *conn,
4239 char *inbuf,char *outbuf,int length,int bufsize)
4241 START_PROFILE(SMBtranss2);
4242 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4243 END_PROFILE(SMBtranss2);
4247 /****************************************************************************
4248 Reply to a SMBtrans2.
4249 ****************************************************************************/
4251 int reply_trans2(connection_struct *conn,
4252 char *inbuf,char *outbuf,int length,int bufsize)
4255 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4256 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4257 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4259 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4260 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4261 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4262 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4263 int32 timeout = IVALS(inbuf,smb_timeout);
4265 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4266 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4267 char *params = NULL, *data = NULL;
4268 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4269 START_PROFILE(SMBtrans2);
4271 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4272 /* Queue this open message as we are the process of an
4275 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4276 DEBUGADD(2,( "in oplock break state.\n"));
4278 push_oplock_pending_smb_message(inbuf, length);
4279 END_PROFILE(SMBtrans2);
4283 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4284 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4285 END_PROFILE(SMBtrans2);
4286 return ERROR_DOS(ERRSRV,ERRaccess);
4289 outsize = set_message(outbuf,0,0,True);
4291 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4292 is so as a sanity check */
4295 * Need to have rc=0 for ioctl to get job id for OS/2.
4296 * Network printing will fail if function is not successful.
4297 * Similar function in reply.c will be used if protocol
4298 * is LANMAN1.0 instead of LM1.2X002.
4299 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4300 * outbuf doesn't have to be set(only job id is used).
4302 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4303 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4304 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4305 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4307 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4308 DEBUG(2,("Transaction is %d\n",tran_call));
4309 END_PROFILE(SMBtrans2);
4310 ERROR_DOS(ERRDOS,ERRinvalidparam);
4314 /* Allocate the space for the maximum needed parameters and data */
4315 if (total_params > 0)
4316 params = (char *)malloc(total_params);
4318 data = (char *)malloc(total_data);
4320 if ((total_params && !params) || (total_data && !data)) {
4321 DEBUG(2,("Out of memory in reply_trans2\n"));
4324 END_PROFILE(SMBtrans2);
4325 return ERROR_DOS(ERRDOS,ERRnomem);
4328 /* Copy the param and data bytes sent with this request into
4329 the params buffer */
4330 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4331 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4333 if (num_params > total_params || num_data > total_data)
4334 exit_server("invalid params in reply_trans2");
4337 unsigned int psoff = SVAL(inbuf, smb_psoff);
4338 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4340 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4341 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4343 memcpy( params, smb_base(inbuf) + psoff, num_params);
4346 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4347 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4349 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4350 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4352 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4355 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4357 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4358 /* We need to send an interim response then receive the rest
4359 of the parameter/data bytes */
4360 outsize = set_message(outbuf,0,0,True);
4361 srv_signing_trans_stop();
4362 if (!send_smb(smbd_server_fd(),outbuf))
4363 exit_server("reply_trans2: send_smb failed.");
4365 while (num_data_sofar < total_data ||
4366 num_params_sofar < total_params) {
4368 unsigned int param_disp;
4369 unsigned int param_off;
4370 unsigned int data_disp;
4371 unsigned int data_off;
4373 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4376 * The sequence number for the trans reply is always
4377 * based on the last secondary received.
4380 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4383 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4384 outsize = set_message(outbuf,0,0,True);
4386 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4388 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4389 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4393 /* Revise total_params and total_data in case
4394 they have changed downwards */
4395 if (SVAL(inbuf, smb_tpscnt) < total_params)
4396 total_params = SVAL(inbuf, smb_tpscnt);
4397 if (SVAL(inbuf, smb_tdscnt) < total_data)
4398 total_data = SVAL(inbuf, smb_tdscnt);
4400 num_params = SVAL(inbuf,smb_spscnt);
4401 param_off = SVAL(inbuf, smb_spsoff);
4402 param_disp = SVAL(inbuf, smb_spsdisp);
4403 num_params_sofar += num_params;
4405 num_data = SVAL(inbuf, smb_sdscnt);
4406 data_off = SVAL(inbuf, smb_sdsoff);
4407 data_disp = SVAL(inbuf, smb_sdsdisp);
4408 num_data_sofar += num_data;
4410 if (num_params_sofar > total_params || num_data_sofar > total_data)
4414 if (param_disp + num_params > total_params)
4416 if ((param_disp + num_params < param_disp) ||
4417 (param_disp + num_params < num_params))
4419 if (param_disp > total_params)
4421 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4422 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4424 if (params + param_disp < params)
4427 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
4430 if (data_disp + num_data > total_data)
4432 if ((data_disp + num_data < data_disp) ||
4433 (data_disp + num_data < num_data))
4435 if (data_disp > total_data)
4437 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4438 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4440 if (data + data_disp < data)
4443 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4448 if (Protocol >= PROTOCOL_NT1) {
4449 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4452 /* Now we must call the relevant TRANS2 function */
4454 case TRANSACT2_OPEN:
4455 START_PROFILE_NESTED(Trans2_open);
4456 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4457 ¶ms, total_params, &data, total_data, max_data_bytes);
4458 END_PROFILE_NESTED(Trans2_open);
4461 case TRANSACT2_FINDFIRST:
4462 START_PROFILE_NESTED(Trans2_findfirst);
4463 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4464 ¶ms, total_params, &data, total_data, max_data_bytes);
4465 END_PROFILE_NESTED(Trans2_findfirst);
4468 case TRANSACT2_FINDNEXT:
4469 START_PROFILE_NESTED(Trans2_findnext);
4470 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4471 ¶ms, total_params, &data, total_data, max_data_bytes);
4472 END_PROFILE_NESTED(Trans2_findnext);
4475 case TRANSACT2_QFSINFO:
4476 START_PROFILE_NESTED(Trans2_qfsinfo);
4477 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4478 ¶ms, total_params, &data, total_data, max_data_bytes);
4479 END_PROFILE_NESTED(Trans2_qfsinfo);
4482 #ifdef HAVE_SYS_QUOTAS
4483 case TRANSACT2_SETFSINFO:
4484 START_PROFILE_NESTED(Trans2_setfsinfo);
4485 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4486 ¶ms, total_params, &data, total_data, max_data_bytes);
4487 END_PROFILE_NESTED(Trans2_setfsinfo);
4490 case TRANSACT2_QPATHINFO:
4491 case TRANSACT2_QFILEINFO:
4492 START_PROFILE_NESTED(Trans2_qpathinfo);
4493 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4494 ¶ms, total_params, &data, total_data, max_data_bytes);
4495 END_PROFILE_NESTED(Trans2_qpathinfo);
4497 case TRANSACT2_SETPATHINFO:
4498 case TRANSACT2_SETFILEINFO:
4499 START_PROFILE_NESTED(Trans2_setpathinfo);
4500 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4501 ¶ms, total_params, &data, total_data, max_data_bytes);
4502 END_PROFILE_NESTED(Trans2_setpathinfo);
4505 case TRANSACT2_FINDNOTIFYFIRST:
4506 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4507 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4508 ¶ms, total_params, &data, total_data, max_data_bytes);
4509 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4512 case TRANSACT2_FINDNOTIFYNEXT:
4513 START_PROFILE_NESTED(Trans2_findnotifynext);
4514 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4515 ¶ms, total_params, &data, total_data, max_data_bytes);
4516 END_PROFILE_NESTED(Trans2_findnotifynext);
4518 case TRANSACT2_MKDIR:
4519 START_PROFILE_NESTED(Trans2_mkdir);
4520 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4521 ¶ms, total_params, &data, total_data, max_data_bytes);
4522 END_PROFILE_NESTED(Trans2_mkdir);
4525 case TRANSACT2_GET_DFS_REFERRAL:
4526 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4527 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4528 ¶ms, total_params, &data, total_data, max_data_bytes);
4529 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4531 case TRANSACT2_IOCTL:
4532 START_PROFILE_NESTED(Trans2_ioctl);
4533 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4534 ¶ms, total_params, &data, total_data, max_data_bytes);
4535 END_PROFILE_NESTED(Trans2_ioctl);
4538 /* Error in request */
4539 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4542 END_PROFILE(SMBtrans2);
4543 srv_signing_trans_stop();
4544 return ERROR_DOS(ERRSRV,ERRerror);
4547 /* As we do not know how many data packets will need to be
4548 returned here the various call_trans2xxxx calls
4549 must send their own. Thus a call_trans2xxx routine only
4550 returns a value other than -1 when it wants to send
4554 srv_signing_trans_stop();
4558 END_PROFILE(SMBtrans2);
4559 return outsize; /* If a correct response was needed the
4560 call_trans2xxx calls have already sent
4561 it. If outsize != -1 then it is returning */
4565 srv_signing_trans_stop();
4568 END_PROFILE(SMBtrans2);
4569 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);