2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2003
5 Copyright (C) Stefan (metze) Metzmacher 2003
7 Extensively modified by Andrew Tridgell, 1995
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 extern int smb_read_error;
28 extern fstring local_machine;
29 extern int global_oplock_break;
30 extern uint32 global_client_caps;
31 extern struct current_user current_user;
33 #define get_file_size(sbuf) ((sbuf).st_size)
35 /* given a stat buffer return the allocated size on disk, taking into
36 account sparse files */
37 SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
40 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
41 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
43 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
45 if (!ret && fsp && fsp->initial_allocation_size)
46 ret = fsp->initial_allocation_size;
47 ret = SMB_ROUNDUP(ret,SMB_ROUNDUP_ALLOCATION_SIZE);
51 /****************************************************************************
52 Utility functions for dealing with extended attributes.
53 ****************************************************************************/
55 static const char *prohibited_ea_names[] = {
56 SAMBA_POSIX_INHERITANCE_EA_NAME,
57 SAMBA_XATTR_DOS_ATTRIB,
61 /****************************************************************************
62 Refuse to allow clients to overwrite our private xattrs.
63 ****************************************************************************/
65 static BOOL samba_private_attr_name(const char *unix_ea_name)
69 for (i = 0; prohibited_ea_names[i]; i++) {
70 if (strequal( prohibited_ea_names[i], unix_ea_name))
77 struct ea_list *next, *prev;
81 /****************************************************************************
82 Get one EA value. Fill in a struct ea_struct.
83 ****************************************************************************/
85 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
86 const char *fname, char *ea_name, struct ea_struct *pea)
88 /* Get the value of this xattr. Max size is 64k. */
89 size_t attr_size = 256;
95 val = talloc_realloc(mem_ctx, val, attr_size);
100 if (fsp && fsp->fd != -1) {
101 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
103 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
106 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
115 DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
116 dump_data(10, val, sizeret);
119 if (strnequal(ea_name, "user.", 5)) {
120 pea->name = &ea_name[5];
124 pea->value.data = val;
125 pea->value.length = (size_t)sizeret;
129 /****************************************************************************
130 Return a linked list of the total EA's. Plus the total size
131 ****************************************************************************/
133 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)
135 /* Get a list of all xattrs. Max namesize is 64k. */
136 size_t ea_namelist_size = 1024;
141 struct ea_list *ea_list_head = NULL;
145 if (!lp_ea_support(SNUM(conn))) {
149 for (i = 0, ea_namelist = talloc(mem_ctx, ea_namelist_size); i < 6;
150 ea_namelist = talloc_realloc(mem_ctx, ea_namelist, ea_namelist_size), i++) {
151 if (fsp && fsp->fd != -1) {
152 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
154 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
157 if (sizeret == -1 && errno == ERANGE) {
158 ea_namelist_size *= 2;
167 DEBUG(10,("get_ea_list: ea_namelist size = %d\n", sizeret ));
170 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
171 struct ea_list *listp, *tmp;
173 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
176 listp = talloc(mem_ctx, sizeof(struct ea_list));
180 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
186 push_ascii_fstring(dos_ea_name, listp->ea.name);
187 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
188 DEBUG(10,("get_ea_list: total_len = %u, %s, val len = %u\n",
189 *pea_total_len, dos_ea_name,
190 (unsigned int)listp->ea.value.length ));
192 DLIST_ADD_END(ea_list_head, listp, tmp);
194 /* Add on 4 for total length. */
195 if (*pea_total_len) {
200 DEBUG(10,("get_ea_list: total_len = %u\n", *pea_total_len));
204 /****************************************************************************
205 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
207 ****************************************************************************/
209 static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size,
210 connection_struct *conn, files_struct *fsp, const char *fname)
212 unsigned int ret_data_size = 4;
216 struct ea_list *ea_list;
218 SMB_ASSERT(total_data_size >= 4);
221 if (!lp_ea_support(SNUM(conn))) {
224 mem_ctx = talloc_init("fill_ea_buffer");
229 ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
231 talloc_destroy(mem_ctx);
235 if (total_ea_len > total_data_size) {
236 talloc_destroy(mem_ctx);
240 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
243 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
244 dos_namelen = strlen(dos_ea_name);
245 if (dos_namelen > 255 || dos_namelen == 0) {
248 if (ea_list->ea.value.length > 65535) {
251 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
255 /* We know we have room. */
256 SCVAL(p,0,ea_list->ea.flags);
257 SCVAL(p,1,dos_namelen);
258 SSVAL(p,2,ea_list->ea.value.length);
259 fstrcpy(p+4, dos_ea_name);
260 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
262 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
263 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
266 ret_data_size = PTR_DIFF(p, pdata);
267 DEBUG(10,("fill_ea_buffer: data_size = %u, total_ea_len = %u\n",
268 ret_data_size, total_ea_len ));
269 talloc_destroy(mem_ctx);
270 SIVAL(pdata,0,ret_data_size);
271 return ret_data_size;
274 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
276 size_t total_ea_len = 0;
277 TALLOC_CTX *mem_ctx = NULL;
279 if (!lp_ea_support(SNUM(conn))) {
282 mem_ctx = talloc_init("estimate_ea_size");
283 (void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
284 talloc_destroy(mem_ctx);
288 /****************************************************************************
289 Ensure the EA name is case insensitive by matching any existing EA name.
290 ****************************************************************************/
292 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
295 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
296 struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
298 for (; ea_list; ea_list = ea_list->next) {
299 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
300 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
301 &unix_ea_name[5], ea_list->ea.name));
302 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
306 talloc_destroy(mem_ctx);
309 /****************************************************************************
310 Set or delete an extended attribute.
311 ****************************************************************************/
313 static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname,
314 char *pdata, int total_data)
316 unsigned int namelen;
319 fstring unix_ea_name;
321 if (!lp_ea_support(SNUM(conn))) {
322 return NT_STATUS_EAS_NOT_SUPPORTED;
325 if (total_data < 8) {
326 return NT_STATUS_INVALID_PARAMETER;
329 if (IVAL(pdata,0) > total_data) {
330 DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data));
331 return NT_STATUS_INVALID_PARAMETER;
335 namelen = CVAL(pdata,1);
336 ealen = SVAL(pdata,2);
338 if (total_data < 8 + namelen + 1 + ealen) {
339 DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n",
340 (unsigned int)total_data, namelen, ealen));
341 return NT_STATUS_INVALID_PARAMETER;
344 if (pdata[namelen] != '\0') {
345 DEBUG(10,("set_ea: ea name not null terminated\n"));
346 return NT_STATUS_INVALID_PARAMETER;
349 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
350 pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE);
351 pdata += (namelen + 1);
353 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
355 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen));
357 DEBUG(10,("set_ea: data :\n"));
358 dump_data(10, pdata, ealen);
361 if (samba_private_attr_name(unix_ea_name)) {
362 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
363 return NT_STATUS_ACCESS_DENIED;
367 /* Remove the attribute. */
368 if (fsp && (fsp->fd != -1)) {
369 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
370 unix_ea_name, fsp->fsp_name));
371 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
373 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
374 unix_ea_name, fname));
375 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
378 /* Removing a non existent attribute always succeeds. */
379 if (ret == -1 && errno == ENOATTR) {
380 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name));
385 if (fsp && (fsp->fd != -1)) {
386 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
387 unix_ea_name, fsp->fsp_name));
388 ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0);
390 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
391 unix_ea_name, fname));
392 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0);
398 if (errno == ENOTSUP) {
399 return NT_STATUS_EAS_NOT_SUPPORTED;
402 return map_nt_error_from_unix(errno);
408 /****************************************************************************
409 Send the required number of replies back.
410 We assume all fields other than the data fields are
411 set correctly for the type of call.
412 HACK ! Always assumes smb_setup field is zero.
413 ****************************************************************************/
415 static int send_trans2_replies(char *outbuf,
422 /* As we are using a protocol > LANMAN1 then the max_send
423 variable must have been set in the sessetupX call.
424 This takes precedence over the max_xmit field in the
425 global struct. These different max_xmit variables should
426 be merged as this is now too confusing */
429 int data_to_send = datasize;
430 int params_to_send = paramsize;
434 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
435 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
436 int data_alignment_offset = 0;
438 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
440 set_message(outbuf,10,0,True);
442 /* If there genuinely are no parameters or data to send just send the empty packet */
444 if(params_to_send == 0 && data_to_send == 0) {
445 if (!send_smb(smbd_server_fd(),outbuf))
446 exit_server("send_trans2_replies: send_smb failed.");
450 /* When sending params and data ensure that both are nicely aligned */
451 /* Only do this alignment when there is also data to send - else
452 can cause NT redirector problems. */
454 if (((params_to_send % 4) != 0) && (data_to_send != 0))
455 data_alignment_offset = 4 - (params_to_send % 4);
457 /* Space is bufsize minus Netbios over TCP header minus SMB header */
458 /* The alignment_offset is to align the param bytes on an even byte
459 boundary. NT 4.0 Beta needs this to work correctly. */
461 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
463 /* useable_space can never be more than max_send minus the alignment offset. */
465 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
467 while (params_to_send || data_to_send) {
468 /* Calculate whether we will totally or partially fill this packet */
470 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
472 /* We can never send more than useable_space */
474 * Note that 'useable_space' does not include the alignment offsets,
475 * but we must include the alignment offsets in the calculation of
476 * the length of the data we send over the wire, as the alignment offsets
477 * are sent here. Fix from Marc_Jacobsen@hp.com.
480 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
482 set_message(outbuf, 10, total_sent_thistime, True);
484 /* Set total params and data to be sent */
485 SSVAL(outbuf,smb_tprcnt,paramsize);
486 SSVAL(outbuf,smb_tdrcnt,datasize);
488 /* Calculate how many parameters and data we can fit into
489 * this packet. Parameters get precedence
492 params_sent_thistime = MIN(params_to_send,useable_space);
493 data_sent_thistime = useable_space - params_sent_thistime;
494 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
496 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
498 /* smb_proff is the offset from the start of the SMB header to the
499 parameter bytes, however the first 4 bytes of outbuf are
500 the Netbios over TCP header. Thus use smb_base() to subtract
501 them from the calculation */
503 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
505 if(params_sent_thistime == 0)
506 SSVAL(outbuf,smb_prdisp,0);
508 /* Absolute displacement of param bytes sent in this packet */
509 SSVAL(outbuf,smb_prdisp,pp - params);
511 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
512 if(data_sent_thistime == 0) {
513 SSVAL(outbuf,smb_droff,0);
514 SSVAL(outbuf,smb_drdisp, 0);
516 /* The offset of the data bytes is the offset of the
517 parameter bytes plus the number of parameters being sent this time */
518 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
519 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
520 SSVAL(outbuf,smb_drdisp, pd - pdata);
523 /* Copy the param bytes into the packet */
525 if(params_sent_thistime)
526 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
528 /* Copy in the data bytes */
529 if(data_sent_thistime)
530 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
531 data_alignment_offset,pd,data_sent_thistime);
533 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
534 params_sent_thistime, data_sent_thistime, useable_space));
535 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
536 params_to_send, data_to_send, paramsize, datasize));
538 /* Send the packet */
539 if (!send_smb(smbd_server_fd(),outbuf))
540 exit_server("send_trans2_replies: send_smb failed.");
542 pp += params_sent_thistime;
543 pd += data_sent_thistime;
545 params_to_send -= params_sent_thistime;
546 data_to_send -= data_sent_thistime;
549 if(params_to_send < 0 || data_to_send < 0) {
550 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
551 params_to_send, data_to_send));
559 /****************************************************************************
560 Reply to a TRANSACT2_OPEN.
561 ****************************************************************************/
563 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
564 char **pparams, int total_params, char **ppdata, int total_data)
566 char *params = *pparams;
571 BOOL return_additional_info;
580 int fmode=0,mtime=0,rmode;
582 SMB_STRUCT_STAT sbuf;
584 BOOL bad_path = False;
589 * Ensure we have enough parameters to perform the operation.
592 if (total_params < 29)
593 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
595 open_mode = SVAL(params, 2);
596 open_attr = SVAL(params,6);
597 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
599 return_additional_info = BITSETW(params,0);
600 open_sattr = SVAL(params, 4);
601 open_time = make_unix_date3(params+8);
603 open_ofun = SVAL(params,12);
604 open_size = IVAL(params,14);
608 return(ERROR_DOS(ERRSRV,ERRaccess));
610 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);
611 if (!NT_STATUS_IS_OK(status)) {
612 return ERROR_NT(status);
615 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
616 fname,open_mode, open_attr, open_ofun, open_size));
618 /* XXXX we need to handle passed times, sattr and flags */
620 unix_convert(fname,conn,0,&bad_path,&sbuf);
622 if (!check_name(fname,conn)) {
623 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
626 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
627 oplock_request, &rmode,&smb_action);
630 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
633 size = get_file_size(sbuf);
634 fmode = dos_mode(conn,fname,&sbuf);
635 mtime = sbuf.st_mtime;
638 close_file(fsp,False);
639 return(ERROR_DOS(ERRDOS,ERRnoaccess));
642 /* Realloc the size of parameters and data we will return */
643 params = Realloc(*pparams, 28);
645 return(ERROR_DOS(ERRDOS,ERRnomem));
648 memset((char *)params,'\0',28);
649 SSVAL(params,0,fsp->fnum);
650 SSVAL(params,2,fmode);
651 put_dos_date2(params,4, mtime);
652 SIVAL(params,8, (uint32)size);
653 SSVAL(params,12,rmode);
655 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
656 smb_action |= EXTENDED_OPLOCK_GRANTED;
658 SSVAL(params,18,smb_action);
661 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
663 SIVAL(params,20,inode);
665 /* Send the required number of replies */
666 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
671 /*********************************************************
672 Routine to check if a given string matches exactly.
673 as a special case a mask of "." does NOT match. That
674 is required for correct wildcard semantics
675 Case can be significant or not.
676 **********************************************************/
678 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
680 if (mask[0] == '.' && mask[1] == 0)
683 return strcmp(str,mask)==0;
684 if (StrCaseCmp(str,mask) != 0) {
687 if (ms_has_wild(str)) {
693 /****************************************************************************
694 Return the filetype for UNIX extensions.
695 ****************************************************************************/
697 static uint32 unix_filetype(mode_t mode)
700 return UNIX_TYPE_FILE;
701 else if(S_ISDIR(mode))
702 return UNIX_TYPE_DIR;
704 else if(S_ISLNK(mode))
705 return UNIX_TYPE_SYMLINK;
708 else if(S_ISCHR(mode))
709 return UNIX_TYPE_CHARDEV;
712 else if(S_ISBLK(mode))
713 return UNIX_TYPE_BLKDEV;
716 else if(S_ISFIFO(mode))
717 return UNIX_TYPE_FIFO;
720 else if(S_ISSOCK(mode))
721 return UNIX_TYPE_SOCKET;
724 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
725 return UNIX_TYPE_UNKNOWN;
728 /****************************************************************************
729 Return the major devicenumber for UNIX extensions.
730 ****************************************************************************/
732 static uint32 unix_dev_major(SMB_DEV_T dev)
734 #if defined(HAVE_DEVICE_MAJOR_FN)
735 return (uint32)major(dev);
737 return (uint32)(dev >> 8);
741 /****************************************************************************
742 Return the minor devicenumber for UNIX extensions.
743 ****************************************************************************/
745 static uint32 unix_dev_minor(SMB_DEV_T dev)
747 #if defined(HAVE_DEVICE_MINOR_FN)
748 return (uint32)minor(dev);
750 return (uint32)(dev & 0xff);
754 /****************************************************************************
755 Map wire perms onto standard UNIX permissions. Obey share restrictions.
756 ****************************************************************************/
758 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
762 if (perms == SMB_MODE_NO_CHANGE)
765 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
766 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
767 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
768 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
769 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
770 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
771 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
772 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
773 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
775 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
778 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
781 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
784 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
785 ret &= lp_dir_mask(SNUM(conn));
786 /* Add in force bits */
787 ret |= lp_force_dir_mode(SNUM(conn));
789 /* Apply mode mask */
790 ret &= lp_create_mask(SNUM(conn));
791 /* Add in force bits */
792 ret |= lp_force_create_mode(SNUM(conn));
798 /****************************************************************************
799 Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
800 ****************************************************************************/
802 time_t interpret_long_unix_date(char *p)
804 DEBUG(10,("interpret_long_unix_date\n"));
805 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
806 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
809 return interpret_long_date(p);
813 /****************************************************************************
814 Get a level dependent lanman2 dir entry.
815 ****************************************************************************/
817 static BOOL get_lanman2_dir_entry(connection_struct *conn,
818 void *inbuf, void *outbuf,
819 char *path_mask,int dirtype,int info_level,
820 int requires_resume_key,
821 BOOL dont_descend,char **ppdata,
822 char *base_data, int space_remaining,
823 BOOL *out_of_space, BOOL *got_exact_match,
828 SMB_STRUCT_STAT sbuf;
832 char *p, *q, *pdata = *ppdata;
836 SMB_OFF_T file_size = 0;
837 SMB_BIG_UINT allocation_size = 0;
839 time_t mdate=0, adate=0, cdate=0;
842 int nt_extmode; /* Used for NT connections instead of mode */
843 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
846 *out_of_space = False;
847 *got_exact_match = False;
852 p = strrchr_m(path_mask,'/');
859 pstrcpy(mask, path_mask);
864 /* Needed if we run out of space */
865 prev_dirpos = TellDir(conn->dirptr);
866 dname = ReadDirName(conn->dirptr);
869 * Due to bugs in NT client redirectors we are not using
870 * resume keys any more - set them to zero.
871 * Check out the related comments in findfirst/findnext.
877 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
878 (long)conn->dirptr,TellDir(conn->dirptr)));
883 pstrcpy(fname,dname);
885 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
886 got_match = mask_match(fname, mask, conn->case_sensitive);
888 if(!got_match && !mangle_is_8_3(fname, False)) {
891 * It turns out that NT matches wildcards against
892 * both long *and* short names. This may explain some
893 * of the wildcard wierdness from old DOS clients
894 * that some people have been seeing.... JRA.
898 pstrcpy( newname, fname);
899 mangle_map( newname, True, False, SNUM(conn));
900 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
901 got_match = mask_match(newname, mask, conn->case_sensitive);
905 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
906 if (dont_descend && !isdots)
909 pstrcpy(pathreal,conn->dirpath);
911 pstrcat(pathreal,"/");
912 pstrcat(pathreal,dname);
914 if (INFO_LEVEL_IS_UNIX(info_level)) {
915 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
916 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
917 pathreal,strerror(errno)));
920 } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
922 /* Needed to show the msdfs symlinks as
925 if(lp_host_msdfs() &&
926 lp_msdfs_root(SNUM(conn)) &&
927 is_msdfs_link(conn, pathreal, NULL, NULL,
930 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
931 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
935 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
936 pathreal,strerror(errno)));
941 mode = dos_mode(conn,pathreal,&sbuf);
943 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
944 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
948 file_size = get_file_size(sbuf);
949 allocation_size = get_allocation_size(NULL,&sbuf);
950 mdate = sbuf.st_mtime;
951 adate = sbuf.st_atime;
952 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
954 if (lp_dos_filetime_resolution(SNUM(conn))) {
963 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
969 mangle_map(fname,False,True,SNUM(conn));
974 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
976 switch (info_level) {
977 case SMB_INFO_STANDARD:
978 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_STANDARD\n"));
979 if(requires_resume_key) {
983 put_dos_date2(p,l1_fdateCreation,cdate);
984 put_dos_date2(p,l1_fdateLastAccess,adate);
985 put_dos_date2(p,l1_fdateLastWrite,mdate);
986 SIVAL(p,l1_cbFile,(uint32)file_size);
987 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
988 SSVAL(p,l1_attrFile,mode);
991 p += align_string(outbuf, p, 0);
992 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
993 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
995 SCVAL(nameptr, -1, len - 2);
997 SCVAL(nameptr, -1, 0);
1001 SCVAL(nameptr, -1, len - 1);
1003 SCVAL(nameptr, -1, 0);
1009 case SMB_INFO_QUERY_EA_SIZE:
1010 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_QUERY_EA_SIZE\n"));
1011 if(requires_resume_key) {
1015 put_dos_date2(p,l2_fdateCreation,cdate);
1016 put_dos_date2(p,l2_fdateLastAccess,adate);
1017 put_dos_date2(p,l2_fdateLastWrite,mdate);
1018 SIVAL(p,l2_cbFile,(uint32)file_size);
1019 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1020 SSVAL(p,l2_attrFile,mode);
1022 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1023 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1027 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1028 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1041 SCVAL(nameptr,0,len);
1043 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1046 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1047 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1048 was_8_3 = mangle_is_8_3(fname, True);
1050 SIVAL(p,0,reskey); p += 4;
1051 put_long_date(p,cdate); p += 8;
1052 put_long_date(p,adate); p += 8;
1053 put_long_date(p,mdate); p += 8;
1054 put_long_date(p,mdate); p += 8;
1055 SOFF_T(p,0,file_size); p += 8;
1056 SOFF_T(p,0,allocation_size); p += 8;
1057 SIVAL(p,0,nt_extmode); p += 4;
1058 q = p; p += 4; /* q is placeholder for name length. */
1060 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1061 SIVAL(p,0,ea_size); /* Extended attributes */
1064 /* Clear the short name buffer. This is
1065 * IMPORTANT as not doing so will trigger
1066 * a Win2k client bug. JRA.
1069 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1070 pstring mangled_name;
1071 pstrcpy(mangled_name, fname);
1072 mangle_map(mangled_name,True,True,SNUM(conn));
1073 mangled_name[12] = 0;
1074 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1081 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1084 len = PTR_DIFF(p, pdata);
1085 len = (len + 3) & ~3;
1090 case SMB_FIND_FILE_DIRECTORY_INFO:
1091 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1093 SIVAL(p,0,reskey); p += 4;
1094 put_long_date(p,cdate); p += 8;
1095 put_long_date(p,adate); p += 8;
1096 put_long_date(p,mdate); p += 8;
1097 put_long_date(p,mdate); p += 8;
1098 SOFF_T(p,0,file_size); p += 8;
1099 SOFF_T(p,0,allocation_size); p += 8;
1100 SIVAL(p,0,nt_extmode); p += 4;
1101 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1104 len = PTR_DIFF(p, pdata);
1105 len = (len + 3) & ~3;
1110 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1111 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1113 SIVAL(p,0,reskey); p += 4;
1114 put_long_date(p,cdate); p += 8;
1115 put_long_date(p,adate); p += 8;
1116 put_long_date(p,mdate); p += 8;
1117 put_long_date(p,mdate); p += 8;
1118 SOFF_T(p,0,file_size); p += 8;
1119 SOFF_T(p,0,allocation_size); p += 8;
1120 SIVAL(p,0,nt_extmode); p += 4;
1121 q = p; p += 4; /* q is placeholder for name length. */
1123 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1124 SIVAL(p,0,ea_size); /* Extended attributes */
1127 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1131 len = PTR_DIFF(p, pdata);
1132 len = (len + 3) & ~3;
1137 case SMB_FIND_FILE_NAMES_INFO:
1138 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1140 SIVAL(p,0,reskey); p += 4;
1142 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1143 acl on a dir (tridge) */
1144 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1147 len = PTR_DIFF(p, pdata);
1148 len = (len + 3) & ~3;
1153 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1154 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1156 SIVAL(p,0,reskey); p += 4;
1157 put_long_date(p,cdate); p += 8;
1158 put_long_date(p,adate); p += 8;
1159 put_long_date(p,mdate); p += 8;
1160 put_long_date(p,mdate); p += 8;
1161 SOFF_T(p,0,file_size); p += 8;
1162 SOFF_T(p,0,allocation_size); p += 8;
1163 SIVAL(p,0,nt_extmode); p += 4;
1164 q = p; p += 4; /* q is placeholder for name length. */
1166 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1167 SIVAL(p,0,ea_size); /* Extended attributes */
1170 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1171 SIVAL(p,0,sbuf.st_dev); p += 4;
1172 SIVAL(p,0,sbuf.st_ino); p += 4;
1173 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1176 len = PTR_DIFF(p, pdata);
1177 len = (len + 3) & ~3;
1182 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1183 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1184 was_8_3 = mangle_is_8_3(fname, True);
1186 SIVAL(p,0,reskey); p += 4;
1187 put_long_date(p,cdate); p += 8;
1188 put_long_date(p,adate); p += 8;
1189 put_long_date(p,mdate); p += 8;
1190 put_long_date(p,mdate); p += 8;
1191 SOFF_T(p,0,file_size); p += 8;
1192 SOFF_T(p,0,allocation_size); p += 8;
1193 SIVAL(p,0,nt_extmode); p += 4;
1194 q = p; p += 4; /* q is placeholder for name length */
1196 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1197 SIVAL(p,0,ea_size); /* Extended attributes */
1200 /* Clear the short name buffer. This is
1201 * IMPORTANT as not doing so will trigger
1202 * a Win2k client bug. JRA.
1205 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1206 pstring mangled_name;
1207 pstrcpy(mangled_name, fname);
1208 mangle_map(mangled_name,True,True,SNUM(conn));
1209 mangled_name[12] = 0;
1210 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1217 SSVAL(p,0,0); p += 2; /* Reserved ? */
1218 SIVAL(p,0,sbuf.st_dev); p += 4;
1219 SIVAL(p,0,sbuf.st_ino); p += 4;
1220 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1223 len = PTR_DIFF(p, pdata);
1224 len = (len + 3) & ~3;
1229 /* CIFS UNIX Extension. */
1231 case SMB_FIND_FILE_UNIX:
1232 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1234 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1236 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1237 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1240 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1243 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1244 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1245 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1248 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1252 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1256 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1259 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1263 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1267 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1270 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1274 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1278 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1281 len = PTR_DIFF(p, pdata);
1282 len = (len + 3) & ~3;
1283 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1285 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1294 if (PTR_DIFF(p,pdata) > space_remaining) {
1295 /* Move the dirptr back to prev_dirpos */
1296 SeekDir(conn->dirptr, prev_dirpos);
1297 *out_of_space = True;
1298 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1299 return False; /* Not finished - just out of space */
1302 /* Setup the last_filename pointer, as an offset from base_data */
1303 *last_name_off = PTR_DIFF(nameptr,base_data);
1304 /* Advance the data pointer to the next slot */
1310 /****************************************************************************
1311 Reply to a TRANS2_FINDFIRST.
1312 ****************************************************************************/
1314 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1315 char **pparams, int total_params, char **ppdata, int total_data)
1317 /* We must be careful here that we don't return more than the
1318 allowed number of data bytes. If this means returning fewer than
1319 maxentries then so be it. We assume that the redirector has
1320 enough room for the fixed number of parameter bytes it has
1322 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1323 char *params = *pparams;
1324 char *pdata = *ppdata;
1325 int dirtype = SVAL(params,0);
1326 int maxentries = SVAL(params,2);
1327 BOOL close_after_first = BITSETW(params+4,0);
1328 BOOL close_if_end = BITSETW(params+4,1);
1329 BOOL requires_resume_key = BITSETW(params+4,2);
1330 int info_level = SVAL(params,6);
1334 int last_name_off=0;
1338 BOOL finished = False;
1339 BOOL dont_descend = False;
1340 BOOL out_of_space = False;
1341 int space_remaining;
1342 BOOL bad_path = False;
1343 SMB_STRUCT_STAT sbuf;
1344 NTSTATUS ntstatus = NT_STATUS_OK;
1346 if (total_params < 12)
1347 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1349 *directory = *mask = 0;
1351 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1352 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1353 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1354 info_level, max_data_bytes));
1356 switch (info_level) {
1357 case SMB_INFO_STANDARD:
1358 case SMB_INFO_QUERY_EA_SIZE:
1359 case SMB_FIND_FILE_DIRECTORY_INFO:
1360 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1361 case SMB_FIND_FILE_NAMES_INFO:
1362 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1363 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1364 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1366 case SMB_FIND_FILE_UNIX:
1367 if (!lp_unix_extensions())
1368 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1371 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1374 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus);
1375 if (!NT_STATUS_IS_OK(ntstatus)) {
1376 return ERROR_NT(ntstatus);
1379 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
1381 unix_convert(directory,conn,0,&bad_path,&sbuf);
1382 if(!check_name(directory,conn)) {
1383 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1386 p = strrchr_m(directory,'/');
1388 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1389 if((directory[0] == '.') && (directory[1] == '\0'))
1392 pstrcpy(mask,directory);
1393 pstrcpy(directory,"./");
1399 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1401 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1403 return(ERROR_DOS(ERRDOS,ERRnomem));
1406 memset((char *)pdata,'\0',max_data_bytes + 1024);
1408 /* Realloc the params space */
1409 params = Realloc(*pparams, 10);
1411 return ERROR_DOS(ERRDOS,ERRnomem);
1414 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1416 return(UNIXERROR(ERRDOS,ERRbadfile));
1418 /* Save the wildcard match and attribs we are using on this directory -
1419 needed as lanman2 assumes these are being saved between calls */
1421 if(!(wcard = strdup(mask))) {
1422 dptr_close(&dptr_num);
1423 return ERROR_DOS(ERRDOS,ERRnomem);
1426 dptr_set_wcard(dptr_num, wcard);
1427 dptr_set_attr(dptr_num, dirtype);
1429 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
1431 /* We don't need to check for VOL here as this is returned by
1432 a different TRANS2 call. */
1434 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1435 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1436 dont_descend = True;
1439 space_remaining = max_data_bytes;
1440 out_of_space = False;
1442 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1443 BOOL got_exact_match = False;
1445 /* this is a heuristic to avoid seeking the dirptr except when
1446 absolutely necessary. It allows for a filename of about 40 chars */
1447 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1448 out_of_space = True;
1451 finished = !get_lanman2_dir_entry(conn,
1453 mask,dirtype,info_level,
1454 requires_resume_key,dont_descend,
1455 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1459 if (finished && out_of_space)
1462 if (!finished && !out_of_space)
1466 * As an optimisation if we know we aren't looking
1467 * for a wildcard name (ie. the name matches the wildcard exactly)
1468 * then we can finish on any (first) match.
1469 * This speeds up large directory searches. JRA.
1475 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1478 /* Check if we can close the dirptr */
1479 if(close_after_first || (finished && close_if_end)) {
1480 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1481 dptr_close(&dptr_num);
1485 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1486 * from observation of NT.
1489 if(numentries == 0) {
1490 dptr_close(&dptr_num);
1491 return ERROR_DOS(ERRDOS,ERRbadfile);
1494 /* At this point pdata points to numentries directory entries. */
1496 /* Set up the return parameter block */
1497 SSVAL(params,0,dptr_num);
1498 SSVAL(params,2,numentries);
1499 SSVAL(params,4,finished);
1500 SSVAL(params,6,0); /* Never an EA error */
1501 SSVAL(params,8,last_name_off);
1503 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1505 if ((! *directory) && dptr_path(dptr_num))
1506 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1508 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1509 smb_fn_name(CVAL(inbuf,smb_com)),
1510 mask, directory, dirtype, numentries ) );
1513 * Force a name mangle here to ensure that the
1514 * mask as an 8.3 name is top of the mangled cache.
1515 * The reasons for this are subtle. Don't remove
1516 * this code unless you know what you are doing
1517 * (see PR#13758). JRA.
1520 if(!mangle_is_8_3_wildcards( mask, False))
1521 mangle_map(mask, True, True, SNUM(conn));
1526 /****************************************************************************
1527 Reply to a TRANS2_FINDNEXT.
1528 ****************************************************************************/
1530 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1531 char **pparams, int total_params, char **ppdata, int total_data)
1533 /* We must be careful here that we don't return more than the
1534 allowed number of data bytes. If this means returning fewer than
1535 maxentries then so be it. We assume that the redirector has
1536 enough room for the fixed number of parameter bytes it has
1538 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1539 char *params = *pparams;
1540 char *pdata = *ppdata;
1541 int dptr_num = SVAL(params,0);
1542 int maxentries = SVAL(params,2);
1543 uint16 info_level = SVAL(params,4);
1544 uint32 resume_key = IVAL(params,6);
1545 BOOL close_after_request = BITSETW(params+10,0);
1546 BOOL close_if_end = BITSETW(params+10,1);
1547 BOOL requires_resume_key = BITSETW(params+10,2);
1548 BOOL continue_bit = BITSETW(params+10,3);
1549 pstring resume_name;
1555 int i, last_name_off=0;
1556 BOOL finished = False;
1557 BOOL dont_descend = False;
1558 BOOL out_of_space = False;
1559 int space_remaining;
1560 NTSTATUS ntstatus = NT_STATUS_OK;
1562 if (total_params < 12)
1563 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1565 *mask = *directory = *resume_name = 0;
1567 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus);
1568 if (!NT_STATUS_IS_OK(ntstatus)) {
1569 return ERROR_NT(ntstatus);
1572 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1573 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1574 resume_key = %d resume name = %s continue=%d level = %d\n",
1575 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1576 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1578 switch (info_level) {
1579 case SMB_INFO_STANDARD:
1580 case SMB_INFO_QUERY_EA_SIZE:
1581 case SMB_FIND_FILE_DIRECTORY_INFO:
1582 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1583 case SMB_FIND_FILE_NAMES_INFO:
1584 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1586 case SMB_FIND_FILE_UNIX:
1587 if (!lp_unix_extensions())
1588 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1591 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1594 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1596 return ERROR_DOS(ERRDOS,ERRnomem);
1599 memset((char *)pdata,'\0',max_data_bytes + 1024);
1601 /* Realloc the params space */
1602 params = Realloc(*pparams, 6*SIZEOFWORD);
1603 if( params == NULL )
1604 return ERROR_DOS(ERRDOS,ERRnomem);
1608 /* Check that the dptr is valid */
1609 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1610 return ERROR_DOS(ERRDOS,ERRnofiles);
1612 string_set(&conn->dirpath,dptr_path(dptr_num));
1614 /* Get the wildcard mask from the dptr */
1615 if((p = dptr_wcard(dptr_num))== NULL) {
1616 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1617 return ERROR_DOS(ERRDOS,ERRnofiles);
1621 pstrcpy(directory,conn->dirpath);
1623 /* Get the attr mask from the dptr */
1624 dirtype = dptr_attr(dptr_num);
1626 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1627 dptr_num, mask, dirtype,
1629 TellDir(conn->dirptr)));
1631 /* We don't need to check for VOL here as this is returned by
1632 a different TRANS2 call. */
1634 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1635 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1636 dont_descend = True;
1639 space_remaining = max_data_bytes;
1640 out_of_space = False;
1643 * Seek to the correct position. We no longer use the resume key but
1644 * depend on the last file name instead.
1647 if(requires_resume_key && *resume_name && !continue_bit) {
1650 * Fix for NT redirector problem triggered by resume key indexes
1651 * changing between directory scans. We now return a resume key of 0
1652 * and instead look for the filename to continue from (also given
1653 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1654 * findfirst/findnext (as is usual) then the directory pointer
1655 * should already be at the correct place. Check this by scanning
1656 * backwards looking for an exact (ie. case sensitive) filename match.
1657 * If we get to the beginning of the directory and haven't found it then scan
1658 * forwards again looking for a match. JRA.
1661 int current_pos, start_pos;
1662 const char *dname = NULL;
1663 pstring dname_pstring;
1664 void *dirptr = conn->dirptr;
1665 start_pos = TellDir(dirptr);
1666 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1667 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1669 SeekDir(dirptr, current_pos);
1670 dname = ReadDirName(dirptr);
1673 * Remember, mangle_map is called by
1674 * get_lanman2_dir_entry(), so the resume name
1675 * could be mangled. Ensure we do the same
1679 /* make sure we get a copy that mangle_map can modify */
1681 pstrcpy(dname_pstring, dname);
1682 mangle_map( dname_pstring, False, True, SNUM(conn));
1684 if(strcsequal( resume_name, dname_pstring)) {
1685 SeekDir(dirptr, current_pos+1);
1686 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1693 * Scan forward from start if not found going backwards.
1696 if(current_pos < 0) {
1697 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1698 SeekDir(dirptr, start_pos);
1699 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1702 * Remember, mangle_map is called by
1703 * get_lanman2_dir_entry(), so the resume name
1704 * could be mangled. Ensure we do the same
1709 /* make sure we get a copy that mangle_map can modify */
1711 pstrcpy(dname_pstring, dname);
1712 mangle_map(dname_pstring, False, True, SNUM(conn));
1714 if(strcsequal( resume_name, dname_pstring)) {
1715 SeekDir(dirptr, current_pos+1);
1716 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1721 } /* end if current_pos */
1722 } /* end if requires_resume_key && !continue_bit */
1724 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1725 BOOL got_exact_match = False;
1727 /* this is a heuristic to avoid seeking the dirptr except when
1728 absolutely necessary. It allows for a filename of about 40 chars */
1729 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1730 out_of_space = True;
1733 finished = !get_lanman2_dir_entry(conn,
1735 mask,dirtype,info_level,
1736 requires_resume_key,dont_descend,
1737 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1741 if (finished && out_of_space)
1744 if (!finished && !out_of_space)
1748 * As an optimisation if we know we aren't looking
1749 * for a wildcard name (ie. the name matches the wildcard exactly)
1750 * then we can finish on any (first) match.
1751 * This speeds up large directory searches. JRA.
1757 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1760 /* Check if we can close the dirptr */
1761 if(close_after_request || (finished && close_if_end)) {
1762 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1763 dptr_close(&dptr_num); /* This frees up the saved mask */
1766 /* Set up the return parameter block */
1767 SSVAL(params,0,numentries);
1768 SSVAL(params,2,finished);
1769 SSVAL(params,4,0); /* Never an EA error */
1770 SSVAL(params,6,last_name_off);
1772 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1774 if ((! *directory) && dptr_path(dptr_num))
1775 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1777 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1778 smb_fn_name(CVAL(inbuf,smb_com)),
1779 mask, directory, dirtype, numentries ) );
1784 /****************************************************************************
1785 Reply to a TRANS2_QFSINFO (query filesystem info).
1786 ****************************************************************************/
1788 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1789 int length, int bufsize,
1790 char **pparams, int total_params, char **ppdata, int total_data)
1792 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1793 char *pdata = *ppdata;
1794 char *params = *pparams;
1795 uint16 info_level = SVAL(params,0);
1798 char *vname = volume_label(SNUM(conn));
1799 int snum = SNUM(conn);
1800 char *fstype = lp_fstype(SNUM(conn));
1803 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1805 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1806 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1807 return ERROR_DOS(ERRSRV,ERRinvdevice);
1810 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1811 if ( pdata == NULL )
1812 return ERROR_DOS(ERRDOS,ERRnomem);
1815 memset((char *)pdata,'\0',max_data_bytes + 1024);
1817 switch (info_level) {
1818 case SMB_INFO_ALLOCATION:
1820 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1822 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1823 block_size = lp_block_size(snum);
1824 if (bsize < block_size) {
1825 SMB_BIG_UINT factor = block_size/bsize;
1830 if (bsize > block_size) {
1831 SMB_BIG_UINT factor = bsize/block_size;
1836 bytes_per_sector = 512;
1837 sectors_per_unit = bsize/bytes_per_sector;
1839 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1840 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1841 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1843 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1844 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1845 SIVAL(pdata,l1_cUnit,dsize);
1846 SIVAL(pdata,l1_cUnitAvail,dfree);
1847 SSVAL(pdata,l1_cbSector,bytes_per_sector);
1851 case SMB_INFO_VOLUME:
1852 /* Return volume name */
1854 * Add volume serial number - hash of a combination of
1855 * the called hostname and the service name.
1857 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1858 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1859 SCVAL(pdata,l2_vol_cch,len);
1860 data_len = l2_vol_szVolLabel + len;
1861 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1862 (unsigned)st.st_ctime, len, vname));
1865 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1866 case SMB_FS_ATTRIBUTE_INFORMATION:
1869 #if defined(HAVE_SYS_QUOTAS)
1870 quota_flag = FILE_VOLUME_QUOTAS;
1873 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1874 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1875 quota_flag); /* FS ATTRIBUTES */
1877 SIVAL(pdata,4,255); /* Max filename component length */
1878 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1879 and will think we can't do long filenames */
1880 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1882 data_len = 12 + len;
1885 case SMB_QUERY_FS_LABEL_INFO:
1886 case SMB_FS_LABEL_INFORMATION:
1887 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1892 case SMB_QUERY_FS_VOLUME_INFO:
1893 case SMB_FS_VOLUME_INFORMATION:
1896 * Add volume serial number - hash of a combination of
1897 * the called hostname and the service name.
1899 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1900 (str_checksum(local_machine)<<16));
1902 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1903 SIVAL(pdata,12,len);
1905 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1906 (int)strlen(vname),vname, lp_servicename(snum)));
1909 case SMB_QUERY_FS_SIZE_INFO:
1910 case SMB_FS_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_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);
1934 SBIG_UINT(pdata,8,dfree);
1935 SIVAL(pdata,16,sectors_per_unit);
1936 SIVAL(pdata,20,bytes_per_sector);
1940 case SMB_FS_FULL_SIZE_INFORMATION:
1942 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1944 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1945 block_size = lp_block_size(snum);
1946 if (bsize < block_size) {
1947 SMB_BIG_UINT factor = block_size/bsize;
1952 if (bsize > block_size) {
1953 SMB_BIG_UINT factor = bsize/block_size;
1958 bytes_per_sector = 512;
1959 sectors_per_unit = bsize/bytes_per_sector;
1960 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1961 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1962 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1963 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1964 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1965 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1966 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1967 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1971 case SMB_QUERY_FS_DEVICE_INFO:
1972 case SMB_FS_DEVICE_INFORMATION:
1974 SIVAL(pdata,0,0); /* dev type */
1975 SIVAL(pdata,4,0); /* characteristics */
1978 #ifdef HAVE_SYS_QUOTAS
1979 case SMB_FS_QUOTA_INFORMATION:
1981 * what we have to send --metze:
1983 * Unknown1: 24 NULL bytes
1984 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1985 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
1986 * Quota Flags: 2 byte :
1987 * Unknown3: 6 NULL bytes
1991 * details for Quota Flags:
1993 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1994 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
1995 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1996 * 0x0001 Enable Quotas: enable quota for this fs
2000 /* we need to fake up a fsp here,
2001 * because its not send in this call
2004 SMB_NTQUOTA_STRUCT quotas;
2007 ZERO_STRUCT(quotas);
2014 if (current_user.uid != 0) {
2015 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2016 lp_servicename(SNUM(conn)),conn->user));
2017 return ERROR_DOS(ERRDOS,ERRnoaccess);
2020 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2021 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2022 return ERROR_DOS(ERRSRV,ERRerror);
2027 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2029 /* Unknown1 24 NULL bytes*/
2030 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2031 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2032 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2034 /* Default Soft Quota 8 bytes */
2035 SBIG_UINT(pdata,24,quotas.softlim);
2037 /* Default Hard Quota 8 bytes */
2038 SBIG_UINT(pdata,32,quotas.hardlim);
2040 /* Quota flag 2 bytes */
2041 SSVAL(pdata,40,quotas.qflags);
2043 /* Unknown3 6 NULL bytes */
2049 #endif /* HAVE_SYS_QUOTAS */
2050 case SMB_FS_OBJECTID_INFORMATION:
2055 * Query the version and capabilities of the CIFS UNIX extensions
2059 case SMB_QUERY_CIFS_UNIX_INFO:
2060 if (!lp_unix_extensions())
2061 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2063 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2064 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2065 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
2068 case SMB_MAC_QUERY_FS_INFO:
2070 * Thursby MAC extension... ONLY on NTFS filesystems
2071 * once we do streams then we don't need this
2073 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2075 SIVAL(pdata,84,0x100); /* Don't support mac... */
2080 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2084 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2086 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2091 #ifdef HAVE_SYS_QUOTAS
2092 /****************************************************************************
2093 Reply to a TRANS2_SETFSINFO (set filesystem info).
2094 ****************************************************************************/
2096 static int call_trans2setfsinfo(connection_struct *conn,
2097 char *inbuf, char *outbuf, int length, int bufsize,
2098 char **pparams, int total_params, char **ppdata, int total_data)
2100 char *pdata = *ppdata;
2101 char *params = *pparams;
2102 files_struct *fsp = NULL;
2105 SMB_NTQUOTA_STRUCT quotas;
2107 ZERO_STRUCT(quotas);
2109 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2112 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2113 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2114 lp_servicename(SNUM(conn)),conn->user));
2115 return ERROR_DOS(ERRSRV,ERRaccess);
2119 if (total_params < 4) {
2120 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2122 return ERROR_DOS(ERRDOS,ERRinvalidparam);
2125 fsp = file_fsp(params,0);
2127 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2128 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2129 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2132 info_level = SVAL(params,2);
2134 switch(info_level) {
2135 case SMB_FS_QUOTA_INFORMATION:
2136 /* note: normaly there're 48 bytes,
2137 * but we didn't use the last 6 bytes for now
2140 if (total_data < 42) {
2141 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2143 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2146 /* unknown_1 24 NULL bytes in pdata*/
2148 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2149 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2150 #ifdef LARGE_SMB_OFF_T
2151 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2152 #else /* LARGE_SMB_OFF_T */
2153 if ((IVAL(pdata,28) != 0)&&
2154 ((quotas.softlim != 0xFFFFFFFF)||
2155 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2156 /* more than 32 bits? */
2157 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2159 #endif /* LARGE_SMB_OFF_T */
2161 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2162 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2163 #ifdef LARGE_SMB_OFF_T
2164 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2165 #else /* LARGE_SMB_OFF_T */
2166 if ((IVAL(pdata,36) != 0)&&
2167 ((quotas.hardlim != 0xFFFFFFFF)||
2168 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2169 /* more than 32 bits? */
2170 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2172 #endif /* LARGE_SMB_OFF_T */
2174 /* quota_flags 2 bytes **/
2175 quotas.qflags = SVAL(pdata,40);
2177 /* unknown_2 6 NULL bytes follow*/
2179 /* now set the quotas */
2180 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2181 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2182 return ERROR_DOS(ERRSRV,ERRerror);
2187 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2189 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2194 * sending this reply works fine,
2195 * but I'm not sure it's the same
2196 * like windows do...
2199 outsize = set_message(outbuf,10,0,True);
2203 #endif /* HAVE_SYS_QUOTAS */
2205 /****************************************************************************
2206 * Utility function to set bad path error.
2207 ****************************************************************************/
2209 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2211 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2212 err, (int)bad_path ));
2216 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2218 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2221 return UNIXERROR(def_class,def_code);
2224 /****************************************************************************
2225 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2226 file name or file id).
2227 ****************************************************************************/
2229 static int call_trans2qfilepathinfo(connection_struct *conn,
2230 char *inbuf, char *outbuf, int length,
2232 char **pparams, int total_params, char **ppdata, int total_data)
2234 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
2235 char *params = *pparams;
2236 char *pdata = *ppdata;
2237 uint16 tran_call = SVAL(inbuf, smb_setup0);
2240 SMB_OFF_T file_size=0;
2241 SMB_BIG_UINT allocation_size=0;
2242 unsigned int data_size;
2243 unsigned int param_size = 2;
2244 SMB_STRUCT_STAT sbuf;
2245 pstring fname, dos_fname;
2250 BOOL bad_path = False;
2251 BOOL delete_pending = False;
2254 files_struct *fsp = NULL;
2255 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2258 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2260 if (tran_call == TRANSACT2_QFILEINFO) {
2261 if (total_params < 4)
2262 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2264 fsp = file_fsp(params,0);
2265 info_level = SVAL(params,2);
2267 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2269 if(fsp && (fsp->fake_file_handle)) {
2271 * This is actually for the QUOTA_FAKE_FILE --metze
2274 pstrcpy(fname, fsp->fsp_name);
2275 unix_convert(fname,conn,0,&bad_path,&sbuf);
2276 if (!check_name(fname,conn)) {
2277 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno)));
2278 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2281 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2283 * This is actually a QFILEINFO on a directory
2284 * handle (returned from an NT SMB). NT5.0 seems
2285 * to do this call. JRA.
2287 pstrcpy(fname, fsp->fsp_name);
2288 unix_convert(fname,conn,0,&bad_path,&sbuf);
2289 if (!check_name(fname,conn)) {
2290 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2291 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2294 if (INFO_LEVEL_IS_UNIX(info_level)) {
2295 /* Always do lstat for UNIX calls. */
2296 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2297 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2298 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2300 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
2301 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2302 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2305 delete_pending = fsp->directory_delete_on_close;
2308 * Original code - this is an open file.
2310 CHECK_FSP(fsp,conn);
2312 pstrcpy(fname, fsp->fsp_name);
2313 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2314 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2315 return(UNIXERROR(ERRDOS,ERRbadfid));
2317 pos = fsp->position_information;
2318 delete_pending = fsp->delete_on_close;
2319 desired_access = fsp->desired_access;
2322 NTSTATUS status = NT_STATUS_OK;
2325 if (total_params < 6)
2326 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2328 info_level = SVAL(params,0);
2330 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2332 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
2333 if (!NT_STATUS_IS_OK(status)) {
2334 return ERROR_NT(status);
2337 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2339 unix_convert(fname,conn,0,&bad_path,&sbuf);
2340 if (!check_name(fname,conn)) {
2341 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2342 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2345 if (INFO_LEVEL_IS_UNIX(info_level)) {
2346 /* Always do lstat for UNIX calls. */
2347 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2348 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2349 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2351 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2352 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2353 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2357 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2358 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2360 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2361 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2363 p = strrchr_m(fname,'/');
2369 mode = dos_mode(conn,fname,&sbuf);
2371 mode = FILE_ATTRIBUTE_NORMAL;
2373 fullpathname = fname;
2374 file_size = get_file_size(sbuf);
2375 allocation_size = get_allocation_size(fsp,&sbuf);
2379 params = Realloc(*pparams,2);
2381 return ERROR_DOS(ERRDOS,ERRnomem);
2383 memset((char *)params,'\0',2);
2384 data_size = max_data_bytes + 1024;
2385 pdata = Realloc(*ppdata, data_size);
2386 if ( pdata == NULL )
2387 return ERROR_DOS(ERRDOS,ERRnomem);
2390 if (total_data > 0 && IVAL(pdata,0) == total_data) {
2391 /* uggh, EAs for OS2 */
2392 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2393 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2396 memset((char *)pdata,'\0',data_size);
2398 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2400 if (lp_dos_filetime_resolution(SNUM(conn))) {
2402 sbuf.st_atime &= ~1;
2403 sbuf.st_mtime &= ~1;
2404 sbuf.st_mtime &= ~1;
2407 /* NT expects the name to be in an exact form of the *full*
2408 filename. See the trans2 torture test */
2409 if (strequal(base_name,".")) {
2410 pstrcpy(dos_fname, "\\");
2412 pstr_sprintf(dos_fname, "\\%s", fname);
2413 string_replace(dos_fname, '/', '\\');
2416 switch (info_level) {
2417 case SMB_INFO_STANDARD:
2418 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2420 put_dos_date2(pdata,l1_fdateCreation,c_time);
2421 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2422 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2423 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2424 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2425 SSVAL(pdata,l1_attrFile,mode);
2428 case SMB_INFO_QUERY_EA_SIZE:
2430 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2431 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2433 put_dos_date2(pdata,l1_fdateCreation,c_time);
2434 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2435 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2436 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2437 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2438 SSVAL(pdata,l1_attrFile,mode);
2439 SIVAL(pdata,l1_attrFile+2,ea_size);
2443 case SMB_INFO_IS_NAME_VALID:
2444 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2445 if (tran_call == TRANSACT2_QFILEINFO) {
2446 /* os/2 needs this ? really ?*/
2447 return ERROR_DOS(ERRDOS,ERRbadfunc);
2453 case SMB_INFO_QUERY_EAS_FROM_LIST:
2454 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2456 put_dos_date2(pdata,0,c_time);
2457 put_dos_date2(pdata,4,sbuf.st_atime);
2458 put_dos_date2(pdata,8,sbuf.st_mtime);
2459 SIVAL(pdata,12,(uint32)file_size);
2460 SIVAL(pdata,16,(uint32)allocation_size);
2461 SIVAL(pdata,20,mode);
2464 case SMB_INFO_QUERY_ALL_EAS:
2465 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2466 /* We have data_size bytes to put EA's into. */
2467 data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname);
2470 case SMB_FILE_BASIC_INFORMATION:
2471 case SMB_QUERY_FILE_BASIC_INFO:
2473 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2474 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2475 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2477 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2481 put_long_date(pdata,c_time);
2482 put_long_date(pdata+8,sbuf.st_atime);
2483 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2484 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2485 SIVAL(pdata,32,mode);
2487 DEBUG(5,("SMB_QFBI - "));
2489 time_t create_time = c_time;
2490 DEBUG(5,("create: %s ", ctime(&create_time)));
2492 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2493 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2494 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2495 DEBUG(5,("mode: %x\n", mode));
2499 case SMB_FILE_STANDARD_INFORMATION:
2500 case SMB_QUERY_FILE_STANDARD_INFO:
2502 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2504 SOFF_T(pdata,0,allocation_size);
2505 SOFF_T(pdata,8,file_size);
2506 if (delete_pending & sbuf.st_nlink)
2507 SIVAL(pdata,16,sbuf.st_nlink - 1);
2509 SIVAL(pdata,16,sbuf.st_nlink);
2511 SCVAL(pdata,21,(mode&aDIR)?1:0);
2514 case SMB_FILE_EA_INFORMATION:
2515 case SMB_QUERY_FILE_EA_INFO:
2517 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2518 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2520 SIVAL(pdata,0,ea_size);
2524 /* Get the 8.3 name - used if NT SMB was negotiated. */
2525 case SMB_QUERY_FILE_ALT_NAME_INFO:
2526 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2530 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2531 pstrcpy(short_name,base_name);
2532 /* Mangle if not already 8.3 */
2533 if(!mangle_is_8_3(short_name, True)) {
2534 mangle_map(short_name,True,True,SNUM(conn));
2536 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2537 data_size = 4 + len;
2542 case SMB_QUERY_FILE_NAME_INFO:
2544 this must be *exactly* right for ACLs on mapped drives to work
2546 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2547 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2548 data_size = 4 + len;
2552 case SMB_FILE_ALLOCATION_INFORMATION:
2553 case SMB_QUERY_FILE_ALLOCATION_INFO:
2554 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2556 SOFF_T(pdata,0,allocation_size);
2559 case SMB_FILE_END_OF_FILE_INFORMATION:
2560 case SMB_QUERY_FILE_END_OF_FILEINFO:
2561 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2563 SOFF_T(pdata,0,file_size);
2566 case SMB_QUERY_FILE_ALL_INFO:
2567 case SMB_FILE_ALL_INFORMATION:
2569 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2570 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2571 put_long_date(pdata,c_time);
2572 put_long_date(pdata+8,sbuf.st_atime);
2573 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2574 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2575 SIVAL(pdata,32,mode);
2577 SOFF_T(pdata,0,allocation_size);
2578 SOFF_T(pdata,8,file_size);
2579 if (delete_pending && sbuf.st_nlink)
2580 SIVAL(pdata,16,sbuf.st_nlink - 1);
2582 SIVAL(pdata,16,sbuf.st_nlink);
2583 SCVAL(pdata,20,delete_pending);
2584 SCVAL(pdata,21,(mode&aDIR)?1:0);
2586 SIVAL(pdata,0,ea_size);
2587 pdata += 4; /* EA info */
2588 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2591 data_size = PTR_DIFF(pdata,(*ppdata));
2594 case SMB_FILE_INTERNAL_INFORMATION:
2595 /* This should be an index number - looks like
2598 I think this causes us to fail the IFSKIT
2599 BasicFileInformationTest. -tpot */
2601 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2602 SIVAL(pdata,0,sbuf.st_dev);
2603 SIVAL(pdata,4,sbuf.st_ino);
2607 case SMB_FILE_ACCESS_INFORMATION:
2608 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2609 SIVAL(pdata,0,desired_access);
2613 case SMB_FILE_NAME_INFORMATION:
2614 /* Pathname with leading '\'. */
2617 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2618 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2619 SIVAL(pdata,0,byte_len);
2620 data_size = 4 + byte_len;
2624 case SMB_FILE_DISPOSITION_INFORMATION:
2625 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2627 SCVAL(pdata,0,delete_pending);
2630 case SMB_FILE_POSITION_INFORMATION:
2631 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2633 SOFF_T(pdata,0,pos);
2636 case SMB_FILE_MODE_INFORMATION:
2637 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2638 SIVAL(pdata,0,mode);
2642 case SMB_FILE_ALIGNMENT_INFORMATION:
2643 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2644 SIVAL(pdata,0,0); /* No alignment needed. */
2650 * NT4 server just returns "invalid query" to this - if we try to answer
2651 * it then NTws gets a BSOD! (tridge).
2652 * W2K seems to want this. JRA.
2654 case SMB_QUERY_FILE_STREAM_INFO:
2656 case SMB_FILE_STREAM_INFORMATION:
2657 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2661 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2662 SIVAL(pdata,0,0); /* ??? */
2663 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2664 SOFF_T(pdata,8,file_size);
2665 SIVAL(pdata,16,allocation_size);
2666 SIVAL(pdata,20,0); /* ??? */
2667 data_size = 24 + byte_len;
2671 case SMB_QUERY_COMPRESSION_INFO:
2672 case SMB_FILE_COMPRESSION_INFORMATION:
2673 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2674 SOFF_T(pdata,0,file_size);
2675 SIVAL(pdata,8,0); /* ??? */
2676 SIVAL(pdata,12,0); /* ??? */
2680 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2681 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2682 put_long_date(pdata,c_time);
2683 put_long_date(pdata+8,sbuf.st_atime);
2684 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2685 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2686 SIVAL(pdata,32,allocation_size);
2687 SOFF_T(pdata,40,file_size);
2688 SIVAL(pdata,48,mode);
2689 SIVAL(pdata,52,0); /* ??? */
2693 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2694 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2695 SIVAL(pdata,0,mode);
2701 * CIFS UNIX Extensions.
2704 case SMB_QUERY_FILE_UNIX_BASIC:
2706 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2707 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2709 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2712 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2715 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2716 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2717 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2720 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2724 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2728 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2731 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2735 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2739 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2742 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2746 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2749 data_size = PTR_DIFF(pdata,(*ppdata));
2753 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2755 for (i=0; i<100; i++)
2756 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2762 case SMB_QUERY_FILE_UNIX_LINK:
2766 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
2768 if(!S_ISLNK(sbuf.st_mode))
2769 return(UNIXERROR(ERRSRV,ERRbadlink));
2771 return(UNIXERROR(ERRDOS,ERRbadlink));
2773 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2775 return(UNIXERROR(ERRDOS,ERRnoaccess));
2777 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2779 data_size = PTR_DIFF(pdata,(*ppdata));
2785 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2788 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
2793 /****************************************************************************
2794 Deal with the internal needs of setting the delete on close flag. Note that
2795 as the tdb locking is recursive, it is safe to call this from within
2796 open_file_shared. JRA.
2797 ****************************************************************************/
2799 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2802 * Only allow delete on close for writable shares.
2805 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2806 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2808 return NT_STATUS_ACCESS_DENIED;
2811 * Only allow delete on close for files/directories opened with delete intent.
2814 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2815 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2817 return NT_STATUS_ACCESS_DENIED;
2820 if(fsp->is_directory) {
2821 fsp->directory_delete_on_close = delete_on_close;
2822 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2823 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2825 fsp->delete_on_close = delete_on_close;
2826 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2827 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2830 return NT_STATUS_OK;
2833 /****************************************************************************
2834 Sets the delete on close flag over all share modes on this file.
2835 Modify the share mode entry for all files open
2836 on this device and inode to tell other smbds we have
2837 changed the delete on close flag. This will be noticed
2838 in the close code, the last closer will delete the file
2840 ****************************************************************************/
2842 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2844 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2845 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2847 if (fsp->is_directory || fsp->is_stat)
2848 return NT_STATUS_OK;
2850 if (lock_share_entry_fsp(fsp) == False)
2851 return NT_STATUS_ACCESS_DENIED;
2853 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2854 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2856 unlock_share_entry_fsp(fsp);
2857 return NT_STATUS_ACCESS_DENIED;
2860 unlock_share_entry_fsp(fsp);
2861 return NT_STATUS_OK;
2864 /****************************************************************************
2865 Returns true if this pathname is within the share, and thus safe.
2866 ****************************************************************************/
2868 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in)
2871 char resolved_name[PATH_MAX+1];
2873 pstring resolved_name;
2875 fstring last_component;
2879 BOOL bad_path = False;
2880 SMB_STRUCT_STAT sbuf;
2882 pstrcpy(link_dest, link_dest_in);
2883 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2885 p = strrchr_m(link_dest, '/');
2887 fstrcpy(last_component, p+1);
2890 fstrcpy(last_component, link_dest);
2891 pstrcpy(link_dest, "./");
2894 if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL)
2897 DEBUG(10,("ensure_link_is_safe: realpath: link_dest (%s) -> real name (%s)\n",
2898 link_dest, resolved_name ));
2900 pstrcpy(link_dest, resolved_name);
2901 pstrcat(link_dest, "/");
2902 pstrcat(link_dest, last_component);
2904 if (*link_dest != '/') {
2905 /* Relative path. */
2906 pstrcpy(link_test, conn->connectpath);
2907 pstrcat(link_test, "/");
2908 pstrcat(link_test, link_dest);
2910 pstrcpy(link_test, link_dest);
2913 DEBUG(10,("ensure_link_is_safe: connectpath = %s, absolute resolved path = %s\n",
2914 conn->connectpath, link_test ));
2917 * Check if the link is within the share.
2920 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2928 /****************************************************************************
2929 Set a hard link (called by UNIX extensions and by NT rename with HARD link
2931 ****************************************************************************/
2933 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
2935 BOOL bad_path_oldname = False;
2936 BOOL bad_path_newname = False;
2937 SMB_STRUCT_STAT sbuf1, sbuf2;
2939 pstring last_component_oldname;
2940 pstring last_component_newname;
2941 NTSTATUS status = NT_STATUS_OK;
2947 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
2948 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
2951 rc = unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
2952 if (!rc && bad_path_oldname) {
2953 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2956 /* Quick check for "." and ".." */
2957 if (last_component_oldname[0] == '.') {
2958 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
2959 return NT_STATUS_OBJECT_NAME_INVALID;
2963 /* source must already exist. */
2964 if (!VALID_STAT(sbuf1)) {
2965 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2968 if (!check_name(oldname,conn)) {
2969 return NT_STATUS_ACCESS_DENIED;
2972 rcdest = unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
2973 if (!rcdest && bad_path_newname) {
2974 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2977 /* Quick check for "." and ".." */
2978 if (last_component_newname[0] == '.') {
2979 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
2980 return NT_STATUS_OBJECT_NAME_INVALID;
2984 /* Disallow if newname already exists. */
2985 if (VALID_STAT(sbuf2)) {
2986 return NT_STATUS_OBJECT_NAME_COLLISION;
2989 if (!check_name(newname,conn)) {
2990 return NT_STATUS_ACCESS_DENIED;
2993 /* No links from a directory. */
2994 if (S_ISDIR(sbuf1.st_mode)) {
2995 return NT_STATUS_FILE_IS_A_DIRECTORY;
2998 /* Ensure this is within the share. */
2999 if (!reduce_name(conn, oldname) != 0)
3000 return NT_STATUS_ACCESS_DENIED;
3002 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3004 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3005 status = map_nt_error_from_unix(errno);
3006 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3007 nt_errstr(status), newname, oldname));
3013 /****************************************************************************
3014 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3015 ****************************************************************************/
3017 static int call_trans2setfilepathinfo(connection_struct *conn,
3018 char *inbuf, char *outbuf, int length, int bufsize,
3019 char **pparams, int total_params, char **ppdata, int total_data)
3021 char *params = *pparams;
3022 char *pdata = *ppdata;
3023 uint16 tran_call = SVAL(inbuf, smb_setup0);
3028 SMB_STRUCT_STAT sbuf;
3031 BOOL bad_path = False;
3032 files_struct *fsp = NULL;
3033 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3034 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3035 mode_t unixmode = 0;
3036 NTSTATUS status = NT_STATUS_OK;
3039 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3041 if (tran_call == TRANSACT2_SETFILEINFO) {
3042 if (total_params < 4)
3043 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3045 fsp = file_fsp(params,0);
3046 info_level = SVAL(params,2);
3048 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3050 * This is actually a SETFILEINFO on a directory
3051 * handle (returned from an NT SMB). NT5.0 seems
3052 * to do this call. JRA.
3054 pstrcpy(fname, fsp->fsp_name);
3055 unix_convert(fname,conn,0,&bad_path,&sbuf);
3056 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
3057 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3058 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3060 } else if (fsp && fsp->print_file) {
3062 * Doing a DELETE_ON_CLOSE should cancel a print job.
3064 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3065 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3067 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3070 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3073 return (UNIXERROR(ERRDOS,ERRbadpath));
3076 * Original code - this is an open file.
3078 CHECK_FSP(fsp,conn);
3080 pstrcpy(fname, fsp->fsp_name);
3083 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3084 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3085 return(UNIXERROR(ERRDOS,ERRbadfid));
3090 if (total_params < 6)
3091 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3093 info_level = SVAL(params,0);
3094 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
3095 if (!NT_STATUS_IS_OK(status)) {
3096 return ERROR_NT(status);
3098 unix_convert(fname,conn,0,&bad_path,&sbuf);
3101 * For CIFS UNIX extensions the target name may not exist.
3104 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3105 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3106 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3109 if(!check_name(fname, conn)) {
3110 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3115 if (!CAN_WRITE(conn))
3116 return ERROR_DOS(ERRSRV,ERRaccess);
3118 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3119 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3121 if (VALID_STAT(sbuf))
3122 unixmode = sbuf.st_mode;
3124 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3125 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3127 /* Realloc the parameter and data sizes */
3128 params = Realloc(*pparams,2);
3130 return ERROR_DOS(ERRDOS,ERRnomem);
3136 /* the pending modtime overrides the current modtime */
3137 sbuf.st_mtime = fsp->pending_modtime;
3140 size = get_file_size(sbuf);
3141 tvs.modtime = sbuf.st_mtime;
3142 tvs.actime = sbuf.st_atime;
3143 dosmode = dos_mode(conn,fname,&sbuf);
3144 unixmode = sbuf.st_mode;
3146 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3147 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3149 switch (info_level) {
3150 case SMB_INFO_STANDARD:
3152 if (total_data < 12)
3153 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3156 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3158 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3162 case SMB_INFO_SET_EA:
3163 status = set_ea(conn, fsp, fname, pdata, total_data);
3164 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3165 return ERROR_NT(status);
3168 /* XXXX um, i don't think this is right.
3169 it's also not in the cifs6.txt spec.
3171 case SMB_INFO_QUERY_EAS_FROM_LIST:
3172 if (total_data < 28)
3173 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3175 tvs.actime = make_unix_date2(pdata+8);
3176 tvs.modtime = make_unix_date2(pdata+12);
3177 size = IVAL(pdata,16);
3178 dosmode = IVAL(pdata,24);
3181 /* XXXX nor this. not in cifs6.txt, either. */
3182 case SMB_INFO_QUERY_ALL_EAS:
3183 if (total_data < 28)
3184 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3186 tvs.actime = make_unix_date2(pdata+8);
3187 tvs.modtime = make_unix_date2(pdata+12);
3188 size = IVAL(pdata,16);
3189 dosmode = IVAL(pdata,24);
3192 case SMB_SET_FILE_BASIC_INFO:
3193 case SMB_FILE_BASIC_INFORMATION:
3195 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3197 time_t changed_time;
3199 if (total_data < 36)
3200 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3202 /* Ignore create time at offset pdata. */
3205 tvs.actime = interpret_long_date(pdata+8);
3207 write_time = interpret_long_date(pdata+16);
3208 changed_time = interpret_long_date(pdata+24);
3210 tvs.modtime = MIN(write_time, changed_time);
3212 if (write_time > tvs.modtime && write_time != 0xffffffff) {
3213 tvs.modtime = write_time;
3215 /* Prefer a defined time to an undefined one. */
3216 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3217 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
3218 ? changed_time : write_time);
3221 dosmode = IVAL(pdata,32);
3225 case SMB_FILE_ALLOCATION_INFORMATION:
3226 case SMB_SET_FILE_ALLOCATION_INFO:
3229 SMB_BIG_UINT allocation_size;
3232 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3234 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3235 #ifdef LARGE_SMB_OFF_T
3236 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3237 #else /* LARGE_SMB_OFF_T */
3238 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3239 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3240 #endif /* LARGE_SMB_OFF_T */
3241 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3242 fname, (double)allocation_size ));
3244 if (allocation_size)
3245 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
3247 if(allocation_size != get_file_size(sbuf)) {
3248 SMB_STRUCT_STAT new_sbuf;
3250 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3251 fname, (double)allocation_size ));
3254 files_struct *new_fsp = NULL;
3255 int access_mode = 0;
3258 if(global_oplock_break) {
3259 /* Queue this file modify as we are the process of an oplock break. */
3261 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3262 DEBUGADD(2,( "in oplock break state.\n"));
3264 push_oplock_pending_smb_message(inbuf, length);
3268 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3269 SET_OPEN_MODE(DOS_OPEN_RDWR),
3270 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3271 FILE_ATTRIBUTE_NORMAL,
3272 0, &access_mode, &action);
3274 if (new_fsp == NULL)
3275 return(UNIXERROR(ERRDOS,ERRbadpath));
3276 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3277 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3278 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3279 new_fsp->fnum, strerror(errno)));
3282 close_file(new_fsp,True);
3284 ret = vfs_allocate_file_space(fsp, allocation_size);
3285 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3286 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3287 fsp->fnum, strerror(errno)));
3292 return ERROR_NT(NT_STATUS_DISK_FULL);
3294 /* Allocate can truncate size... */
3295 size = get_file_size(new_sbuf);
3301 case SMB_FILE_END_OF_FILE_INFORMATION:
3302 case SMB_SET_FILE_END_OF_FILE_INFO:
3305 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3307 size = IVAL(pdata,0);
3308 #ifdef LARGE_SMB_OFF_T
3309 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3310 #else /* LARGE_SMB_OFF_T */
3311 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3312 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3313 #endif /* LARGE_SMB_OFF_T */
3314 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3318 case SMB_FILE_DISPOSITION_INFORMATION:
3319 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3321 BOOL delete_on_close;
3324 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3326 delete_on_close = (CVAL(pdata,0) ? True : False);
3328 /* Just ignore this set on a path. */
3329 if (tran_call != TRANSACT2_SETFILEINFO)
3333 return(UNIXERROR(ERRDOS,ERRbadfid));
3335 status = set_delete_on_close_internal(fsp, delete_on_close);
3337 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3338 return ERROR_NT(status);
3340 /* The set is across all open files on this dev/inode pair. */
3341 status =set_delete_on_close_over_all(fsp, delete_on_close);
3342 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3343 return ERROR_NT(status);
3348 case SMB_FILE_POSITION_INFORMATION:
3350 SMB_BIG_UINT position_information;
3353 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3355 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3356 #ifdef LARGE_SMB_OFF_T
3357 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3358 #else /* LARGE_SMB_OFF_T */
3359 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3360 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3361 #endif /* LARGE_SMB_OFF_T */
3362 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3363 fname, (double)position_information ));
3365 fsp->position_information = position_information;
3370 * CIFS UNIX extensions.
3373 case SMB_SET_FILE_UNIX_BASIC:
3375 uint32 raw_unixmode;
3377 if (total_data < 100)
3378 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3380 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3381 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3382 size=IVAL(pdata,0); /* first 8 Bytes are size */
3383 #ifdef LARGE_SMB_OFF_T
3384 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3385 #else /* LARGE_SMB_OFF_T */
3386 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3387 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3388 #endif /* LARGE_SMB_OFF_T */
3390 pdata+=24; /* ctime & st_blocks are not changed */
3391 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
3392 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
3394 set_owner = (uid_t)IVAL(pdata,0);
3396 set_grp = (gid_t)IVAL(pdata,0);
3398 raw_unixmode = IVAL(pdata,28);
3399 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3400 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3402 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3403 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3404 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3406 if (!VALID_STAT(sbuf)) {
3409 * The only valid use of this is to create character and block
3410 * devices, and named pipes. This is deprecated (IMHO) and
3411 * a new info level should be used for mknod. JRA.
3414 #if !defined(HAVE_MAKEDEV_FN)
3415 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3416 #else /* HAVE_MAKEDEV_FN */
3417 uint32 file_type = IVAL(pdata,0);
3418 uint32 dev_major = IVAL(pdata,4);
3419 uint32 dev_minor = IVAL(pdata,12);
3421 uid_t myuid = geteuid();
3422 gid_t mygid = getegid();
3425 if (tran_call == TRANSACT2_SETFILEINFO)
3426 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3428 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3429 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3431 dev = makedev(dev_major, dev_minor);
3433 /* We can only create as the owner/group we are. */
3435 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3436 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3437 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3438 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3440 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
3441 file_type != UNIX_TYPE_FIFO)
3442 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3444 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3445 0%o for file %s\n", (double)dev, unixmode, fname ));
3447 /* Ok - do the mknod. */
3448 if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
3449 return(UNIXERROR(ERRDOS,ERRnoaccess));
3451 inherit_access_acl(conn, fname, unixmode);
3454 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3456 #endif /* HAVE_MAKEDEV_FN */
3461 * Deal with the UNIX specific mode set.
3464 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3465 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3466 (unsigned int)unixmode, fname ));
3467 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3468 return(UNIXERROR(ERRDOS,ERRnoaccess));
3472 * Deal with the UNIX specific uid set.
3475 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3476 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3477 (unsigned int)set_owner, fname ));
3478 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3479 return(UNIXERROR(ERRDOS,ERRnoaccess));
3483 * Deal with the UNIX specific gid set.
3486 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3487 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3488 (unsigned int)set_owner, fname ));
3489 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3490 return(UNIXERROR(ERRDOS,ERRnoaccess));
3495 case SMB_SET_FILE_UNIX_LINK:
3497 pstring link_target;
3498 char *newname = fname;
3500 /* Set a symbolic link. */
3501 /* Don't allow this if follow links is false. */
3503 if (!lp_symlinks(SNUM(conn)))
3504 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3506 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
3508 /* !widelinks forces the target path to be within the share. */
3509 if (!lp_widelinks(SNUM(conn))) {
3511 char *last_dirp = NULL;
3513 unix_format(link_target);
3515 pstrcpy(rel_name, newname);
3516 last_dirp = strrchr_m(rel_name, '/');
3518 last_dirp[1] = '\0';
3520 pstrcpy(rel_name, "./");
3522 pstrcat(rel_name, link_target);
3523 if (ensure_link_is_safe(conn, rel_name) != 0) {
3524 return(UNIXERROR(ERRDOS,ERRnoaccess));
3527 if (check_name(link_target, conn)) {
3528 return(UNIXERROR(ERRDOS,ERRnoaccess));
3532 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3533 fname, link_target ));
3535 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
3536 return(UNIXERROR(ERRDOS,ERRnoaccess));
3538 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3542 case SMB_SET_FILE_UNIX_HLINK:
3545 char *newname = fname;
3547 /* Set a hard link. */
3548 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
3549 if (!NT_STATUS_IS_OK(status)) {
3550 return ERROR_NT(status);
3553 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3556 status = hardlink_internals(conn, oldname, newname);
3557 if (!NT_STATUS_IS_OK(status)) {
3558 return ERROR_NT(status);
3562 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3566 case SMB_FILE_RENAME_INFORMATION:
3575 if (total_data < 12)
3576 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3578 overwrite = (CVAL(pdata,0) ? True : False);
3579 root_fid = IVAL(pdata,4);
3580 len = IVAL(pdata,8);
3581 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
3582 if (!NT_STATUS_IS_OK(status)) {
3583 return ERROR_NT(status);
3586 /* Check the new name has no '/' characters. */
3587 if (strchr_m(newname, '/'))
3588 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3590 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3592 /* Create the base directory. */
3593 pstrcpy(base_name, fname);
3594 p = strrchr_m(base_name, '/');
3597 /* Append the new name. */
3598 pstrcat(base_name, "/");
3599 pstrcat(base_name, newname);
3602 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3603 fsp->fnum, fsp->fsp_name, base_name ));
3604 status = rename_internals_fsp(conn, fsp, base_name, overwrite);
3606 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3608 status = rename_internals(conn, fname, base_name, 0, overwrite);
3610 if (!NT_STATUS_IS_OK(status)) {
3611 return ERROR_NT(status);
3613 process_pending_change_notify_queue((time_t)0);
3615 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3619 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3622 /* get some defaults (no modifications) if any info is zero or -1. */
3623 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
3624 tvs.actime = sbuf.st_atime;
3626 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3627 tvs.modtime = sbuf.st_mtime;
3629 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3630 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3631 DEBUG(6,("size: %.0f ", (double)size));
3634 if (S_ISDIR(sbuf.st_mode))
3640 DEBUG(6,("dosmode: %x\n" , dosmode));
3642 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3643 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3644 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3645 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3648 * Only do this test if we are not explicitly
3649 * changing the size of a file.
3652 size = get_file_size(sbuf);
3656 * Try and set the times, size and mode of this file -
3657 * if they are different from the current values
3659 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3662 * This was a setfileinfo on an open file.
3663 * NT does this a lot. It's actually pointless
3664 * setting the time here, as it will be overwritten
3665 * on the next write, so we save the request
3666 * away and will set it on file close. JRA.
3669 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3670 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3671 fsp->pending_modtime = tvs.modtime;
3676 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3678 if(file_utime(conn, fname, &tvs)!=0)
3679 return(UNIXERROR(ERRDOS,ERRnoaccess));
3683 /* check the mode isn't different, before changing it */
3684 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3686 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3688 if(file_set_dosmode(conn, fname, dosmode, NULL)) {
3689 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
3690 return(UNIXERROR(ERRDOS,ERRnoaccess));
3694 if (size != get_file_size(sbuf)) {
3698 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3699 fname, (double)size ));
3702 files_struct *new_fsp = NULL;
3703 int access_mode = 0;
3706 if(global_oplock_break) {
3707 /* Queue this file modify as we are the process of an oplock break. */
3709 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3710 DEBUGADD(2,( "in oplock break state.\n"));
3712 push_oplock_pending_smb_message(inbuf, length);
3716 new_fsp = open_file_shared(conn, fname, &sbuf,
3717 SET_OPEN_MODE(DOS_OPEN_RDWR),
3718 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3719 FILE_ATTRIBUTE_NORMAL,
3720 0, &access_mode, &action);
3722 if (new_fsp == NULL)
3723 return(UNIXERROR(ERRDOS,ERRbadpath));
3724 ret = vfs_set_filelen(new_fsp, size);
3725 close_file(new_fsp,True);
3727 ret = vfs_set_filelen(fsp, size);
3731 return (UNIXERROR(ERRHRD,ERRdiskfull));
3735 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3740 /****************************************************************************
3741 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3742 ****************************************************************************/
3744 static int call_trans2mkdir(connection_struct *conn,
3745 char *inbuf, char *outbuf, int length, int bufsize,
3746 char **pparams, int total_params, char **ppdata, int total_data)
3748 char *params = *pparams;
3751 SMB_STRUCT_STAT sbuf;
3752 BOOL bad_path = False;
3753 NTSTATUS status = NT_STATUS_OK;
3755 if (!CAN_WRITE(conn))
3756 return ERROR_DOS(ERRSRV,ERRaccess);
3758 if (total_params < 4)
3759 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3761 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status);
3762 if (!NT_STATUS_IS_OK(status)) {
3763 return ERROR_NT(status);
3766 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3768 unix_convert(directory,conn,0,&bad_path,&sbuf);
3769 if (check_name(directory,conn))
3770 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3773 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3774 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
3777 /* Realloc the parameter and data sizes */
3778 params = Realloc(*pparams,2);
3780 return ERROR_DOS(ERRDOS,ERRnomem);
3785 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3790 /****************************************************************************
3791 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3792 We don't actually do this - we just send a null response.
3793 ****************************************************************************/
3795 static int call_trans2findnotifyfirst(connection_struct *conn,
3796 char *inbuf, char *outbuf, int length, int bufsize,
3797 char **pparams, int total_params, char **ppdata, int total_data)
3799 static uint16 fnf_handle = 257;
3800 char *params = *pparams;
3803 if (total_params < 6)
3804 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3806 info_level = SVAL(params,4);
3807 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3809 switch (info_level) {
3814 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3817 /* Realloc the parameter and data sizes */
3818 params = Realloc(*pparams,6);
3820 return ERROR_DOS(ERRDOS,ERRnomem);
3823 SSVAL(params,0,fnf_handle);
3824 SSVAL(params,2,0); /* No changes */
3825 SSVAL(params,4,0); /* No EA errors */
3832 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3837 /****************************************************************************
3838 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3839 changes). Currently this does nothing.
3840 ****************************************************************************/
3842 static int call_trans2findnotifynext(connection_struct *conn,
3843 char *inbuf, char *outbuf, int length, int bufsize,
3844 char **pparams, int total_params, char **ppdata, int total_data)
3846 char *params = *pparams;
3848 DEBUG(3,("call_trans2findnotifynext\n"));
3850 /* Realloc the parameter and data sizes */
3851 params = Realloc(*pparams,4);
3853 return ERROR_DOS(ERRDOS,ERRnomem);
3856 SSVAL(params,0,0); /* No changes */
3857 SSVAL(params,2,0); /* No EA errors */
3859 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3864 /****************************************************************************
3865 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3866 ****************************************************************************/
3868 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3869 char* outbuf, int length, int bufsize,
3870 char **pparams, int total_params, char **ppdata, int total_data)
3872 char *params = *pparams;
3875 int max_referral_level;
3877 DEBUG(10,("call_trans2getdfsreferral\n"));
3879 if (total_params < 2)
3880 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3882 max_referral_level = SVAL(params,0);
3884 if(!lp_host_msdfs())
3885 return ERROR_DOS(ERRDOS,ERRbadfunc);
3887 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
3888 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
3889 return UNIXERROR(ERRDOS,ERRbadfile);
3891 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3892 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3897 #define LMCAT_SPL 0x53
3898 #define LMFUNC_GETJOBID 0x60
3900 /****************************************************************************
3901 Reply to a TRANS2_IOCTL - used for OS/2 printing.
3902 ****************************************************************************/
3904 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3905 char* outbuf, int length, int bufsize,
3906 char **pparams, int total_params, char **ppdata, int total_data)
3908 char *pdata = *ppdata;
3909 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3911 /* check for an invalid fid before proceeding */
3914 return(ERROR_DOS(ERRDOS,ERRbadfid));
3916 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3917 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3918 pdata = Realloc(*ppdata, 32);
3920 return ERROR_DOS(ERRDOS,ERRnomem);
3923 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3924 CAN ACCEPT THIS IN UNICODE. JRA. */
3926 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
3927 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3928 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3929 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3932 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3933 return ERROR_DOS(ERRSRV,ERRerror);
3937 /****************************************************************************
3938 Reply to a SMBfindclose (stop trans2 directory search).
3939 ****************************************************************************/
3941 int reply_findclose(connection_struct *conn,
3942 char *inbuf,char *outbuf,int length,int bufsize)
3945 int dptr_num=SVALS(inbuf,smb_vwv0);
3946 START_PROFILE(SMBfindclose);
3948 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3950 dptr_close(&dptr_num);
3952 outsize = set_message(outbuf,0,0,True);
3954 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3956 END_PROFILE(SMBfindclose);
3960 /****************************************************************************
3961 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3962 ****************************************************************************/
3964 int reply_findnclose(connection_struct *conn,
3965 char *inbuf,char *outbuf,int length,int bufsize)
3969 START_PROFILE(SMBfindnclose);
3971 dptr_num = SVAL(inbuf,smb_vwv0);
3973 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3975 /* We never give out valid handles for a
3976 findnotifyfirst - so any dptr_num is ok here.
3979 outsize = set_message(outbuf,0,0,True);
3981 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3983 END_PROFILE(SMBfindnclose);
3987 /****************************************************************************
3988 Reply to a SMBtranss2 - just ignore it!
3989 ****************************************************************************/
3991 int reply_transs2(connection_struct *conn,
3992 char *inbuf,char *outbuf,int length,int bufsize)
3994 START_PROFILE(SMBtranss2);
3995 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3996 END_PROFILE(SMBtranss2);
4000 /****************************************************************************
4001 Reply to a SMBtrans2.
4002 ****************************************************************************/
4004 int reply_trans2(connection_struct *conn,
4005 char *inbuf,char *outbuf,int length,int bufsize)
4008 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4009 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4011 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4012 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
4013 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4014 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4015 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4016 int32 timeout = IVALS(inbuf,smb_timeout);
4018 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4019 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4020 char *params = NULL, *data = NULL;
4021 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4022 START_PROFILE(SMBtrans2);
4024 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4025 /* Queue this open message as we are the process of an
4028 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4029 DEBUGADD(2,( "in oplock break state.\n"));
4031 push_oplock_pending_smb_message(inbuf, length);
4032 END_PROFILE(SMBtrans2);
4036 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4037 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4038 END_PROFILE(SMBtrans2);
4039 return ERROR_DOS(ERRSRV,ERRaccess);
4042 outsize = set_message(outbuf,0,0,True);
4044 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4045 is so as a sanity check */
4048 * Need to have rc=0 for ioctl to get job id for OS/2.
4049 * Network printing will fail if function is not successful.
4050 * Similar function in reply.c will be used if protocol
4051 * is LANMAN1.0 instead of LM1.2X002.
4052 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4053 * outbuf doesn't have to be set(only job id is used).
4055 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4056 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4057 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4058 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4060 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4061 DEBUG(2,("Transaction is %d\n",tran_call));
4062 END_PROFILE(SMBtrans2);
4063 ERROR_DOS(ERRDOS,ERRinvalidparam);
4067 /* Allocate the space for the maximum needed parameters and data */
4068 if (total_params > 0)
4069 params = (char *)malloc(total_params);
4071 data = (char *)malloc(total_data);
4073 if ((total_params && !params) || (total_data && !data)) {
4074 DEBUG(2,("Out of memory in reply_trans2\n"));
4077 END_PROFILE(SMBtrans2);
4078 return ERROR_DOS(ERRDOS,ERRnomem);
4081 /* Copy the param and data bytes sent with this request into
4082 the params buffer */
4083 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4084 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4086 if (num_params > total_params || num_data > total_data)
4087 exit_server("invalid params in reply_trans2");
4090 unsigned int psoff = SVAL(inbuf, smb_psoff);
4091 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4093 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4094 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4096 memcpy( params, smb_base(inbuf) + psoff, num_params);
4099 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4100 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4102 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4103 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4105 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4108 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4110 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4111 /* We need to send an interim response then receive the rest
4112 of the parameter/data bytes */
4113 outsize = set_message(outbuf,0,0,True);
4114 srv_signing_trans_stop();
4115 if (!send_smb(smbd_server_fd(),outbuf))
4116 exit_server("reply_trans2: send_smb failed.");
4118 while (num_data_sofar < total_data ||
4119 num_params_sofar < total_params) {
4121 unsigned int param_disp;
4122 unsigned int param_off;
4123 unsigned int data_disp;
4124 unsigned int data_off;
4126 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4129 * The sequence number for the trans reply is always
4130 * based on the last secondary received.
4133 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4136 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4137 outsize = set_message(outbuf,0,0,True);
4139 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4141 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4142 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4146 /* Revise total_params and total_data in case
4147 they have changed downwards */
4148 if (SVAL(inbuf, smb_tpscnt) < total_params)
4149 total_params = SVAL(inbuf, smb_tpscnt);
4150 if (SVAL(inbuf, smb_tdscnt) < total_data)
4151 total_data = SVAL(inbuf, smb_tdscnt);
4153 num_params = SVAL(inbuf,smb_spscnt);
4154 param_off = SVAL(inbuf, smb_spsoff);
4155 param_disp = SVAL(inbuf, smb_spsdisp);
4156 num_params_sofar += num_params;
4158 num_data = SVAL(inbuf, smb_sdscnt);
4159 data_off = SVAL(inbuf, smb_sdsoff);
4160 data_disp = SVAL(inbuf, smb_sdsdisp);
4161 num_data_sofar += num_data;
4163 if (num_params_sofar > total_params || num_data_sofar > total_data)
4167 if (param_disp + num_params >= total_params)
4169 if ((param_disp + num_params < param_disp) ||
4170 (param_disp + num_params < num_params))
4172 if (param_disp > total_params)
4174 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4175 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4177 if (params + param_disp < params)
4180 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
4183 if (data_disp + num_data >= total_data)
4185 if ((data_disp + num_data < data_disp) ||
4186 (data_disp + num_data < num_data))
4188 if (data_disp > total_data)
4190 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4191 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4193 if (data + data_disp < data)
4196 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4201 if (Protocol >= PROTOCOL_NT1) {
4202 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4205 /* Now we must call the relevant TRANS2 function */
4207 case TRANSACT2_OPEN:
4208 START_PROFILE_NESTED(Trans2_open);
4209 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4210 ¶ms, total_params, &data, total_data);
4211 END_PROFILE_NESTED(Trans2_open);
4214 case TRANSACT2_FINDFIRST:
4215 START_PROFILE_NESTED(Trans2_findfirst);
4216 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4217 ¶ms, total_params, &data, total_data);
4218 END_PROFILE_NESTED(Trans2_findfirst);
4221 case TRANSACT2_FINDNEXT:
4222 START_PROFILE_NESTED(Trans2_findnext);
4223 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4224 ¶ms, total_params, &data, total_data);
4225 END_PROFILE_NESTED(Trans2_findnext);
4228 case TRANSACT2_QFSINFO:
4229 START_PROFILE_NESTED(Trans2_qfsinfo);
4230 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4231 ¶ms, total_params, &data, total_data);
4232 END_PROFILE_NESTED(Trans2_qfsinfo);
4235 #ifdef HAVE_SYS_QUOTAS
4236 case TRANSACT2_SETFSINFO:
4237 START_PROFILE_NESTED(Trans2_setfsinfo);
4238 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4239 ¶ms, total_params, &data, total_data);
4240 END_PROFILE_NESTED(Trans2_setfsinfo);
4243 case TRANSACT2_QPATHINFO:
4244 case TRANSACT2_QFILEINFO:
4245 START_PROFILE_NESTED(Trans2_qpathinfo);
4246 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4247 ¶ms, total_params, &data, total_data);
4248 END_PROFILE_NESTED(Trans2_qpathinfo);
4250 case TRANSACT2_SETPATHINFO:
4251 case TRANSACT2_SETFILEINFO:
4252 START_PROFILE_NESTED(Trans2_setpathinfo);
4253 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4254 ¶ms, total_params, &data, total_data);
4255 END_PROFILE_NESTED(Trans2_setpathinfo);
4258 case TRANSACT2_FINDNOTIFYFIRST:
4259 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4260 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4261 ¶ms, total_params, &data, total_data);
4262 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4265 case TRANSACT2_FINDNOTIFYNEXT:
4266 START_PROFILE_NESTED(Trans2_findnotifynext);
4267 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4268 ¶ms, total_params, &data, total_data);
4269 END_PROFILE_NESTED(Trans2_findnotifynext);
4271 case TRANSACT2_MKDIR:
4272 START_PROFILE_NESTED(Trans2_mkdir);
4273 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4274 ¶ms, total_params, &data, total_data);
4275 END_PROFILE_NESTED(Trans2_mkdir);
4278 case TRANSACT2_GET_DFS_REFERRAL:
4279 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4280 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4281 ¶ms, total_params, &data, total_data);
4282 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4284 case TRANSACT2_IOCTL:
4285 START_PROFILE_NESTED(Trans2_ioctl);
4286 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4287 ¶ms, total_params, &data, total_data);
4288 END_PROFILE_NESTED(Trans2_ioctl);
4291 /* Error in request */
4292 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4295 END_PROFILE(SMBtrans2);
4296 srv_signing_trans_stop();
4297 return ERROR_DOS(ERRSRV,ERRerror);
4300 /* As we do not know how many data packets will need to be
4301 returned here the various call_trans2xxxx calls
4302 must send their own. Thus a call_trans2xxx routine only
4303 returns a value other than -1 when it wants to send
4307 srv_signing_trans_stop();
4311 END_PROFILE(SMBtrans2);
4312 return outsize; /* If a correct response was needed the
4313 call_trans2xxx calls have already sent
4314 it. If outsize != -1 then it is returning */
4318 srv_signing_trans_stop();
4321 END_PROFILE(SMBtrans2);
4322 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);