2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2003
5 Copyright (C) Stefan (metze) Metzmacher 2003
7 Extensively modified by Andrew Tridgell, 1995
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 extern enum protocol_types Protocol;
27 extern int smb_read_error;
28 extern int global_oplock_break;
29 extern uint32 global_client_caps;
30 extern struct current_user current_user;
32 #define get_file_size(sbuf) ((sbuf).st_size)
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 /********************************************************************
36 Roundup a value to the nearest SMB_ROUNDUP_ALLOCATION_SIZE boundary.
37 Only do this for Windows clients.
38 ********************************************************************/
40 SMB_BIG_UINT smb_roundup(SMB_BIG_UINT val)
42 /* Only roundup for Windows clients. */
43 enum remote_arch_types ra_type = get_remote_arch();
44 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
45 val = SMB_ROUNDUP(val,SMB_ROUNDUP_ALLOCATION_SIZE);
50 /********************************************************************
51 Given a stat buffer return the allocated size on disk, taking into
53 ********************************************************************/
55 SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
59 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
60 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
62 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
65 if (!ret && fsp && fsp->initial_allocation_size)
66 ret = fsp->initial_allocation_size;
68 ret = smb_roundup(ret);
73 /****************************************************************************
74 Utility functions for dealing with extended attributes.
75 ****************************************************************************/
77 static const char *prohibited_ea_names[] = {
78 SAMBA_POSIX_INHERITANCE_EA_NAME,
79 SAMBA_XATTR_DOS_ATTRIB,
83 /****************************************************************************
84 Refuse to allow clients to overwrite our private xattrs.
85 ****************************************************************************/
87 static BOOL samba_private_attr_name(const char *unix_ea_name)
91 for (i = 0; prohibited_ea_names[i]; i++) {
92 if (strequal( prohibited_ea_names[i], unix_ea_name))
99 struct ea_list *next, *prev;
103 /****************************************************************************
104 Get one EA value. Fill in a struct ea_struct.
105 ****************************************************************************/
107 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
108 const char *fname, char *ea_name, struct ea_struct *pea)
110 /* Get the value of this xattr. Max size is 64k. */
111 size_t attr_size = 256;
117 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
122 if (fsp && fsp->fd != -1) {
123 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
125 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
128 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
137 DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
138 dump_data(10, val, sizeret);
141 if (strnequal(ea_name, "user.", 5)) {
142 pea->name = &ea_name[5];
146 pea->value.data = val;
147 pea->value.length = (size_t)sizeret;
151 /****************************************************************************
152 Return a linked list of the total EA's. Plus the total size
153 ****************************************************************************/
155 static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, const char *fname, size_t *pea_total_len)
157 /* Get a list of all xattrs. Max namesize is 64k. */
158 size_t ea_namelist_size = 1024;
163 struct ea_list *ea_list_head = NULL;
167 if (!lp_ea_support(SNUM(conn))) {
171 for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
172 ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
173 if (fsp && fsp->fd != -1) {
174 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
176 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
179 if (sizeret == -1 && errno == ERANGE) {
180 ea_namelist_size *= 2;
189 DEBUG(10,("get_ea_list: ea_namelist size = %d\n", sizeret ));
192 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
193 struct ea_list *listp, *tmp;
195 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
198 listp = TALLOC_P(mem_ctx, struct ea_list);
202 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
208 push_ascii_fstring(dos_ea_name, listp->ea.name);
209 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
210 DEBUG(10,("get_ea_list: total_len = %u, %s, val len = %u\n",
211 *pea_total_len, dos_ea_name,
212 (unsigned int)listp->ea.value.length ));
214 DLIST_ADD_END(ea_list_head, listp, tmp);
216 /* Add on 4 for total length. */
217 if (*pea_total_len) {
222 DEBUG(10,("get_ea_list: total_len = %u\n", *pea_total_len));
226 /****************************************************************************
227 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
229 ****************************************************************************/
231 static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size,
232 connection_struct *conn, files_struct *fsp, const char *fname)
234 unsigned int ret_data_size = 4;
238 struct ea_list *ea_list;
240 SMB_ASSERT(total_data_size >= 4);
243 if (!lp_ea_support(SNUM(conn))) {
246 mem_ctx = talloc_init("fill_ea_buffer");
251 ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
253 talloc_destroy(mem_ctx);
257 if (total_ea_len > total_data_size) {
258 talloc_destroy(mem_ctx);
262 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
265 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
266 dos_namelen = strlen(dos_ea_name);
267 if (dos_namelen > 255 || dos_namelen == 0) {
270 if (ea_list->ea.value.length > 65535) {
273 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
277 /* We know we have room. */
278 SCVAL(p,0,ea_list->ea.flags);
279 SCVAL(p,1,dos_namelen);
280 SSVAL(p,2,ea_list->ea.value.length);
281 fstrcpy(p+4, dos_ea_name);
282 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
284 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
285 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
288 ret_data_size = PTR_DIFF(p, pdata);
289 DEBUG(10,("fill_ea_buffer: data_size = %u, total_ea_len = %u\n",
290 ret_data_size, total_ea_len ));
291 talloc_destroy(mem_ctx);
292 SIVAL(pdata,0,ret_data_size);
293 return ret_data_size;
296 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
298 size_t total_ea_len = 0;
299 TALLOC_CTX *mem_ctx = NULL;
301 if (!lp_ea_support(SNUM(conn))) {
304 mem_ctx = talloc_init("estimate_ea_size");
305 (void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
306 talloc_destroy(mem_ctx);
310 /****************************************************************************
311 Ensure the EA name is case insensitive by matching any existing EA name.
312 ****************************************************************************/
314 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
317 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
318 struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
320 for (; ea_list; ea_list = ea_list->next) {
321 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
322 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
323 &unix_ea_name[5], ea_list->ea.name));
324 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
328 talloc_destroy(mem_ctx);
331 /****************************************************************************
332 Set or delete an extended attribute.
333 ****************************************************************************/
335 static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname,
336 char *pdata, int total_data)
338 unsigned int namelen;
341 fstring unix_ea_name;
343 if (!lp_ea_support(SNUM(conn))) {
344 return NT_STATUS_EAS_NOT_SUPPORTED;
347 if (total_data < 8) {
348 return NT_STATUS_INVALID_PARAMETER;
351 if (IVAL(pdata,0) > total_data) {
352 DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data));
353 return NT_STATUS_INVALID_PARAMETER;
357 namelen = CVAL(pdata,1);
358 ealen = SVAL(pdata,2);
360 if (total_data < 8 + namelen + 1 + ealen) {
361 DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n",
362 (unsigned int)total_data, namelen, ealen));
363 return NT_STATUS_INVALID_PARAMETER;
366 if (pdata[namelen] != '\0') {
367 DEBUG(10,("set_ea: ea name not null terminated\n"));
368 return NT_STATUS_INVALID_PARAMETER;
371 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
372 pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE);
373 pdata += (namelen + 1);
375 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
377 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen));
379 DEBUG(10,("set_ea: data :\n"));
380 dump_data(10, pdata, ealen);
383 if (samba_private_attr_name(unix_ea_name)) {
384 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
385 return NT_STATUS_ACCESS_DENIED;
389 /* Remove the attribute. */
390 if (fsp && (fsp->fd != -1)) {
391 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
392 unix_ea_name, fsp->fsp_name));
393 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
395 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
396 unix_ea_name, fname));
397 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
400 /* Removing a non existent attribute always succeeds. */
401 if (ret == -1 && errno == ENOATTR) {
402 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name));
407 if (fsp && (fsp->fd != -1)) {
408 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
409 unix_ea_name, fsp->fsp_name));
410 ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0);
412 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
413 unix_ea_name, fname));
414 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0);
420 if (errno == ENOTSUP) {
421 return NT_STATUS_EAS_NOT_SUPPORTED;
424 return map_nt_error_from_unix(errno);
430 /****************************************************************************
431 Send the required number of replies back.
432 We assume all fields other than the data fields are
433 set correctly for the type of call.
434 HACK ! Always assumes smb_setup field is zero.
435 ****************************************************************************/
437 static int send_trans2_replies(char *outbuf,
444 /* As we are using a protocol > LANMAN1 then the max_send
445 variable must have been set in the sessetupX call.
446 This takes precedence over the max_xmit field in the
447 global struct. These different max_xmit variables should
448 be merged as this is now too confusing */
451 int data_to_send = datasize;
452 int params_to_send = paramsize;
456 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
457 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
458 int data_alignment_offset = 0;
460 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
462 set_message(outbuf,10,0,True);
464 /* If there genuinely are no parameters or data to send just send the empty packet */
466 if(params_to_send == 0 && data_to_send == 0) {
467 if (!send_smb(smbd_server_fd(),outbuf))
468 exit_server("send_trans2_replies: send_smb failed.");
472 /* When sending params and data ensure that both are nicely aligned */
473 /* Only do this alignment when there is also data to send - else
474 can cause NT redirector problems. */
476 if (((params_to_send % 4) != 0) && (data_to_send != 0))
477 data_alignment_offset = 4 - (params_to_send % 4);
479 /* Space is bufsize minus Netbios over TCP header minus SMB header */
480 /* The alignment_offset is to align the param bytes on an even byte
481 boundary. NT 4.0 Beta needs this to work correctly. */
483 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
485 /* useable_space can never be more than max_send minus the alignment offset. */
487 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
489 while (params_to_send || data_to_send) {
490 /* Calculate whether we will totally or partially fill this packet */
492 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
494 /* We can never send more than useable_space */
496 * Note that 'useable_space' does not include the alignment offsets,
497 * but we must include the alignment offsets in the calculation of
498 * the length of the data we send over the wire, as the alignment offsets
499 * are sent here. Fix from Marc_Jacobsen@hp.com.
502 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
504 set_message(outbuf, 10, total_sent_thistime, True);
506 /* Set total params and data to be sent */
507 SSVAL(outbuf,smb_tprcnt,paramsize);
508 SSVAL(outbuf,smb_tdrcnt,datasize);
510 /* Calculate how many parameters and data we can fit into
511 * this packet. Parameters get precedence
514 params_sent_thistime = MIN(params_to_send,useable_space);
515 data_sent_thistime = useable_space - params_sent_thistime;
516 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
518 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
520 /* smb_proff is the offset from the start of the SMB header to the
521 parameter bytes, however the first 4 bytes of outbuf are
522 the Netbios over TCP header. Thus use smb_base() to subtract
523 them from the calculation */
525 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
527 if(params_sent_thistime == 0)
528 SSVAL(outbuf,smb_prdisp,0);
530 /* Absolute displacement of param bytes sent in this packet */
531 SSVAL(outbuf,smb_prdisp,pp - params);
533 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
534 if(data_sent_thistime == 0) {
535 SSVAL(outbuf,smb_droff,0);
536 SSVAL(outbuf,smb_drdisp, 0);
538 /* The offset of the data bytes is the offset of the
539 parameter bytes plus the number of parameters being sent this time */
540 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
541 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
542 SSVAL(outbuf,smb_drdisp, pd - pdata);
545 /* Copy the param bytes into the packet */
547 if(params_sent_thistime)
548 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
550 /* Copy in the data bytes */
551 if(data_sent_thistime)
552 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
553 data_alignment_offset,pd,data_sent_thistime);
555 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
556 params_sent_thistime, data_sent_thistime, useable_space));
557 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
558 params_to_send, data_to_send, paramsize, datasize));
560 /* Send the packet */
561 if (!send_smb(smbd_server_fd(),outbuf))
562 exit_server("send_trans2_replies: send_smb failed.");
564 pp += params_sent_thistime;
565 pd += data_sent_thistime;
567 params_to_send -= params_sent_thistime;
568 data_to_send -= data_sent_thistime;
571 if(params_to_send < 0 || data_to_send < 0) {
572 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
573 params_to_send, data_to_send));
581 /****************************************************************************
582 Reply to a TRANSACT2_OPEN.
583 ****************************************************************************/
585 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
586 char **pparams, int total_params, char **ppdata, int total_data,
587 unsigned int max_data_bytes)
589 char *params = *pparams;
594 BOOL return_additional_info;
603 int fmode=0,mtime=0,rmode;
605 SMB_STRUCT_STAT sbuf;
607 BOOL bad_path = False;
612 * Ensure we have enough parameters to perform the operation.
615 if (total_params < 29)
616 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
618 open_mode = SVAL(params, 2);
619 open_attr = SVAL(params,6);
620 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
622 return_additional_info = BITSETW(params,0);
623 open_sattr = SVAL(params, 4);
624 open_time = make_unix_date3(params+8);
626 open_ofun = SVAL(params,12);
627 open_size = IVAL(params,14);
631 return(ERROR_DOS(ERRSRV,ERRaccess));
633 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
634 if (!NT_STATUS_IS_OK(status)) {
635 return ERROR_NT(status);
638 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
639 fname,open_mode, open_attr, open_ofun, open_size));
641 /* XXXX we need to handle passed times, sattr and flags */
643 unix_convert(fname,conn,0,&bad_path,&sbuf);
645 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
648 if (!check_name(fname,conn)) {
649 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
652 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
653 oplock_request, &rmode,&smb_action);
656 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
657 /* We have re-scheduled this call. */
658 clear_cached_errors();
661 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
664 size = get_file_size(sbuf);
665 fmode = dos_mode(conn,fname,&sbuf);
666 mtime = sbuf.st_mtime;
669 close_file(fsp,False);
670 return(ERROR_DOS(ERRDOS,ERRnoaccess));
673 /* Realloc the size of parameters and data we will return */
674 params = SMB_REALLOC(*pparams, 28);
676 return(ERROR_DOS(ERRDOS,ERRnomem));
679 memset((char *)params,'\0',28);
680 SSVAL(params,0,fsp->fnum);
681 SSVAL(params,2,fmode);
682 put_dos_date2(params,4, mtime);
683 SIVAL(params,8, (uint32)size);
684 SSVAL(params,12,rmode);
686 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
687 smb_action |= EXTENDED_OPLOCK_GRANTED;
689 SSVAL(params,18,smb_action);
692 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
694 SIVAL(params,20,inode);
696 /* Send the required number of replies */
697 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
702 /*********************************************************
703 Routine to check if a given string matches exactly.
704 as a special case a mask of "." does NOT match. That
705 is required for correct wildcard semantics
706 Case can be significant or not.
707 **********************************************************/
709 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
711 if (mask[0] == '.' && mask[1] == 0)
714 return strcmp(str,mask)==0;
715 if (StrCaseCmp(str,mask) != 0) {
718 if (ms_has_wild(str)) {
724 /****************************************************************************
725 Return the filetype for UNIX extensions.
726 ****************************************************************************/
728 static uint32 unix_filetype(mode_t mode)
731 return UNIX_TYPE_FILE;
732 else if(S_ISDIR(mode))
733 return UNIX_TYPE_DIR;
735 else if(S_ISLNK(mode))
736 return UNIX_TYPE_SYMLINK;
739 else if(S_ISCHR(mode))
740 return UNIX_TYPE_CHARDEV;
743 else if(S_ISBLK(mode))
744 return UNIX_TYPE_BLKDEV;
747 else if(S_ISFIFO(mode))
748 return UNIX_TYPE_FIFO;
751 else if(S_ISSOCK(mode))
752 return UNIX_TYPE_SOCKET;
755 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
756 return UNIX_TYPE_UNKNOWN;
759 /****************************************************************************
760 Map wire perms onto standard UNIX permissions. Obey share restrictions.
761 ****************************************************************************/
763 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
767 if (perms == SMB_MODE_NO_CHANGE)
770 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
771 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
772 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
773 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
774 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
775 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
776 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
777 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
778 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
780 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
783 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
786 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
789 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
790 ret &= lp_dir_mask(SNUM(conn));
791 /* Add in force bits */
792 ret |= lp_force_dir_mode(SNUM(conn));
794 /* Apply mode mask */
795 ret &= lp_create_mask(SNUM(conn));
796 /* Add in force bits */
797 ret |= lp_force_create_mode(SNUM(conn));
803 /****************************************************************************
804 Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
805 ****************************************************************************/
807 time_t interpret_long_unix_date(char *p)
809 DEBUG(10,("interpret_long_unix_date\n"));
810 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
811 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
814 return interpret_long_date(p);
818 /****************************************************************************
819 Get a level dependent lanman2 dir entry.
820 ****************************************************************************/
822 static BOOL get_lanman2_dir_entry(connection_struct *conn,
823 void *inbuf, void *outbuf,
824 char *path_mask,int dirtype,int info_level,
825 int requires_resume_key,
826 BOOL dont_descend,char **ppdata,
827 char *base_data, int space_remaining,
828 BOOL *out_of_space, BOOL *got_exact_match,
833 SMB_STRUCT_STAT sbuf;
837 char *p, *q, *pdata = *ppdata;
841 SMB_OFF_T file_size = 0;
842 SMB_BIG_UINT allocation_size = 0;
844 time_t mdate=0, adate=0, cdate=0;
847 int nt_extmode; /* Used for NT connections instead of mode */
848 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
851 *out_of_space = False;
852 *got_exact_match = False;
857 p = strrchr_m(path_mask,'/');
864 pstrcpy(mask, path_mask);
869 /* Needed if we run out of space */
870 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
871 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
874 * Due to bugs in NT client redirectors we are not using
875 * resume keys any more - set them to zero.
876 * Check out the related comments in findfirst/findnext.
882 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
883 (long)conn->dirptr,curr_dirpos));
888 pstrcpy(fname,dname);
890 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
891 got_match = mask_match(fname, mask, conn->case_sensitive);
893 if(!got_match && !mangle_is_8_3(fname, False)) {
896 * It turns out that NT matches wildcards against
897 * both long *and* short names. This may explain some
898 * of the wildcard wierdness from old DOS clients
899 * that some people have been seeing.... JRA.
903 pstrcpy( newname, fname);
904 mangle_map( newname, True, False, SNUM(conn));
905 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
906 got_match = mask_match(newname, mask, conn->case_sensitive);
910 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
911 if (dont_descend && !isdots)
914 pstrcpy(pathreal,conn->dirpath);
916 pstrcat(pathreal,"/");
917 pstrcat(pathreal,dname);
919 if (INFO_LEVEL_IS_UNIX(info_level)) {
920 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
921 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
922 pathreal,strerror(errno)));
925 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
927 /* Needed to show the msdfs symlinks as
930 if(lp_host_msdfs() &&
931 lp_msdfs_root(SNUM(conn)) &&
932 is_msdfs_link(conn, pathreal, NULL, NULL,
935 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
936 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
940 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
941 pathreal,strerror(errno)));
946 mode = dos_mode(conn,pathreal,&sbuf);
948 if (!dir_check_ftype(conn,mode,dirtype)) {
949 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
953 file_size = get_file_size(sbuf);
954 allocation_size = get_allocation_size(NULL,&sbuf);
955 mdate = sbuf.st_mtime;
956 adate = sbuf.st_atime;
957 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
959 if (lp_dos_filetime_resolution(SNUM(conn))) {
966 /* This is necessary, as otherwise the
967 * desktop.ini file in this folder is
969 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
973 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
979 mangle_map(fname,False,True,SNUM(conn));
984 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
986 switch (info_level) {
987 case SMB_INFO_STANDARD:
988 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_STANDARD\n"));
989 if(requires_resume_key) {
993 put_dos_date2(p,l1_fdateCreation,cdate);
994 put_dos_date2(p,l1_fdateLastAccess,adate);
995 put_dos_date2(p,l1_fdateLastWrite,mdate);
996 SIVAL(p,l1_cbFile,(uint32)file_size);
997 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
998 SSVAL(p,l1_attrFile,mode);
1001 p += align_string(outbuf, p, 0);
1002 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1003 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1005 SCVAL(nameptr, -1, len - 2);
1007 SCVAL(nameptr, -1, 0);
1011 SCVAL(nameptr, -1, len - 1);
1013 SCVAL(nameptr, -1, 0);
1019 case SMB_INFO_QUERY_EA_SIZE:
1020 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_QUERY_EA_SIZE\n"));
1021 if(requires_resume_key) {
1025 put_dos_date2(p,l2_fdateCreation,cdate);
1026 put_dos_date2(p,l2_fdateLastAccess,adate);
1027 put_dos_date2(p,l2_fdateLastWrite,mdate);
1028 SIVAL(p,l2_cbFile,(uint32)file_size);
1029 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1030 SSVAL(p,l2_attrFile,mode);
1032 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1033 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1037 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1038 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1051 SCVAL(nameptr,0,len);
1053 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1056 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1057 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1058 was_8_3 = mangle_is_8_3(fname, True);
1060 SIVAL(p,0,reskey); p += 4;
1061 put_long_date(p,cdate); p += 8;
1062 put_long_date(p,adate); p += 8;
1063 put_long_date(p,mdate); p += 8;
1064 put_long_date(p,mdate); p += 8;
1065 SOFF_T(p,0,file_size); p += 8;
1066 SOFF_T(p,0,allocation_size); p += 8;
1067 SIVAL(p,0,nt_extmode); p += 4;
1068 q = p; p += 4; /* q is placeholder for name length. */
1070 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1071 SIVAL(p,0,ea_size); /* Extended attributes */
1074 /* Clear the short name buffer. This is
1075 * IMPORTANT as not doing so will trigger
1076 * a Win2k client bug. JRA.
1079 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1080 pstring mangled_name;
1081 pstrcpy(mangled_name, fname);
1082 mangle_map(mangled_name,True,True,SNUM(conn));
1083 mangled_name[12] = 0;
1084 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1091 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1094 len = PTR_DIFF(p, pdata);
1095 len = (len + 3) & ~3;
1100 case SMB_FIND_FILE_DIRECTORY_INFO:
1101 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1103 SIVAL(p,0,reskey); p += 4;
1104 put_long_date(p,cdate); p += 8;
1105 put_long_date(p,adate); p += 8;
1106 put_long_date(p,mdate); p += 8;
1107 put_long_date(p,mdate); p += 8;
1108 SOFF_T(p,0,file_size); p += 8;
1109 SOFF_T(p,0,allocation_size); p += 8;
1110 SIVAL(p,0,nt_extmode); p += 4;
1111 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1114 len = PTR_DIFF(p, pdata);
1115 len = (len + 3) & ~3;
1120 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1121 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1123 SIVAL(p,0,reskey); p += 4;
1124 put_long_date(p,cdate); p += 8;
1125 put_long_date(p,adate); p += 8;
1126 put_long_date(p,mdate); p += 8;
1127 put_long_date(p,mdate); p += 8;
1128 SOFF_T(p,0,file_size); p += 8;
1129 SOFF_T(p,0,allocation_size); p += 8;
1130 SIVAL(p,0,nt_extmode); p += 4;
1131 q = p; p += 4; /* q is placeholder for name length. */
1133 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1134 SIVAL(p,0,ea_size); /* Extended attributes */
1137 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1141 len = PTR_DIFF(p, pdata);
1142 len = (len + 3) & ~3;
1147 case SMB_FIND_FILE_NAMES_INFO:
1148 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1150 SIVAL(p,0,reskey); p += 4;
1152 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1153 acl on a dir (tridge) */
1154 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1157 len = PTR_DIFF(p, pdata);
1158 len = (len + 3) & ~3;
1163 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1164 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1166 SIVAL(p,0,reskey); p += 4;
1167 put_long_date(p,cdate); p += 8;
1168 put_long_date(p,adate); p += 8;
1169 put_long_date(p,mdate); p += 8;
1170 put_long_date(p,mdate); p += 8;
1171 SOFF_T(p,0,file_size); p += 8;
1172 SOFF_T(p,0,allocation_size); p += 8;
1173 SIVAL(p,0,nt_extmode); p += 4;
1174 q = p; p += 4; /* q is placeholder for name length. */
1176 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1177 SIVAL(p,0,ea_size); /* Extended attributes */
1180 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1181 SIVAL(p,0,sbuf.st_dev); p += 4;
1182 SIVAL(p,0,sbuf.st_ino); p += 4;
1183 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1186 len = PTR_DIFF(p, pdata);
1187 len = (len + 3) & ~3;
1192 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1193 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1194 was_8_3 = mangle_is_8_3(fname, True);
1196 SIVAL(p,0,reskey); p += 4;
1197 put_long_date(p,cdate); p += 8;
1198 put_long_date(p,adate); p += 8;
1199 put_long_date(p,mdate); p += 8;
1200 put_long_date(p,mdate); p += 8;
1201 SOFF_T(p,0,file_size); p += 8;
1202 SOFF_T(p,0,allocation_size); p += 8;
1203 SIVAL(p,0,nt_extmode); p += 4;
1204 q = p; p += 4; /* q is placeholder for name length */
1206 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1207 SIVAL(p,0,ea_size); /* Extended attributes */
1210 /* Clear the short name buffer. This is
1211 * IMPORTANT as not doing so will trigger
1212 * a Win2k client bug. JRA.
1215 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1216 pstring mangled_name;
1217 pstrcpy(mangled_name, fname);
1218 mangle_map(mangled_name,True,True,SNUM(conn));
1219 mangled_name[12] = 0;
1220 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1227 SSVAL(p,0,0); p += 2; /* Reserved ? */
1228 SIVAL(p,0,sbuf.st_dev); p += 4;
1229 SIVAL(p,0,sbuf.st_ino); p += 4;
1230 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1233 len = PTR_DIFF(p, pdata);
1234 len = (len + 3) & ~3;
1239 /* CIFS UNIX Extension. */
1241 case SMB_FIND_FILE_UNIX:
1242 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1244 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1246 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1247 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1250 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1253 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1254 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1255 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1258 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1262 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1266 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1269 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1273 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1277 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1280 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1284 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1288 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1291 len = PTR_DIFF(p, pdata);
1292 len = (len + 3) & ~3;
1293 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1295 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1304 if (PTR_DIFF(p,pdata) > space_remaining) {
1305 /* Move the dirptr back to prev_dirpos */
1306 dptr_SeekDir(conn->dirptr, prev_dirpos);
1307 *out_of_space = True;
1308 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1309 return False; /* Not finished - just out of space */
1312 /* Setup the last_filename pointer, as an offset from base_data */
1313 *last_name_off = PTR_DIFF(nameptr,base_data);
1314 /* Advance the data pointer to the next slot */
1320 /****************************************************************************
1321 Reply to a TRANS2_FINDFIRST.
1322 ****************************************************************************/
1324 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1325 char **pparams, int total_params, char **ppdata, int total_data,
1326 unsigned int max_data_bytes)
1328 /* We must be careful here that we don't return more than the
1329 allowed number of data bytes. If this means returning fewer than
1330 maxentries then so be it. We assume that the redirector has
1331 enough room for the fixed number of parameter bytes it has
1333 char *params = *pparams;
1334 char *pdata = *ppdata;
1335 int dirtype = SVAL(params,0);
1336 int maxentries = SVAL(params,2);
1337 uint16 findfirst_flags = SVAL(params,4);
1338 BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1339 BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1340 BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1341 int info_level = SVAL(params,6);
1345 int last_name_off=0;
1349 BOOL finished = False;
1350 BOOL dont_descend = False;
1351 BOOL out_of_space = False;
1352 int space_remaining;
1353 BOOL bad_path = False;
1354 SMB_STRUCT_STAT sbuf;
1355 NTSTATUS ntstatus = NT_STATUS_OK;
1357 if (total_params < 12)
1358 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1360 *directory = *mask = 0;
1362 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1363 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1364 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1365 info_level, max_data_bytes));
1368 /* W2K3 seems to treat zero as 1. */
1372 switch (info_level) {
1373 case SMB_INFO_STANDARD:
1374 case SMB_INFO_QUERY_EA_SIZE:
1375 case SMB_FIND_FILE_DIRECTORY_INFO:
1376 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1377 case SMB_FIND_FILE_NAMES_INFO:
1378 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1379 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1380 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1382 case SMB_FIND_FILE_UNIX:
1383 if (!lp_unix_extensions())
1384 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1387 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1390 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1391 if (!NT_STATUS_IS_OK(ntstatus)) {
1392 return ERROR_NT(ntstatus);
1395 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
1397 unix_convert(directory,conn,0,&bad_path,&sbuf);
1399 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1401 if(!check_name(directory,conn)) {
1402 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1405 p = strrchr_m(directory,'/');
1407 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1408 if((directory[0] == '.') && (directory[1] == '\0'))
1411 pstrcpy(mask,directory);
1412 pstrcpy(directory,"./");
1418 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1420 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1422 return(ERROR_DOS(ERRDOS,ERRnomem));
1425 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1427 /* Realloc the params space */
1428 params = SMB_REALLOC(*pparams, 10);
1430 return ERROR_DOS(ERRDOS,ERRnomem);
1433 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1435 return(UNIXERROR(ERRDOS,ERRbadfile));
1437 /* Save the wildcard match and attribs we are using on this directory -
1438 needed as lanman2 assumes these are being saved between calls */
1440 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1441 dptr_close(&dptr_num);
1442 return ERROR_DOS(ERRDOS,ERRnomem);
1445 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1447 /* We don't need to check for VOL here as this is returned by
1448 a different TRANS2 call. */
1450 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1451 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1452 dont_descend = True;
1455 space_remaining = max_data_bytes;
1456 out_of_space = False;
1458 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1459 BOOL got_exact_match = False;
1461 /* this is a heuristic to avoid seeking the dirptr except when
1462 absolutely necessary. It allows for a filename of about 40 chars */
1463 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1464 out_of_space = True;
1467 finished = !get_lanman2_dir_entry(conn,
1469 mask,dirtype,info_level,
1470 requires_resume_key,dont_descend,
1471 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1475 if (finished && out_of_space)
1478 if (!finished && !out_of_space)
1482 * As an optimisation if we know we aren't looking
1483 * for a wildcard name (ie. the name matches the wildcard exactly)
1484 * then we can finish on any (first) match.
1485 * This speeds up large directory searches. JRA.
1491 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1494 /* Check if we can close the dirptr */
1495 if(close_after_first || (finished && close_if_end)) {
1496 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1497 dptr_close(&dptr_num);
1501 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1502 * from observation of NT.
1505 if(numentries == 0) {
1506 dptr_close(&dptr_num);
1507 return ERROR_DOS(ERRDOS,ERRbadfile);
1510 /* At this point pdata points to numentries directory entries. */
1512 /* Set up the return parameter block */
1513 SSVAL(params,0,dptr_num);
1514 SSVAL(params,2,numentries);
1515 SSVAL(params,4,finished);
1516 SSVAL(params,6,0); /* Never an EA error */
1517 SSVAL(params,8,last_name_off);
1519 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1521 if ((! *directory) && dptr_path(dptr_num))
1522 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1524 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1525 smb_fn_name(CVAL(inbuf,smb_com)),
1526 mask, directory, dirtype, numentries ) );
1529 * Force a name mangle here to ensure that the
1530 * mask as an 8.3 name is top of the mangled cache.
1531 * The reasons for this are subtle. Don't remove
1532 * this code unless you know what you are doing
1533 * (see PR#13758). JRA.
1536 if(!mangle_is_8_3_wildcards( mask, False))
1537 mangle_map(mask, True, True, SNUM(conn));
1542 /****************************************************************************
1543 Reply to a TRANS2_FINDNEXT.
1544 ****************************************************************************/
1546 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1547 char **pparams, int total_params, char **ppdata, int total_data,
1548 unsigned int max_data_bytes)
1550 /* We must be careful here that we don't return more than the
1551 allowed number of data bytes. If this means returning fewer than
1552 maxentries then so be it. We assume that the redirector has
1553 enough room for the fixed number of parameter bytes it has
1555 char *params = *pparams;
1556 char *pdata = *ppdata;
1557 int dptr_num = SVAL(params,0);
1558 int maxentries = SVAL(params,2);
1559 uint16 info_level = SVAL(params,4);
1560 uint32 resume_key = IVAL(params,6);
1561 uint16 findnext_flags = SVAL(params,10);
1562 BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1563 BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1564 BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1565 BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1566 pstring resume_name;
1572 int i, last_name_off=0;
1573 BOOL finished = False;
1574 BOOL dont_descend = False;
1575 BOOL out_of_space = False;
1576 int space_remaining;
1577 NTSTATUS ntstatus = NT_STATUS_OK;
1579 if (total_params < 12)
1580 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1582 *mask = *directory = *resume_name = 0;
1584 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1585 if (!NT_STATUS_IS_OK(ntstatus)) {
1586 return ERROR_NT(ntstatus);
1589 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1590 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1591 resume_key = %d resume name = %s continue=%d level = %d\n",
1592 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1593 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1596 /* W2K3 seems to treat zero as 1. */
1600 switch (info_level) {
1601 case SMB_INFO_STANDARD:
1602 case SMB_INFO_QUERY_EA_SIZE:
1603 case SMB_FIND_FILE_DIRECTORY_INFO:
1604 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1605 case SMB_FIND_FILE_NAMES_INFO:
1606 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1608 case SMB_FIND_FILE_UNIX:
1609 if (!lp_unix_extensions())
1610 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1613 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1616 pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1618 return ERROR_DOS(ERRDOS,ERRnomem);
1621 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1623 /* Realloc the params space */
1624 params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1625 if( params == NULL )
1626 return ERROR_DOS(ERRDOS,ERRnomem);
1630 /* Check that the dptr is valid */
1631 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1632 return ERROR_DOS(ERRDOS,ERRnofiles);
1634 string_set(&conn->dirpath,dptr_path(dptr_num));
1636 /* Get the wildcard mask from the dptr */
1637 if((p = dptr_wcard(dptr_num))== NULL) {
1638 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1639 return ERROR_DOS(ERRDOS,ERRnofiles);
1643 pstrcpy(directory,conn->dirpath);
1645 /* Get the attr mask from the dptr */
1646 dirtype = dptr_attr(dptr_num);
1648 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
1649 dptr_num, mask, dirtype,
1651 dptr_TellDir(conn->dirptr)));
1653 /* We don't need to check for VOL here as this is returned by
1654 a different TRANS2 call. */
1656 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1657 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1658 dont_descend = True;
1661 space_remaining = max_data_bytes;
1662 out_of_space = False;
1665 * Seek to the correct position. We no longer use the resume key but
1666 * depend on the last file name instead.
1669 if(*resume_name && !continue_bit) {
1672 long current_pos = 0;
1674 * Remember, mangle_map is called by
1675 * get_lanman2_dir_entry(), so the resume name
1676 * could be mangled. Ensure we check the unmangled name.
1679 if (mangle_is_mangled(resume_name)) {
1680 mangle_check_cache(resume_name, sizeof(resume_name)-1);
1684 * Fix for NT redirector problem triggered by resume key indexes
1685 * changing between directory scans. We now return a resume key of 0
1686 * and instead look for the filename to continue from (also given
1687 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1688 * findfirst/findnext (as is usual) then the directory pointer
1689 * should already be at the correct place.
1692 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
1693 } /* end if resume_name && !continue_bit */
1695 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1696 BOOL got_exact_match = False;
1698 /* this is a heuristic to avoid seeking the dirptr except when
1699 absolutely necessary. It allows for a filename of about 40 chars */
1700 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1701 out_of_space = True;
1704 finished = !get_lanman2_dir_entry(conn,
1706 mask,dirtype,info_level,
1707 requires_resume_key,dont_descend,
1708 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1712 if (finished && out_of_space)
1715 if (!finished && !out_of_space)
1719 * As an optimisation if we know we aren't looking
1720 * for a wildcard name (ie. the name matches the wildcard exactly)
1721 * then we can finish on any (first) match.
1722 * This speeds up large directory searches. JRA.
1728 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1731 /* Check if we can close the dirptr */
1732 if(close_after_request || (finished && close_if_end)) {
1733 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1734 dptr_close(&dptr_num); /* This frees up the saved mask */
1737 /* Set up the return parameter block */
1738 SSVAL(params,0,numentries);
1739 SSVAL(params,2,finished);
1740 SSVAL(params,4,0); /* Never an EA error */
1741 SSVAL(params,6,last_name_off);
1743 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1745 if ((! *directory) && dptr_path(dptr_num))
1746 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1748 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1749 smb_fn_name(CVAL(inbuf,smb_com)),
1750 mask, directory, dirtype, numentries ) );
1755 /****************************************************************************
1756 Reply to a TRANS2_QFSINFO (query filesystem info).
1757 ****************************************************************************/
1759 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1760 char **pparams, int total_params, char **ppdata, int total_data,
1761 unsigned int max_data_bytes)
1763 char *pdata = *ppdata;
1764 char *params = *pparams;
1765 uint16 info_level = SVAL(params,0);
1768 char *vname = volume_label(SNUM(conn));
1769 int snum = SNUM(conn);
1770 char *fstype = lp_fstype(SNUM(conn));
1773 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1775 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1776 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1777 return ERROR_DOS(ERRSRV,ERRinvdevice);
1780 pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1781 if ( pdata == NULL )
1782 return ERROR_DOS(ERRDOS,ERRnomem);
1785 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1787 switch (info_level) {
1788 case SMB_INFO_ALLOCATION:
1790 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1792 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1793 block_size = lp_block_size(snum);
1794 if (bsize < block_size) {
1795 SMB_BIG_UINT factor = block_size/bsize;
1800 if (bsize > block_size) {
1801 SMB_BIG_UINT factor = bsize/block_size;
1806 bytes_per_sector = 512;
1807 sectors_per_unit = bsize/bytes_per_sector;
1809 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1810 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1811 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1813 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1814 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1815 SIVAL(pdata,l1_cUnit,dsize);
1816 SIVAL(pdata,l1_cUnitAvail,dfree);
1817 SSVAL(pdata,l1_cbSector,bytes_per_sector);
1821 case SMB_INFO_VOLUME:
1822 /* Return volume name */
1824 * Add volume serial number - hash of a combination of
1825 * the called hostname and the service name.
1827 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
1828 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1829 SCVAL(pdata,l2_vol_cch,len);
1830 data_len = l2_vol_szVolLabel + len;
1831 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1832 (unsigned)st.st_ctime, len, vname));
1835 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1836 case SMB_FS_ATTRIBUTE_INFORMATION:
1839 #if defined(HAVE_SYS_QUOTAS)
1840 quota_flag = FILE_VOLUME_QUOTAS;
1843 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1844 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1845 quota_flag); /* FS ATTRIBUTES */
1847 SIVAL(pdata,4,255); /* Max filename component length */
1848 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1849 and will think we can't do long filenames */
1850 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1852 data_len = 12 + len;
1855 case SMB_QUERY_FS_LABEL_INFO:
1856 case SMB_FS_LABEL_INFORMATION:
1857 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1862 case SMB_QUERY_FS_VOLUME_INFO:
1863 case SMB_FS_VOLUME_INFORMATION:
1866 * Add volume serial number - hash of a combination of
1867 * the called hostname and the service name.
1869 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1870 (str_checksum(get_local_machine_name())<<16));
1872 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1873 SIVAL(pdata,12,len);
1875 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1876 (int)strlen(vname),vname, lp_servicename(snum)));
1879 case SMB_QUERY_FS_SIZE_INFO:
1880 case SMB_FS_SIZE_INFORMATION:
1882 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1884 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1885 block_size = lp_block_size(snum);
1886 if (bsize < block_size) {
1887 SMB_BIG_UINT factor = block_size/bsize;
1892 if (bsize > block_size) {
1893 SMB_BIG_UINT factor = bsize/block_size;
1898 bytes_per_sector = 512;
1899 sectors_per_unit = bsize/bytes_per_sector;
1900 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1901 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1902 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1903 SBIG_UINT(pdata,0,dsize);
1904 SBIG_UINT(pdata,8,dfree);
1905 SIVAL(pdata,16,sectors_per_unit);
1906 SIVAL(pdata,20,bytes_per_sector);
1910 case SMB_FS_FULL_SIZE_INFORMATION:
1912 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1914 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1915 block_size = lp_block_size(snum);
1916 if (bsize < block_size) {
1917 SMB_BIG_UINT factor = block_size/bsize;
1922 if (bsize > block_size) {
1923 SMB_BIG_UINT factor = bsize/block_size;
1928 bytes_per_sector = 512;
1929 sectors_per_unit = bsize/bytes_per_sector;
1930 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1931 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1932 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1933 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1934 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1935 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1936 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1937 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1941 case SMB_QUERY_FS_DEVICE_INFO:
1942 case SMB_FS_DEVICE_INFORMATION:
1944 SIVAL(pdata,0,0); /* dev type */
1945 SIVAL(pdata,4,0); /* characteristics */
1948 #ifdef HAVE_SYS_QUOTAS
1949 case SMB_FS_QUOTA_INFORMATION:
1951 * what we have to send --metze:
1953 * Unknown1: 24 NULL bytes
1954 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1955 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
1956 * Quota Flags: 2 byte :
1957 * Unknown3: 6 NULL bytes
1961 * details for Quota Flags:
1963 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1964 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
1965 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1966 * 0x0001 Enable Quotas: enable quota for this fs
1970 /* we need to fake up a fsp here,
1971 * because its not send in this call
1974 SMB_NTQUOTA_STRUCT quotas;
1977 ZERO_STRUCT(quotas);
1984 if (current_user.uid != 0) {
1985 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1986 lp_servicename(SNUM(conn)),conn->user));
1987 return ERROR_DOS(ERRDOS,ERRnoaccess);
1990 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
1991 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
1992 return ERROR_DOS(ERRSRV,ERRerror);
1997 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
1999 /* Unknown1 24 NULL bytes*/
2000 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2001 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2002 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2004 /* Default Soft Quota 8 bytes */
2005 SBIG_UINT(pdata,24,quotas.softlim);
2007 /* Default Hard Quota 8 bytes */
2008 SBIG_UINT(pdata,32,quotas.hardlim);
2010 /* Quota flag 2 bytes */
2011 SSVAL(pdata,40,quotas.qflags);
2013 /* Unknown3 6 NULL bytes */
2019 #endif /* HAVE_SYS_QUOTAS */
2020 case SMB_FS_OBJECTID_INFORMATION:
2025 * Query the version and capabilities of the CIFS UNIX extensions
2029 case SMB_QUERY_CIFS_UNIX_INFO:
2030 if (!lp_unix_extensions())
2031 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2033 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2034 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2035 SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
2038 case SMB_MAC_QUERY_FS_INFO:
2040 * Thursby MAC extension... ONLY on NTFS filesystems
2041 * once we do streams then we don't need this
2043 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2045 SIVAL(pdata,84,0x100); /* Don't support mac... */
2050 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2054 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2056 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2061 #ifdef HAVE_SYS_QUOTAS
2062 /****************************************************************************
2063 Reply to a TRANS2_SETFSINFO (set filesystem info).
2064 ****************************************************************************/
2066 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2067 char **pparams, int total_params, char **ppdata, int total_data,
2068 unsigned int max_data_bytes)
2070 char *pdata = *ppdata;
2071 char *params = *pparams;
2072 files_struct *fsp = NULL;
2075 SMB_NTQUOTA_STRUCT quotas;
2077 ZERO_STRUCT(quotas);
2079 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2082 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2083 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2084 lp_servicename(SNUM(conn)),conn->user));
2085 return ERROR_DOS(ERRSRV,ERRaccess);
2089 if (total_params < 4) {
2090 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2092 return ERROR_DOS(ERRDOS,ERRinvalidparam);
2095 fsp = file_fsp(params,0);
2097 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2098 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2099 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2102 info_level = SVAL(params,2);
2104 switch(info_level) {
2105 case SMB_FS_QUOTA_INFORMATION:
2106 /* note: normaly there're 48 bytes,
2107 * but we didn't use the last 6 bytes for now
2110 if (total_data < 42) {
2111 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2113 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2116 /* unknown_1 24 NULL bytes in pdata*/
2118 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2119 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2120 #ifdef LARGE_SMB_OFF_T
2121 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2122 #else /* LARGE_SMB_OFF_T */
2123 if ((IVAL(pdata,28) != 0)&&
2124 ((quotas.softlim != 0xFFFFFFFF)||
2125 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2126 /* more than 32 bits? */
2127 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2129 #endif /* LARGE_SMB_OFF_T */
2131 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2132 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2133 #ifdef LARGE_SMB_OFF_T
2134 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2135 #else /* LARGE_SMB_OFF_T */
2136 if ((IVAL(pdata,36) != 0)&&
2137 ((quotas.hardlim != 0xFFFFFFFF)||
2138 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2139 /* more than 32 bits? */
2140 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2142 #endif /* LARGE_SMB_OFF_T */
2144 /* quota_flags 2 bytes **/
2145 quotas.qflags = SVAL(pdata,40);
2147 /* unknown_2 6 NULL bytes follow*/
2149 /* now set the quotas */
2150 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2151 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2152 return ERROR_DOS(ERRSRV,ERRerror);
2157 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2159 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2164 * sending this reply works fine,
2165 * but I'm not sure it's the same
2166 * like windows do...
2169 outsize = set_message(outbuf,10,0,True);
2173 #endif /* HAVE_SYS_QUOTAS */
2175 /****************************************************************************
2176 Utility function to set bad path error.
2177 ****************************************************************************/
2179 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2181 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2182 err, (int)bad_path ));
2186 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2188 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2191 return UNIXERROR(def_class,def_code);
2194 /****************************************************************************
2195 Utility function to count the number of entries in a POSIX acl.
2196 ****************************************************************************/
2198 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2200 unsigned int ace_count = 0;
2201 int entry_id = SMB_ACL_FIRST_ENTRY;
2202 SMB_ACL_ENTRY_T entry;
2204 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2206 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2207 entry_id = SMB_ACL_NEXT_ENTRY;
2214 /****************************************************************************
2215 Utility function to marshall a POSIX acl into wire format.
2216 ****************************************************************************/
2218 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2220 int entry_id = SMB_ACL_FIRST_ENTRY;
2221 SMB_ACL_ENTRY_T entry;
2223 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2224 SMB_ACL_TAG_T tagtype;
2225 SMB_ACL_PERMSET_T permset;
2226 unsigned char perms = 0;
2227 unsigned int own_grp;
2230 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2231 entry_id = SMB_ACL_NEXT_ENTRY;
2234 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2235 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2239 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2240 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2244 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2245 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2246 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2248 SCVAL(pdata,1,perms);
2251 case SMB_ACL_USER_OBJ:
2252 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2253 own_grp = (unsigned int)pst->st_uid;
2254 SIVAL(pdata,2,own_grp);
2259 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2261 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2263 own_grp = (unsigned int)*puid;
2264 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2265 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2266 SIVAL(pdata,2,own_grp);
2270 case SMB_ACL_GROUP_OBJ:
2271 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2272 own_grp = (unsigned int)pst->st_gid;
2273 SIVAL(pdata,2,own_grp);
2278 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2280 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2282 own_grp = (unsigned int)*pgid;
2283 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2284 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2285 SIVAL(pdata,2,own_grp);
2290 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2291 SIVAL(pdata,2,0xFFFFFFFF);
2292 SIVAL(pdata,6,0xFFFFFFFF);
2295 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2296 SIVAL(pdata,2,0xFFFFFFFF);
2297 SIVAL(pdata,6,0xFFFFFFFF);
2300 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2303 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2309 /****************************************************************************
2310 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2311 file name or file id).
2312 ****************************************************************************/
2314 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2315 char **pparams, int total_params, char **ppdata, int total_data,
2316 unsigned int max_data_bytes)
2318 char *params = *pparams;
2319 char *pdata = *ppdata;
2320 uint16 tran_call = SVAL(inbuf, smb_setup0);
2323 SMB_OFF_T file_size=0;
2324 SMB_BIG_UINT allocation_size=0;
2325 unsigned int data_size;
2326 unsigned int param_size = 2;
2327 SMB_STRUCT_STAT sbuf;
2328 pstring fname, dos_fname;
2333 BOOL bad_path = False;
2334 BOOL delete_pending = False;
2337 files_struct *fsp = NULL;
2338 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2341 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2345 if (tran_call == TRANSACT2_QFILEINFO) {
2346 if (total_params < 4)
2347 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2349 fsp = file_fsp(params,0);
2350 info_level = SVAL(params,2);
2352 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2354 if(fsp && (fsp->fake_file_handle)) {
2356 * This is actually for the QUOTA_FAKE_FILE --metze
2359 pstrcpy(fname, fsp->fsp_name);
2360 /* We know this name is ok, it's already passed the checks. */
2362 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2364 * This is actually a QFILEINFO on a directory
2365 * handle (returned from an NT SMB). NT5.0 seems
2366 * to do this call. JRA.
2368 /* We know this name is ok, it's already passed the checks. */
2369 pstrcpy(fname, fsp->fsp_name);
2371 if (INFO_LEVEL_IS_UNIX(info_level)) {
2372 /* Always do lstat for UNIX calls. */
2373 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2374 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2375 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2377 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2378 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2379 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2382 delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2385 * Original code - this is an open file.
2387 CHECK_FSP(fsp,conn);
2389 pstrcpy(fname, fsp->fsp_name);
2390 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2391 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2392 return(UNIXERROR(ERRDOS,ERRbadfid));
2394 pos = fsp->position_information;
2395 delete_pending = fsp->delete_on_close;
2396 desired_access = fsp->desired_access;
2399 NTSTATUS status = NT_STATUS_OK;
2402 if (total_params < 6)
2403 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2405 info_level = SVAL(params,0);
2407 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2409 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2410 if (!NT_STATUS_IS_OK(status)) {
2411 return ERROR_NT(status);
2414 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2416 unix_convert(fname,conn,0,&bad_path,&sbuf);
2418 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2420 if (!check_name(fname,conn)) {
2421 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2422 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2425 if (INFO_LEVEL_IS_UNIX(info_level)) {
2426 /* Always do lstat for UNIX calls. */
2427 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2428 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2429 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2431 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2432 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2433 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2437 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2438 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2440 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2441 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2443 p = strrchr_m(fname,'/');
2449 mode = dos_mode(conn,fname,&sbuf);
2451 mode = FILE_ATTRIBUTE_NORMAL;
2453 fullpathname = fname;
2454 file_size = get_file_size(sbuf);
2455 allocation_size = get_allocation_size(fsp,&sbuf);
2457 /* This is necessary, as otherwise the desktop.ini file in
2458 * this folder is ignored */
2459 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2463 params = SMB_REALLOC(*pparams,2);
2465 return ERROR_DOS(ERRDOS,ERRnomem);
2467 memset((char *)params,'\0',2);
2468 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2469 pdata = SMB_REALLOC(*ppdata, data_size);
2470 if ( pdata == NULL )
2471 return ERROR_DOS(ERRDOS,ERRnomem);
2474 if (total_data > 0 && IVAL(pdata,0) == total_data) {
2475 /* uggh, EAs for OS2 */
2476 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2477 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2480 memset((char *)pdata,'\0',data_size);
2482 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2484 if (fsp && fsp->pending_modtime) {
2485 /* the pending modtime overrides the current modtime */
2486 sbuf.st_mtime = fsp->pending_modtime;
2489 if (lp_dos_filetime_resolution(SNUM(conn))) {
2491 sbuf.st_atime &= ~1;
2492 sbuf.st_ctime &= ~1;
2493 sbuf.st_mtime &= ~1;
2496 /* NT expects the name to be in an exact form of the *full*
2497 filename. See the trans2 torture test */
2498 if (strequal(base_name,".")) {
2499 pstrcpy(dos_fname, "\\");
2501 pstr_sprintf(dos_fname, "\\%s", fname);
2502 string_replace(dos_fname, '/', '\\');
2505 switch (info_level) {
2506 case SMB_INFO_STANDARD:
2507 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2509 put_dos_date2(pdata,l1_fdateCreation,c_time);
2510 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2511 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2512 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2513 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2514 SSVAL(pdata,l1_attrFile,mode);
2517 case SMB_INFO_QUERY_EA_SIZE:
2519 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2520 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2522 put_dos_date2(pdata,l1_fdateCreation,c_time);
2523 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2524 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2525 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2526 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2527 SSVAL(pdata,l1_attrFile,mode);
2528 SIVAL(pdata,l1_attrFile+2,ea_size);
2532 case SMB_INFO_IS_NAME_VALID:
2533 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2534 if (tran_call == TRANSACT2_QFILEINFO) {
2535 /* os/2 needs this ? really ?*/
2536 return ERROR_DOS(ERRDOS,ERRbadfunc);
2542 case SMB_INFO_QUERY_EAS_FROM_LIST:
2543 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2545 put_dos_date2(pdata,0,c_time);
2546 put_dos_date2(pdata,4,sbuf.st_atime);
2547 put_dos_date2(pdata,8,sbuf.st_mtime);
2548 SIVAL(pdata,12,(uint32)file_size);
2549 SIVAL(pdata,16,(uint32)allocation_size);
2550 SIVAL(pdata,20,mode);
2553 case SMB_INFO_QUERY_ALL_EAS:
2554 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2555 /* We have data_size bytes to put EA's into. */
2556 data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname);
2559 case SMB_FILE_BASIC_INFORMATION:
2560 case SMB_QUERY_FILE_BASIC_INFO:
2562 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2563 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2564 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2566 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2570 put_long_date(pdata,c_time);
2571 put_long_date(pdata+8,sbuf.st_atime);
2572 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2573 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2574 SIVAL(pdata,32,mode);
2576 DEBUG(5,("SMB_QFBI - "));
2578 time_t create_time = c_time;
2579 DEBUG(5,("create: %s ", ctime(&create_time)));
2581 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2582 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2583 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2584 DEBUG(5,("mode: %x\n", mode));
2588 case SMB_FILE_STANDARD_INFORMATION:
2589 case SMB_QUERY_FILE_STANDARD_INFO:
2591 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2593 SOFF_T(pdata,0,allocation_size);
2594 SOFF_T(pdata,8,file_size);
2595 if (delete_pending & sbuf.st_nlink)
2596 SIVAL(pdata,16,sbuf.st_nlink - 1);
2598 SIVAL(pdata,16,sbuf.st_nlink);
2600 SCVAL(pdata,21,(mode&aDIR)?1:0);
2603 case SMB_FILE_EA_INFORMATION:
2604 case SMB_QUERY_FILE_EA_INFO:
2606 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2607 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2609 SIVAL(pdata,0,ea_size);
2613 /* Get the 8.3 name - used if NT SMB was negotiated. */
2614 case SMB_QUERY_FILE_ALT_NAME_INFO:
2615 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2619 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2620 pstrcpy(short_name,base_name);
2621 /* Mangle if not already 8.3 */
2622 if(!mangle_is_8_3(short_name, True)) {
2623 mangle_map(short_name,True,True,SNUM(conn));
2625 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2626 data_size = 4 + len;
2631 case SMB_QUERY_FILE_NAME_INFO:
2633 this must be *exactly* right for ACLs on mapped drives to work
2635 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2636 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2637 data_size = 4 + len;
2641 case SMB_FILE_ALLOCATION_INFORMATION:
2642 case SMB_QUERY_FILE_ALLOCATION_INFO:
2643 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2645 SOFF_T(pdata,0,allocation_size);
2648 case SMB_FILE_END_OF_FILE_INFORMATION:
2649 case SMB_QUERY_FILE_END_OF_FILEINFO:
2650 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2652 SOFF_T(pdata,0,file_size);
2655 case SMB_QUERY_FILE_ALL_INFO:
2656 case SMB_FILE_ALL_INFORMATION:
2658 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2659 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2660 put_long_date(pdata,c_time);
2661 put_long_date(pdata+8,sbuf.st_atime);
2662 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2663 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2664 SIVAL(pdata,32,mode);
2666 SOFF_T(pdata,0,allocation_size);
2667 SOFF_T(pdata,8,file_size);
2668 if (delete_pending && sbuf.st_nlink)
2669 SIVAL(pdata,16,sbuf.st_nlink - 1);
2671 SIVAL(pdata,16,sbuf.st_nlink);
2672 SCVAL(pdata,20,delete_pending);
2673 SCVAL(pdata,21,(mode&aDIR)?1:0);
2675 SIVAL(pdata,0,ea_size);
2676 pdata += 4; /* EA info */
2677 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2680 data_size = PTR_DIFF(pdata,(*ppdata));
2683 case SMB_FILE_INTERNAL_INFORMATION:
2684 /* This should be an index number - looks like
2687 I think this causes us to fail the IFSKIT
2688 BasicFileInformationTest. -tpot */
2690 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2691 SIVAL(pdata,0,sbuf.st_dev);
2692 SIVAL(pdata,4,sbuf.st_ino);
2696 case SMB_FILE_ACCESS_INFORMATION:
2697 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2698 SIVAL(pdata,0,desired_access);
2702 case SMB_FILE_NAME_INFORMATION:
2703 /* Pathname with leading '\'. */
2706 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2707 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2708 SIVAL(pdata,0,byte_len);
2709 data_size = 4 + byte_len;
2713 case SMB_FILE_DISPOSITION_INFORMATION:
2714 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2716 SCVAL(pdata,0,delete_pending);
2719 case SMB_FILE_POSITION_INFORMATION:
2720 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2722 SOFF_T(pdata,0,pos);
2725 case SMB_FILE_MODE_INFORMATION:
2726 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2727 SIVAL(pdata,0,mode);
2731 case SMB_FILE_ALIGNMENT_INFORMATION:
2732 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2733 SIVAL(pdata,0,0); /* No alignment needed. */
2739 * NT4 server just returns "invalid query" to this - if we try to answer
2740 * it then NTws gets a BSOD! (tridge).
2741 * W2K seems to want this. JRA.
2743 case SMB_QUERY_FILE_STREAM_INFO:
2745 case SMB_FILE_STREAM_INFORMATION:
2746 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2750 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2751 SIVAL(pdata,0,0); /* ??? */
2752 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2753 SOFF_T(pdata,8,file_size);
2754 SIVAL(pdata,16,allocation_size);
2755 SIVAL(pdata,20,0); /* ??? */
2756 data_size = 24 + byte_len;
2760 case SMB_QUERY_COMPRESSION_INFO:
2761 case SMB_FILE_COMPRESSION_INFORMATION:
2762 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2763 SOFF_T(pdata,0,file_size);
2764 SIVAL(pdata,8,0); /* ??? */
2765 SIVAL(pdata,12,0); /* ??? */
2769 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2770 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2771 put_long_date(pdata,c_time);
2772 put_long_date(pdata+8,sbuf.st_atime);
2773 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2774 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2775 SIVAL(pdata,32,allocation_size);
2776 SOFF_T(pdata,40,file_size);
2777 SIVAL(pdata,48,mode);
2778 SIVAL(pdata,52,0); /* ??? */
2782 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2783 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2784 SIVAL(pdata,0,mode);
2790 * CIFS UNIX Extensions.
2793 case SMB_QUERY_FILE_UNIX_BASIC:
2795 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2796 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2798 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2801 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2804 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2805 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2806 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2809 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2813 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2817 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2820 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2824 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2828 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2831 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2835 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2838 data_size = PTR_DIFF(pdata,(*ppdata));
2842 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2844 for (i=0; i<100; i++)
2845 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2851 case SMB_QUERY_FILE_UNIX_LINK:
2855 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
2857 if(!S_ISLNK(sbuf.st_mode))
2858 return(UNIXERROR(ERRSRV,ERRbadlink));
2860 return(UNIXERROR(ERRDOS,ERRbadlink));
2862 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2864 return(UNIXERROR(ERRDOS,ERRnoaccess));
2866 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2868 data_size = PTR_DIFF(pdata,(*ppdata));
2873 case SMB_QUERY_POSIX_ACL:
2875 SMB_ACL_T file_acl = NULL;
2876 SMB_ACL_T def_acl = NULL;
2877 uint16 num_file_acls = 0;
2878 uint16 num_def_acls = 0;
2880 if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
2881 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
2883 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
2886 if (file_acl == NULL && no_acl_syscall_error(errno)) {
2887 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
2889 return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
2892 if (S_ISDIR(sbuf.st_mode)) {
2893 if (fsp && fsp->is_directory) {
2894 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
2896 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
2898 def_acl = free_empty_sys_acl(conn, def_acl);
2901 num_file_acls = count_acl_entries(conn, file_acl);
2902 num_def_acls = count_acl_entries(conn, def_acl);
2904 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
2905 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
2907 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
2908 SMB_POSIX_ACL_HEADER_SIZE) ));
2910 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2913 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2915 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2918 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
2919 SSVAL(pdata,2,num_file_acls);
2920 SSVAL(pdata,4,num_def_acls);
2921 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
2923 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2926 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2928 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
2930 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
2932 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2935 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2937 return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
2941 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
2944 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2946 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
2951 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2954 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
2959 /****************************************************************************
2960 Deal with the internal needs of setting the delete on close flag. Note that
2961 as the tdb locking is recursive, it is safe to call this from within
2962 open_file_shared. JRA.
2963 ****************************************************************************/
2965 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
2967 if (delete_on_close) {
2969 * Only allow delete on close for writable files.
2972 if (dosmode & aRONLY) {
2973 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
2975 return NT_STATUS_CANNOT_DELETE;
2979 * Only allow delete on close for writable shares.
2982 if (!CAN_WRITE(fsp->conn)) {
2983 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2985 return NT_STATUS_ACCESS_DENIED;
2989 * Only allow delete on close for files/directories opened with delete intent.
2992 if (!(fsp->desired_access & DELETE_ACCESS)) {
2993 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2995 return NT_STATUS_ACCESS_DENIED;
2999 if(fsp->is_directory) {
3000 fsp->directory_delete_on_close = delete_on_close;
3001 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3002 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3004 fsp->delete_on_close = delete_on_close;
3005 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3006 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3009 return NT_STATUS_OK;
3012 /****************************************************************************
3013 Sets the delete on close flag over all share modes on this file.
3014 Modify the share mode entry for all files open
3015 on this device and inode to tell other smbds we have
3016 changed the delete on close flag. This will be noticed
3017 in the close code, the last closer will delete the file
3019 ****************************************************************************/
3021 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3023 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3024 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3026 if (fsp->is_directory || fsp->is_stat)
3027 return NT_STATUS_OK;
3029 if (lock_share_entry_fsp(fsp) == False)
3030 return NT_STATUS_ACCESS_DENIED;
3032 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3033 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3035 unlock_share_entry_fsp(fsp);
3036 return NT_STATUS_ACCESS_DENIED;
3039 unlock_share_entry_fsp(fsp);
3040 return NT_STATUS_OK;
3043 /****************************************************************************
3044 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3046 ****************************************************************************/
3048 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3050 BOOL bad_path_oldname = False;
3051 BOOL bad_path_newname = False;
3052 SMB_STRUCT_STAT sbuf1, sbuf2;
3053 pstring last_component_oldname;
3054 pstring last_component_newname;
3055 NTSTATUS status = NT_STATUS_OK;
3061 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3062 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3065 unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3066 if (bad_path_oldname) {
3067 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3070 /* Quick check for "." and ".." */
3071 if (last_component_oldname[0] == '.') {
3072 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3073 return NT_STATUS_OBJECT_NAME_INVALID;
3077 /* source must already exist. */
3078 if (!VALID_STAT(sbuf1)) {
3079 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3082 if (!check_name(oldname,conn)) {
3083 return NT_STATUS_ACCESS_DENIED;
3086 unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3087 if (bad_path_newname) {
3088 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3091 /* Quick check for "." and ".." */
3092 if (last_component_newname[0] == '.') {
3093 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3094 return NT_STATUS_OBJECT_NAME_INVALID;
3098 /* Disallow if newname already exists. */
3099 if (VALID_STAT(sbuf2)) {
3100 return NT_STATUS_OBJECT_NAME_COLLISION;
3103 if (!check_name(newname,conn)) {
3104 return NT_STATUS_ACCESS_DENIED;
3107 /* No links from a directory. */
3108 if (S_ISDIR(sbuf1.st_mode)) {
3109 return NT_STATUS_FILE_IS_A_DIRECTORY;
3112 /* Ensure this is within the share. */
3113 if (!reduce_name(conn, oldname) != 0)
3114 return NT_STATUS_ACCESS_DENIED;
3116 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3118 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3119 status = map_nt_error_from_unix(errno);
3120 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3121 nt_errstr(status), newname, oldname));
3127 /****************************************************************************
3128 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3129 ****************************************************************************/
3131 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3132 char **pparams, int total_params, char **ppdata, int total_data,
3133 unsigned int max_data_bytes)
3135 char *params = *pparams;
3136 char *pdata = *ppdata;
3137 uint16 tran_call = SVAL(inbuf, smb_setup0);
3142 SMB_STRUCT_STAT sbuf;
3145 BOOL bad_path = False;
3146 files_struct *fsp = NULL;
3147 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3148 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3149 mode_t unixmode = 0;
3150 NTSTATUS status = NT_STATUS_OK;
3153 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3157 if (tran_call == TRANSACT2_SETFILEINFO) {
3158 if (total_params < 4)
3159 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3161 fsp = file_fsp(params,0);
3162 info_level = SVAL(params,2);
3164 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3166 * This is actually a SETFILEINFO on a directory
3167 * handle (returned from an NT SMB). NT5.0 seems
3168 * to do this call. JRA.
3170 pstrcpy(fname, fsp->fsp_name);
3171 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3172 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3173 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3175 } else if (fsp && fsp->print_file) {
3177 * Doing a DELETE_ON_CLOSE should cancel a print job.
3179 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3180 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3182 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3185 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3188 return (UNIXERROR(ERRDOS,ERRbadpath));
3191 * Original code - this is an open file.
3193 CHECK_FSP(fsp,conn);
3195 pstrcpy(fname, fsp->fsp_name);
3198 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3199 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3200 return(UNIXERROR(ERRDOS,ERRbadfid));
3205 if (total_params < 6)
3206 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3208 info_level = SVAL(params,0);
3209 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3210 if (!NT_STATUS_IS_OK(status)) {
3211 return ERROR_NT(status);
3213 unix_convert(fname,conn,0,&bad_path,&sbuf);
3215 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3219 * For CIFS UNIX extensions the target name may not exist.
3222 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3223 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3224 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3227 if(!check_name(fname, conn)) {
3228 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3233 if (!CAN_WRITE(conn))
3234 return ERROR_DOS(ERRSRV,ERRaccess);
3236 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3237 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3239 if (VALID_STAT(sbuf))
3240 unixmode = sbuf.st_mode;
3242 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3243 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3245 /* Realloc the parameter and data sizes */
3246 params = SMB_REALLOC(*pparams,2);
3248 return ERROR_DOS(ERRDOS,ERRnomem);
3253 if (fsp && fsp->pending_modtime) {
3254 /* the pending modtime overrides the current modtime */
3255 sbuf.st_mtime = fsp->pending_modtime;
3258 size = get_file_size(sbuf);
3259 tvs.modtime = sbuf.st_mtime;
3260 tvs.actime = sbuf.st_atime;
3261 dosmode = dos_mode(conn,fname,&sbuf);
3262 unixmode = sbuf.st_mode;
3264 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3265 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3267 switch (info_level) {
3268 case SMB_INFO_STANDARD:
3270 if (total_data < 12)
3271 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3274 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3276 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3280 case SMB_INFO_SET_EA:
3281 status = set_ea(conn, fsp, fname, pdata, total_data);
3282 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3283 return ERROR_NT(status);
3286 /* XXXX um, i don't think this is right.
3287 it's also not in the cifs6.txt spec.
3289 case SMB_INFO_QUERY_EAS_FROM_LIST:
3290 if (total_data < 28)
3291 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3293 tvs.actime = make_unix_date2(pdata+8);
3294 tvs.modtime = make_unix_date2(pdata+12);
3295 size = IVAL(pdata,16);
3296 dosmode = IVAL(pdata,24);
3299 /* XXXX nor this. not in cifs6.txt, either. */
3300 case SMB_INFO_QUERY_ALL_EAS:
3301 if (total_data < 28)
3302 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3304 tvs.actime = make_unix_date2(pdata+8);
3305 tvs.modtime = make_unix_date2(pdata+12);
3306 size = IVAL(pdata,16);
3307 dosmode = IVAL(pdata,24);
3310 case SMB_SET_FILE_BASIC_INFO:
3311 case SMB_FILE_BASIC_INFORMATION:
3313 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3315 time_t changed_time;
3317 if (total_data < 36)
3318 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3320 /* Ignore create time at offset pdata. */
3323 tvs.actime = interpret_long_date(pdata+8);
3325 write_time = interpret_long_date(pdata+16);
3326 changed_time = interpret_long_date(pdata+24);
3328 tvs.modtime = MIN(write_time, changed_time);
3330 if (write_time > tvs.modtime && write_time != 0xffffffff) {
3331 tvs.modtime = write_time;
3333 /* Prefer a defined time to an undefined one. */
3334 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3335 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
3336 ? changed_time : write_time);
3339 dosmode = IVAL(pdata,32);
3343 case SMB_FILE_ALLOCATION_INFORMATION:
3344 case SMB_SET_FILE_ALLOCATION_INFO:
3347 SMB_BIG_UINT allocation_size;
3350 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3352 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3353 #ifdef LARGE_SMB_OFF_T
3354 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3355 #else /* LARGE_SMB_OFF_T */
3356 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3357 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3358 #endif /* LARGE_SMB_OFF_T */
3359 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3360 fname, (double)allocation_size ));
3362 if (allocation_size)
3363 allocation_size = smb_roundup(allocation_size);
3365 if(allocation_size != get_file_size(sbuf)) {
3366 SMB_STRUCT_STAT new_sbuf;
3368 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3369 fname, (double)allocation_size ));
3372 files_struct *new_fsp = NULL;
3373 int access_mode = 0;
3376 if(global_oplock_break) {
3377 /* Queue this file modify as we are the process of an oplock break. */
3379 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3380 DEBUGADD(2,( "in oplock break state.\n"));
3382 push_oplock_pending_smb_message(inbuf, length);
3386 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3387 SET_OPEN_MODE(DOS_OPEN_RDWR),
3388 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3389 FILE_ATTRIBUTE_NORMAL,
3390 INTERNAL_OPEN_ONLY, &access_mode, &action);
3392 if (new_fsp == NULL)
3393 return(UNIXERROR(ERRDOS,ERRbadpath));
3394 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3395 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3396 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3397 new_fsp->fnum, strerror(errno)));
3400 close_file(new_fsp,True);
3402 ret = vfs_allocate_file_space(fsp, allocation_size);
3403 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3404 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3405 fsp->fnum, strerror(errno)));
3410 return ERROR_NT(NT_STATUS_DISK_FULL);
3412 /* Allocate can truncate size... */
3413 size = get_file_size(new_sbuf);
3419 case SMB_FILE_END_OF_FILE_INFORMATION:
3420 case SMB_SET_FILE_END_OF_FILE_INFO:
3423 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3425 size = IVAL(pdata,0);
3426 #ifdef LARGE_SMB_OFF_T
3427 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3428 #else /* LARGE_SMB_OFF_T */
3429 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3430 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3431 #endif /* LARGE_SMB_OFF_T */
3432 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3436 case SMB_FILE_DISPOSITION_INFORMATION:
3437 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3439 BOOL delete_on_close;
3442 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3444 delete_on_close = (CVAL(pdata,0) ? True : False);
3446 /* Just ignore this set on a path. */
3447 if (tran_call != TRANSACT2_SETFILEINFO)
3451 return(UNIXERROR(ERRDOS,ERRbadfid));
3453 status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3455 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3456 return ERROR_NT(status);
3458 /* The set is across all open files on this dev/inode pair. */
3459 status =set_delete_on_close_over_all(fsp, delete_on_close);
3460 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3461 return ERROR_NT(status);
3466 case SMB_FILE_POSITION_INFORMATION:
3468 SMB_BIG_UINT position_information;
3471 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3473 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3474 #ifdef LARGE_SMB_OFF_T
3475 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3476 #else /* LARGE_SMB_OFF_T */
3477 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3478 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3479 #endif /* LARGE_SMB_OFF_T */
3480 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3481 fname, (double)position_information ));
3483 fsp->position_information = position_information;
3488 * CIFS UNIX extensions.
3491 case SMB_SET_FILE_UNIX_BASIC:
3493 uint32 raw_unixmode;
3495 if (total_data < 100)
3496 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3498 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3499 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3500 size=IVAL(pdata,0); /* first 8 Bytes are size */
3501 #ifdef LARGE_SMB_OFF_T
3502 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3503 #else /* LARGE_SMB_OFF_T */
3504 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3505 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3506 #endif /* LARGE_SMB_OFF_T */
3508 pdata+=24; /* ctime & st_blocks are not changed */
3509 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
3510 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
3512 set_owner = (uid_t)IVAL(pdata,0);
3514 set_grp = (gid_t)IVAL(pdata,0);
3516 raw_unixmode = IVAL(pdata,28);
3517 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3518 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3520 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3521 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3522 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3524 if (!VALID_STAT(sbuf)) {
3527 * The only valid use of this is to create character and block
3528 * devices, and named pipes. This is deprecated (IMHO) and
3529 * a new info level should be used for mknod. JRA.
3532 uint32 file_type = IVAL(pdata,0);
3533 #if defined(HAVE_MAKEDEV)
3534 uint32 dev_major = IVAL(pdata,4);
3535 uint32 dev_minor = IVAL(pdata,12);
3538 uid_t myuid = geteuid();
3539 gid_t mygid = getegid();
3540 SMB_DEV_T dev = (SMB_DEV_T)0;
3542 if (tran_call == TRANSACT2_SETFILEINFO)
3543 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3545 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3546 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3548 #if defined(HAVE_MAKEDEV)
3549 dev = makedev(dev_major, dev_minor);
3552 /* We can only create as the owner/group we are. */
3554 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3555 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3556 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3557 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3559 switch (file_type) {
3560 #if defined(S_IFIFO)
3561 case UNIX_TYPE_FIFO:
3562 unixmode |= S_IFIFO;
3565 #if defined(S_IFSOCK)
3566 case UNIX_TYPE_SOCKET:
3567 unixmode |= S_IFSOCK;
3570 #if defined(S_IFCHR)
3571 case UNIX_TYPE_CHARDEV:
3572 unixmode |= S_IFCHR;
3575 #if defined(S_IFBLK)
3576 case UNIX_TYPE_BLKDEV:
3577 unixmode |= S_IFBLK;
3581 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3584 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3585 0%o for file %s\n", (double)dev, unixmode, fname ));
3587 /* Ok - do the mknod. */
3588 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
3589 return(UNIXERROR(ERRDOS,ERRnoaccess));
3591 inherit_access_acl(conn, fname, unixmode);
3594 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3599 * Deal with the UNIX specific mode set.
3602 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3603 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3604 (unsigned int)unixmode, fname ));
3605 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3606 return(UNIXERROR(ERRDOS,ERRnoaccess));
3610 * Deal with the UNIX specific uid set.
3613 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3614 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3615 (unsigned int)set_owner, fname ));
3616 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3617 return(UNIXERROR(ERRDOS,ERRnoaccess));
3621 * Deal with the UNIX specific gid set.
3624 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3625 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3626 (unsigned int)set_owner, fname ));
3627 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3628 return(UNIXERROR(ERRDOS,ERRnoaccess));
3633 case SMB_SET_FILE_UNIX_LINK:
3635 pstring link_target;
3636 char *newname = fname;
3638 /* Set a symbolic link. */
3639 /* Don't allow this if follow links is false. */
3641 if (!lp_symlinks(SNUM(conn)))
3642 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3644 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
3646 /* !widelinks forces the target path to be within the share. */
3647 /* This means we can interpret the target as a pathname. */
3648 if (!lp_widelinks(SNUM(conn))) {
3650 char *last_dirp = NULL;
3652 unix_format(link_target);
3653 if (*link_target == '/') {
3654 /* No absolute paths allowed. */
3655 return(UNIXERROR(ERRDOS,ERRnoaccess));
3657 pstrcpy(rel_name, newname);
3658 last_dirp = strrchr_m(rel_name, '/');
3660 last_dirp[1] = '\0';
3662 pstrcpy(rel_name, "./");
3664 pstrcat(rel_name, link_target);
3666 if (!check_name(rel_name, conn)) {
3667 return(UNIXERROR(ERRDOS,ERRnoaccess));
3671 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3672 fname, link_target ));
3674 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
3675 return(UNIXERROR(ERRDOS,ERRnoaccess));
3677 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3681 case SMB_SET_FILE_UNIX_HLINK:
3684 char *newname = fname;
3686 /* Set a hard link. */
3687 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
3688 if (!NT_STATUS_IS_OK(status)) {
3689 return ERROR_NT(status);
3692 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3695 status = hardlink_internals(conn, oldname, newname);
3696 if (!NT_STATUS_IS_OK(status)) {
3697 return ERROR_NT(status);
3701 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3705 case SMB_FILE_RENAME_INFORMATION:
3714 if (total_data < 12)
3715 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3717 overwrite = (CVAL(pdata,0) ? True : False);
3718 root_fid = IVAL(pdata,4);
3719 len = IVAL(pdata,8);
3720 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
3721 if (!NT_STATUS_IS_OK(status)) {
3722 return ERROR_NT(status);
3725 /* Check the new name has no '/' characters. */
3726 if (strchr_m(newname, '/'))
3727 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3729 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3731 /* Create the base directory. */
3732 pstrcpy(base_name, fname);
3733 p = strrchr_m(base_name, '/');
3736 /* Append the new name. */
3737 pstrcat(base_name, "/");
3738 pstrcat(base_name, newname);
3741 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3742 fsp->fnum, fsp->fsp_name, base_name ));
3743 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
3745 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3747 status = rename_internals(conn, fname, base_name, 0, overwrite);
3749 if (!NT_STATUS_IS_OK(status)) {
3750 return ERROR_NT(status);
3752 process_pending_change_notify_queue((time_t)0);
3754 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3758 case SMB_SET_POSIX_ACL:
3760 uint16 posix_acl_version;
3761 uint16 num_file_acls;
3762 uint16 num_def_acls;
3763 BOOL valid_file_acls = True;
3764 BOOL valid_def_acls = True;
3766 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
3767 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3769 posix_acl_version = SVAL(pdata,0);
3770 num_file_acls = SVAL(pdata,2);
3771 num_def_acls = SVAL(pdata,4);
3773 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3774 valid_file_acls = False;
3778 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3779 valid_def_acls = False;
3783 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
3784 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3787 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
3788 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
3789 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3792 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
3793 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
3794 return(UNIXERROR(ERRDOS,ERRnoaccess));
3797 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
3798 pdata + SMB_POSIX_ACL_HEADER_SIZE +
3799 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
3800 return(UNIXERROR(ERRDOS,ERRnoaccess));
3804 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3809 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3812 /* get some defaults (no modifications) if any info is zero or -1. */
3813 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
3814 tvs.actime = sbuf.st_atime;
3816 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3817 tvs.modtime = sbuf.st_mtime;
3819 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3820 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3821 DEBUG(6,("size: %.0f ", (double)size));
3824 if (S_ISDIR(sbuf.st_mode))
3830 DEBUG(6,("dosmode: %x\n" , dosmode));
3832 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3833 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3834 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3835 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3838 * Only do this test if we are not explicitly
3839 * changing the size of a file.
3842 size = get_file_size(sbuf);
3846 * Try and set the times, size and mode of this file -
3847 * if they are different from the current values
3849 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3852 * This was a setfileinfo on an open file.
3853 * NT does this a lot. We also need to
3854 * set the time here, as it can be read by
3855 * FindFirst/FindNext and with the patch for bug #2045
3856 * in smbd/fileio.c it ensures that this timestamp is
3857 * kept sticky even after a write. We save the request
3858 * away and will set it on file close and after a write. JRA.
3861 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3862 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3863 fsp->pending_modtime = tvs.modtime;
3866 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3868 if(file_utime(conn, fname, &tvs)!=0) {
3869 return(UNIXERROR(ERRDOS,ERRnoaccess));
3874 /* check the mode isn't different, before changing it */
3875 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3877 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3879 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
3880 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
3881 return(UNIXERROR(ERRDOS,ERRnoaccess));
3885 if (size != get_file_size(sbuf)) {
3889 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3890 fname, (double)size ));
3893 files_struct *new_fsp = NULL;
3894 int access_mode = 0;
3897 if(global_oplock_break) {
3898 /* Queue this file modify as we are the process of an oplock break. */
3900 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3901 DEBUGADD(2,( "in oplock break state.\n"));
3903 push_oplock_pending_smb_message(inbuf, length);
3907 new_fsp = open_file_shared(conn, fname, &sbuf,
3908 SET_OPEN_MODE(DOS_OPEN_RDWR),
3909 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3910 FILE_ATTRIBUTE_NORMAL,
3911 INTERNAL_OPEN_ONLY, &access_mode, &action);
3913 if (new_fsp == NULL)
3914 return(UNIXERROR(ERRDOS,ERRbadpath));
3915 ret = vfs_set_filelen(new_fsp, size);
3916 close_file(new_fsp,True);
3918 ret = vfs_set_filelen(fsp, size);
3922 return (UNIXERROR(ERRHRD,ERRdiskfull));
3926 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3931 /****************************************************************************
3932 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3933 ****************************************************************************/
3935 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3936 char **pparams, int total_params, char **ppdata, int total_data,
3937 unsigned int max_data_bytes)
3939 char *params = *pparams;
3942 SMB_STRUCT_STAT sbuf;
3943 BOOL bad_path = False;
3944 NTSTATUS status = NT_STATUS_OK;
3946 if (!CAN_WRITE(conn))
3947 return ERROR_DOS(ERRSRV,ERRaccess);
3949 if (total_params < 4)
3950 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3952 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
3953 if (!NT_STATUS_IS_OK(status)) {
3954 return ERROR_NT(status);
3957 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3959 unix_convert(directory,conn,0,&bad_path,&sbuf);
3961 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3963 if (check_name(directory,conn))
3964 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3967 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3968 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
3971 /* Realloc the parameter and data sizes */
3972 params = SMB_REALLOC(*pparams,2);
3974 return ERROR_DOS(ERRDOS,ERRnomem);
3979 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3984 /****************************************************************************
3985 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3986 We don't actually do this - we just send a null response.
3987 ****************************************************************************/
3989 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3990 char **pparams, int total_params, char **ppdata, int total_data,
3991 unsigned int max_data_bytes)
3993 static uint16 fnf_handle = 257;
3994 char *params = *pparams;
3997 if (total_params < 6)
3998 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4000 info_level = SVAL(params,4);
4001 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4003 switch (info_level) {
4008 return ERROR_DOS(ERRDOS,ERRunknownlevel);
4011 /* Realloc the parameter and data sizes */
4012 params = SMB_REALLOC(*pparams,6);
4014 return ERROR_DOS(ERRDOS,ERRnomem);
4017 SSVAL(params,0,fnf_handle);
4018 SSVAL(params,2,0); /* No changes */
4019 SSVAL(params,4,0); /* No EA errors */
4026 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4031 /****************************************************************************
4032 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4033 changes). Currently this does nothing.
4034 ****************************************************************************/
4036 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4037 char **pparams, int total_params, char **ppdata, int total_data,
4038 unsigned int max_data_bytes)
4040 char *params = *pparams;
4042 DEBUG(3,("call_trans2findnotifynext\n"));
4044 /* Realloc the parameter and data sizes */
4045 params = SMB_REALLOC(*pparams,4);
4047 return ERROR_DOS(ERRDOS,ERRnomem);
4050 SSVAL(params,0,0); /* No changes */
4051 SSVAL(params,2,0); /* No EA errors */
4053 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4058 /****************************************************************************
4059 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4060 ****************************************************************************/
4062 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4063 char **pparams, int total_params, char **ppdata, int total_data,
4064 unsigned int max_data_bytes)
4066 char *params = *pparams;
4069 int max_referral_level;
4071 DEBUG(10,("call_trans2getdfsreferral\n"));
4073 if (total_params < 2)
4074 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4076 max_referral_level = SVAL(params,0);
4078 if(!lp_host_msdfs())
4079 return ERROR_DOS(ERRDOS,ERRbadfunc);
4081 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
4082 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4083 return UNIXERROR(ERRDOS,ERRbadfile);
4085 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4086 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4091 #define LMCAT_SPL 0x53
4092 #define LMFUNC_GETJOBID 0x60
4094 /****************************************************************************
4095 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4096 ****************************************************************************/
4098 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4099 char **pparams, int total_params, char **ppdata, int total_data,
4100 unsigned int max_data_bytes)
4102 char *pdata = *ppdata;
4103 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4105 /* check for an invalid fid before proceeding */
4108 return(ERROR_DOS(ERRDOS,ERRbadfid));
4110 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4111 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4112 pdata = SMB_REALLOC(*ppdata, 32);
4114 return ERROR_DOS(ERRDOS,ERRnomem);
4117 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4118 CAN ACCEPT THIS IN UNICODE. JRA. */
4120 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
4121 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4122 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4123 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4126 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4127 return ERROR_DOS(ERRSRV,ERRerror);
4131 /****************************************************************************
4132 Reply to a SMBfindclose (stop trans2 directory search).
4133 ****************************************************************************/
4135 int reply_findclose(connection_struct *conn,
4136 char *inbuf,char *outbuf,int length,int bufsize)
4139 int dptr_num=SVALS(inbuf,smb_vwv0);
4140 START_PROFILE(SMBfindclose);
4142 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4144 dptr_close(&dptr_num);
4146 outsize = set_message(outbuf,0,0,True);
4148 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4150 END_PROFILE(SMBfindclose);
4154 /****************************************************************************
4155 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4156 ****************************************************************************/
4158 int reply_findnclose(connection_struct *conn,
4159 char *inbuf,char *outbuf,int length,int bufsize)
4163 START_PROFILE(SMBfindnclose);
4165 dptr_num = SVAL(inbuf,smb_vwv0);
4167 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4169 /* We never give out valid handles for a
4170 findnotifyfirst - so any dptr_num is ok here.
4173 outsize = set_message(outbuf,0,0,True);
4175 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4177 END_PROFILE(SMBfindnclose);
4181 /****************************************************************************
4182 Reply to a SMBtranss2 - just ignore it!
4183 ****************************************************************************/
4185 int reply_transs2(connection_struct *conn,
4186 char *inbuf,char *outbuf,int length,int bufsize)
4188 START_PROFILE(SMBtranss2);
4189 DEBUG(4,("Ignoring transs2 of length %d\n",length));
4190 END_PROFILE(SMBtranss2);
4194 /****************************************************************************
4195 Reply to a SMBtrans2.
4196 ****************************************************************************/
4198 int reply_trans2(connection_struct *conn,
4199 char *inbuf,char *outbuf,int length,int bufsize)
4202 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4203 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4204 unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4206 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4207 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4208 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4209 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4210 int32 timeout = IVALS(inbuf,smb_timeout);
4212 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4213 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4214 char *params = NULL, *data = NULL;
4215 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4216 START_PROFILE(SMBtrans2);
4218 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4219 /* Queue this open message as we are the process of an
4222 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4223 DEBUGADD(2,( "in oplock break state.\n"));
4225 push_oplock_pending_smb_message(inbuf, length);
4226 END_PROFILE(SMBtrans2);
4230 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4231 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4232 END_PROFILE(SMBtrans2);
4233 return ERROR_DOS(ERRSRV,ERRaccess);
4236 outsize = set_message(outbuf,0,0,True);
4238 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4239 is so as a sanity check */
4242 * Need to have rc=0 for ioctl to get job id for OS/2.
4243 * Network printing will fail if function is not successful.
4244 * Similar function in reply.c will be used if protocol
4245 * is LANMAN1.0 instead of LM1.2X002.
4246 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4247 * outbuf doesn't have to be set(only job id is used).
4249 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4250 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4251 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4252 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4254 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4255 DEBUG(2,("Transaction is %d\n",tran_call));
4256 END_PROFILE(SMBtrans2);
4257 ERROR_DOS(ERRDOS,ERRinvalidparam);
4261 /* Allocate the space for the maximum needed parameters and data */
4262 if (total_params > 0)
4263 params = (char *)SMB_MALLOC(total_params);
4265 data = (char *)SMB_MALLOC(total_data);
4267 if ((total_params && !params) || (total_data && !data)) {
4268 DEBUG(2,("Out of memory in reply_trans2\n"));
4271 END_PROFILE(SMBtrans2);
4272 return ERROR_DOS(ERRDOS,ERRnomem);
4275 /* Copy the param and data bytes sent with this request into
4276 the params buffer */
4277 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4278 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4280 if (num_params > total_params || num_data > total_data)
4281 exit_server("invalid params in reply_trans2");
4284 unsigned int psoff = SVAL(inbuf, smb_psoff);
4285 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4287 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4288 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4290 memcpy( params, smb_base(inbuf) + psoff, num_params);
4293 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4294 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4296 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4297 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4299 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4302 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4304 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4305 /* We need to send an interim response then receive the rest
4306 of the parameter/data bytes */
4307 outsize = set_message(outbuf,0,0,True);
4308 srv_signing_trans_stop();
4309 if (!send_smb(smbd_server_fd(),outbuf))
4310 exit_server("reply_trans2: send_smb failed.");
4312 while (num_data_sofar < total_data ||
4313 num_params_sofar < total_params) {
4315 unsigned int param_disp;
4316 unsigned int param_off;
4317 unsigned int data_disp;
4318 unsigned int data_off;
4320 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4323 * The sequence number for the trans reply is always
4324 * based on the last secondary received.
4327 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4330 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4331 outsize = set_message(outbuf,0,0,True);
4333 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4335 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4336 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4340 /* Revise total_params and total_data in case
4341 they have changed downwards */
4342 if (SVAL(inbuf, smb_tpscnt) < total_params)
4343 total_params = SVAL(inbuf, smb_tpscnt);
4344 if (SVAL(inbuf, smb_tdscnt) < total_data)
4345 total_data = SVAL(inbuf, smb_tdscnt);
4347 num_params = SVAL(inbuf,smb_spscnt);
4348 param_off = SVAL(inbuf, smb_spsoff);
4349 param_disp = SVAL(inbuf, smb_spsdisp);
4350 num_params_sofar += num_params;
4352 num_data = SVAL(inbuf, smb_sdscnt);
4353 data_off = SVAL(inbuf, smb_sdsoff);
4354 data_disp = SVAL(inbuf, smb_sdsdisp);
4355 num_data_sofar += num_data;
4357 if (num_params_sofar > total_params || num_data_sofar > total_data)
4361 if (param_disp + num_params > total_params)
4363 if ((param_disp + num_params < param_disp) ||
4364 (param_disp + num_params < num_params))
4366 if (param_disp > total_params)
4368 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4369 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4371 if (params + param_disp < params)
4374 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
4377 if (data_disp + num_data > total_data)
4379 if ((data_disp + num_data < data_disp) ||
4380 (data_disp + num_data < num_data))
4382 if (data_disp > total_data)
4384 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4385 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4387 if (data + data_disp < data)
4390 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4395 if (Protocol >= PROTOCOL_NT1) {
4396 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4399 /* Now we must call the relevant TRANS2 function */
4401 case TRANSACT2_OPEN:
4402 START_PROFILE_NESTED(Trans2_open);
4403 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4404 ¶ms, total_params, &data, total_data, max_data_bytes);
4405 END_PROFILE_NESTED(Trans2_open);
4408 case TRANSACT2_FINDFIRST:
4409 START_PROFILE_NESTED(Trans2_findfirst);
4410 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4411 ¶ms, total_params, &data, total_data, max_data_bytes);
4412 END_PROFILE_NESTED(Trans2_findfirst);
4415 case TRANSACT2_FINDNEXT:
4416 START_PROFILE_NESTED(Trans2_findnext);
4417 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4418 ¶ms, total_params, &data, total_data, max_data_bytes);
4419 END_PROFILE_NESTED(Trans2_findnext);
4422 case TRANSACT2_QFSINFO:
4423 START_PROFILE_NESTED(Trans2_qfsinfo);
4424 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4425 ¶ms, total_params, &data, total_data, max_data_bytes);
4426 END_PROFILE_NESTED(Trans2_qfsinfo);
4429 #ifdef HAVE_SYS_QUOTAS
4430 case TRANSACT2_SETFSINFO:
4431 START_PROFILE_NESTED(Trans2_setfsinfo);
4432 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4433 ¶ms, total_params, &data, total_data, max_data_bytes);
4434 END_PROFILE_NESTED(Trans2_setfsinfo);
4437 case TRANSACT2_QPATHINFO:
4438 case TRANSACT2_QFILEINFO:
4439 START_PROFILE_NESTED(Trans2_qpathinfo);
4440 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4441 ¶ms, total_params, &data, total_data, max_data_bytes);
4442 END_PROFILE_NESTED(Trans2_qpathinfo);
4444 case TRANSACT2_SETPATHINFO:
4445 case TRANSACT2_SETFILEINFO:
4446 START_PROFILE_NESTED(Trans2_setpathinfo);
4447 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4448 ¶ms, total_params, &data, total_data, max_data_bytes);
4449 END_PROFILE_NESTED(Trans2_setpathinfo);
4452 case TRANSACT2_FINDNOTIFYFIRST:
4453 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4454 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4455 ¶ms, total_params, &data, total_data, max_data_bytes);
4456 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4459 case TRANSACT2_FINDNOTIFYNEXT:
4460 START_PROFILE_NESTED(Trans2_findnotifynext);
4461 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4462 ¶ms, total_params, &data, total_data, max_data_bytes);
4463 END_PROFILE_NESTED(Trans2_findnotifynext);
4465 case TRANSACT2_MKDIR:
4466 START_PROFILE_NESTED(Trans2_mkdir);
4467 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4468 ¶ms, total_params, &data, total_data, max_data_bytes);
4469 END_PROFILE_NESTED(Trans2_mkdir);
4472 case TRANSACT2_GET_DFS_REFERRAL:
4473 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4474 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4475 ¶ms, total_params, &data, total_data, max_data_bytes);
4476 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4478 case TRANSACT2_IOCTL:
4479 START_PROFILE_NESTED(Trans2_ioctl);
4480 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4481 ¶ms, total_params, &data, total_data, max_data_bytes);
4482 END_PROFILE_NESTED(Trans2_ioctl);
4485 /* Error in request */
4486 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4489 END_PROFILE(SMBtrans2);
4490 srv_signing_trans_stop();
4491 return ERROR_DOS(ERRSRV,ERRerror);
4494 /* As we do not know how many data packets will need to be
4495 returned here the various call_trans2xxxx calls
4496 must send their own. Thus a call_trans2xxx routine only
4497 returns a value other than -1 when it wants to send
4501 srv_signing_trans_stop();
4505 END_PROFILE(SMBtrans2);
4506 return outsize; /* If a correct response was needed the
4507 call_trans2xxx calls have already sent
4508 it. If outsize != -1 then it is returning */
4512 srv_signing_trans_stop();
4515 END_PROFILE(SMBtrans2);
4516 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);