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, char *link_dest_out)
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 /* Store the UNIX converted path. */
2886 pstrcpy(link_dest_out, link_dest);
2888 p = strrchr_m(link_dest, '/');
2890 fstrcpy(last_component, p+1);
2893 fstrcpy(last_component, link_dest);
2894 pstrcpy(link_dest, "./");
2897 if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL)
2900 DEBUG(10,("ensure_link_is_safe: realpath: link_dest (%s) -> real name (%s)\n",
2901 link_dest, resolved_name ));
2903 pstrcpy(link_dest, resolved_name);
2904 pstrcat(link_dest, "/");
2905 pstrcat(link_dest, last_component);
2907 if (*link_dest != '/') {
2908 /* Relative path. */
2909 pstrcpy(link_test, conn->connectpath);
2910 pstrcat(link_test, "/");
2911 pstrcat(link_test, link_dest);
2913 pstrcpy(link_test, link_dest);
2916 DEBUG(10,("ensure_link_is_safe: connectpath = %s, absolute resolved path = %s\n",
2917 conn->connectpath, link_test ));
2920 * Check if the link is within the share.
2923 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2931 /****************************************************************************
2932 Set a hard link (called by UNIX extensions and by NT rename with HARD link
2934 ****************************************************************************/
2936 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
2938 BOOL bad_path_oldname = False;
2939 BOOL bad_path_newname = False;
2940 SMB_STRUCT_STAT sbuf1, sbuf2;
2942 pstring last_component_oldname;
2943 pstring last_component_newname;
2944 NTSTATUS status = NT_STATUS_OK;
2950 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
2951 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
2954 rc = unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
2955 if (!rc && bad_path_oldname) {
2956 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2959 /* Quick check for "." and ".." */
2960 if (last_component_oldname[0] == '.') {
2961 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
2962 return NT_STATUS_OBJECT_NAME_INVALID;
2966 /* source must already exist. */
2967 if (!VALID_STAT(sbuf1)) {
2968 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2971 if (!check_name(oldname,conn)) {
2972 return NT_STATUS_ACCESS_DENIED;
2975 rcdest = unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
2976 if (!rcdest && bad_path_newname) {
2977 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2980 /* Quick check for "." and ".." */
2981 if (last_component_newname[0] == '.') {
2982 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
2983 return NT_STATUS_OBJECT_NAME_INVALID;
2987 /* Disallow if newname already exists. */
2988 if (VALID_STAT(sbuf2)) {
2989 return NT_STATUS_OBJECT_NAME_COLLISION;
2992 if (!check_name(newname,conn)) {
2993 return NT_STATUS_ACCESS_DENIED;
2996 /* No links from a directory. */
2997 if (S_ISDIR(sbuf1.st_mode)) {
2998 return NT_STATUS_FILE_IS_A_DIRECTORY;
3001 if (ensure_link_is_safe(conn, oldname, oldname) != 0)
3002 return NT_STATUS_ACCESS_DENIED;
3004 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3006 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3007 status = map_nt_error_from_unix(errno);
3008 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3009 nt_errstr(status), newname, oldname));
3015 /****************************************************************************
3016 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3017 ****************************************************************************/
3019 static int call_trans2setfilepathinfo(connection_struct *conn,
3020 char *inbuf, char *outbuf, int length, int bufsize,
3021 char **pparams, int total_params, char **ppdata, int total_data)
3023 char *params = *pparams;
3024 char *pdata = *ppdata;
3025 uint16 tran_call = SVAL(inbuf, smb_setup0);
3030 SMB_STRUCT_STAT sbuf;
3033 BOOL bad_path = False;
3034 files_struct *fsp = NULL;
3035 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3036 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3037 mode_t unixmode = 0;
3038 NTSTATUS status = NT_STATUS_OK;
3041 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3043 if (tran_call == TRANSACT2_SETFILEINFO) {
3044 if (total_params < 4)
3045 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3047 fsp = file_fsp(params,0);
3048 info_level = SVAL(params,2);
3050 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3052 * This is actually a SETFILEINFO on a directory
3053 * handle (returned from an NT SMB). NT5.0 seems
3054 * to do this call. JRA.
3056 pstrcpy(fname, fsp->fsp_name);
3057 unix_convert(fname,conn,0,&bad_path,&sbuf);
3058 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
3059 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3060 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3062 } else if (fsp && fsp->print_file) {
3064 * Doing a DELETE_ON_CLOSE should cancel a print job.
3066 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3067 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3069 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3072 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3075 return (UNIXERROR(ERRDOS,ERRbadpath));
3078 * Original code - this is an open file.
3080 CHECK_FSP(fsp,conn);
3082 pstrcpy(fname, fsp->fsp_name);
3085 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3086 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3087 return(UNIXERROR(ERRDOS,ERRbadfid));
3092 if (total_params < 6)
3093 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3095 info_level = SVAL(params,0);
3096 srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
3097 if (!NT_STATUS_IS_OK(status)) {
3098 return ERROR_NT(status);
3100 unix_convert(fname,conn,0,&bad_path,&sbuf);
3103 * For CIFS UNIX extensions the target name may not exist.
3106 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3107 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3108 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3111 if(!check_name(fname, conn)) {
3112 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3117 if (!CAN_WRITE(conn))
3118 return ERROR_DOS(ERRSRV,ERRaccess);
3120 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3121 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3123 if (VALID_STAT(sbuf))
3124 unixmode = sbuf.st_mode;
3126 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3127 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3129 /* Realloc the parameter and data sizes */
3130 params = Realloc(*pparams,2);
3132 return ERROR_DOS(ERRDOS,ERRnomem);
3138 /* the pending modtime overrides the current modtime */
3139 sbuf.st_mtime = fsp->pending_modtime;
3142 size = get_file_size(sbuf);
3143 tvs.modtime = sbuf.st_mtime;
3144 tvs.actime = sbuf.st_atime;
3145 dosmode = dos_mode(conn,fname,&sbuf);
3146 unixmode = sbuf.st_mode;
3148 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3149 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3151 switch (info_level) {
3152 case SMB_INFO_STANDARD:
3154 if (total_data < 12)
3155 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3158 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3160 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3164 case SMB_INFO_SET_EA:
3165 status = set_ea(conn, fsp, fname, pdata, total_data);
3166 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3167 return ERROR_NT(status);
3170 /* XXXX um, i don't think this is right.
3171 it's also not in the cifs6.txt spec.
3173 case SMB_INFO_QUERY_EAS_FROM_LIST:
3174 if (total_data < 28)
3175 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3177 tvs.actime = make_unix_date2(pdata+8);
3178 tvs.modtime = make_unix_date2(pdata+12);
3179 size = IVAL(pdata,16);
3180 dosmode = IVAL(pdata,24);
3183 /* XXXX nor this. not in cifs6.txt, either. */
3184 case SMB_INFO_QUERY_ALL_EAS:
3185 if (total_data < 28)
3186 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3188 tvs.actime = make_unix_date2(pdata+8);
3189 tvs.modtime = make_unix_date2(pdata+12);
3190 size = IVAL(pdata,16);
3191 dosmode = IVAL(pdata,24);
3194 case SMB_SET_FILE_BASIC_INFO:
3195 case SMB_FILE_BASIC_INFORMATION:
3197 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3199 time_t changed_time;
3201 if (total_data < 36)
3202 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3204 /* Ignore create time at offset pdata. */
3207 tvs.actime = interpret_long_date(pdata+8);
3209 write_time = interpret_long_date(pdata+16);
3210 changed_time = interpret_long_date(pdata+24);
3212 tvs.modtime = MIN(write_time, changed_time);
3214 if (write_time > tvs.modtime && write_time != 0xffffffff) {
3215 tvs.modtime = write_time;
3217 /* Prefer a defined time to an undefined one. */
3218 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3219 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
3220 ? changed_time : write_time);
3223 dosmode = IVAL(pdata,32);
3227 case SMB_FILE_ALLOCATION_INFORMATION:
3228 case SMB_SET_FILE_ALLOCATION_INFO:
3231 SMB_BIG_UINT allocation_size;
3234 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3236 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3237 #ifdef LARGE_SMB_OFF_T
3238 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3239 #else /* LARGE_SMB_OFF_T */
3240 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3241 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3242 #endif /* LARGE_SMB_OFF_T */
3243 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3244 fname, (double)allocation_size ));
3246 if (allocation_size)
3247 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
3249 if(allocation_size != get_file_size(sbuf)) {
3250 SMB_STRUCT_STAT new_sbuf;
3252 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3253 fname, (double)allocation_size ));
3256 files_struct *new_fsp = NULL;
3257 int access_mode = 0;
3260 if(global_oplock_break) {
3261 /* Queue this file modify as we are the process of an oplock break. */
3263 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3264 DEBUGADD(2,( "in oplock break state.\n"));
3266 push_oplock_pending_smb_message(inbuf, length);
3270 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3271 SET_OPEN_MODE(DOS_OPEN_RDWR),
3272 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3273 FILE_ATTRIBUTE_NORMAL,
3274 0, &access_mode, &action);
3276 if (new_fsp == NULL)
3277 return(UNIXERROR(ERRDOS,ERRbadpath));
3278 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3279 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3280 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3281 new_fsp->fnum, strerror(errno)));
3284 close_file(new_fsp,True);
3286 ret = vfs_allocate_file_space(fsp, allocation_size);
3287 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3288 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3289 fsp->fnum, strerror(errno)));
3294 return ERROR_NT(NT_STATUS_DISK_FULL);
3296 /* Allocate can truncate size... */
3297 size = get_file_size(new_sbuf);
3303 case SMB_FILE_END_OF_FILE_INFORMATION:
3304 case SMB_SET_FILE_END_OF_FILE_INFO:
3307 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3309 size = IVAL(pdata,0);
3310 #ifdef LARGE_SMB_OFF_T
3311 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3312 #else /* LARGE_SMB_OFF_T */
3313 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3314 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3315 #endif /* LARGE_SMB_OFF_T */
3316 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3320 case SMB_FILE_DISPOSITION_INFORMATION:
3321 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3323 BOOL delete_on_close;
3326 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3328 delete_on_close = (CVAL(pdata,0) ? True : False);
3330 /* Just ignore this set on a path. */
3331 if (tran_call != TRANSACT2_SETFILEINFO)
3335 return(UNIXERROR(ERRDOS,ERRbadfid));
3337 status = set_delete_on_close_internal(fsp, delete_on_close);
3339 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3340 return ERROR_NT(status);
3342 /* The set is across all open files on this dev/inode pair. */
3343 status =set_delete_on_close_over_all(fsp, delete_on_close);
3344 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3345 return ERROR_NT(status);
3350 case SMB_FILE_POSITION_INFORMATION:
3352 SMB_BIG_UINT position_information;
3355 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3357 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3358 #ifdef LARGE_SMB_OFF_T
3359 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3360 #else /* LARGE_SMB_OFF_T */
3361 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3362 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3363 #endif /* LARGE_SMB_OFF_T */
3364 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3365 fname, (double)position_information ));
3367 fsp->position_information = position_information;
3372 * CIFS UNIX extensions.
3375 case SMB_SET_FILE_UNIX_BASIC:
3377 uint32 raw_unixmode;
3379 if (total_data < 100)
3380 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3382 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3383 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3384 size=IVAL(pdata,0); /* first 8 Bytes are size */
3385 #ifdef LARGE_SMB_OFF_T
3386 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3387 #else /* LARGE_SMB_OFF_T */
3388 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3389 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3390 #endif /* LARGE_SMB_OFF_T */
3392 pdata+=24; /* ctime & st_blocks are not changed */
3393 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
3394 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
3396 set_owner = (uid_t)IVAL(pdata,0);
3398 set_grp = (gid_t)IVAL(pdata,0);
3400 raw_unixmode = IVAL(pdata,28);
3401 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3402 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3404 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3405 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3406 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3408 if (!VALID_STAT(sbuf)) {
3411 * The only valid use of this is to create character and block
3412 * devices, and named pipes. This is deprecated (IMHO) and
3413 * a new info level should be used for mknod. JRA.
3416 #if !defined(HAVE_MAKEDEV_FN)
3417 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3418 #else /* HAVE_MAKEDEV_FN */
3419 uint32 file_type = IVAL(pdata,0);
3420 uint32 dev_major = IVAL(pdata,4);
3421 uint32 dev_minor = IVAL(pdata,12);
3423 uid_t myuid = geteuid();
3424 gid_t mygid = getegid();
3427 if (tran_call == TRANSACT2_SETFILEINFO)
3428 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3430 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3431 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3433 dev = makedev(dev_major, dev_minor);
3435 /* We can only create as the owner/group we are. */
3437 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3438 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3439 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3440 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3442 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
3443 file_type != UNIX_TYPE_FIFO)
3444 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3446 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3447 0%o for file %s\n", (double)dev, unixmode, fname ));
3449 /* Ok - do the mknod. */
3450 if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
3451 return(UNIXERROR(ERRDOS,ERRnoaccess));
3453 inherit_access_acl(conn, fname, unixmode);
3456 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3458 #endif /* HAVE_MAKEDEV_FN */
3463 * Deal with the UNIX specific mode set.
3466 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3467 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3468 (unsigned int)unixmode, fname ));
3469 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3470 return(UNIXERROR(ERRDOS,ERRnoaccess));
3474 * Deal with the UNIX specific uid set.
3477 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3478 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3479 (unsigned int)set_owner, fname ));
3480 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3481 return(UNIXERROR(ERRDOS,ERRnoaccess));
3485 * Deal with the UNIX specific gid set.
3488 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3489 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3490 (unsigned int)set_owner, fname ));
3491 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3492 return(UNIXERROR(ERRDOS,ERRnoaccess));
3497 case SMB_SET_FILE_UNIX_LINK:
3499 pstring link_target;
3500 char *newname = fname;
3502 /* Set a symbolic link. */
3503 /* Don't allow this if follow links is false. */
3505 if (!lp_symlinks(SNUM(conn)))
3506 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3508 srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
3510 /* !widelinks forces the target path to be within the share. */
3511 if (!lp_widelinks(SNUM(conn))) {
3513 char *last_dirp = NULL;
3515 unix_format(link_target);
3517 pstrcpy(rel_name, newname);
3518 last_dirp = strrchr_m(rel_name, '/');
3520 last_dirp[1] = '\0';
3522 pstrcpy(rel_name, "./");
3524 pstrcat(rel_name, link_target);
3525 if (ensure_link_is_safe(conn, rel_name, rel_name) != 0) {
3526 return(UNIXERROR(ERRDOS,ERRnoaccess));
3529 if (check_name(link_target, conn)) {
3530 return(UNIXERROR(ERRDOS,ERRnoaccess));
3534 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3535 fname, link_target ));
3537 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
3538 return(UNIXERROR(ERRDOS,ERRnoaccess));
3540 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3544 case SMB_SET_FILE_UNIX_HLINK:
3547 char *newname = fname;
3549 /* Set a hard link. */
3550 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
3551 if (!NT_STATUS_IS_OK(status)) {
3552 return ERROR_NT(status);
3555 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3558 status = hardlink_internals(conn, oldname, newname);
3559 if (!NT_STATUS_IS_OK(status)) {
3560 return ERROR_NT(status);
3564 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3568 case SMB_FILE_RENAME_INFORMATION:
3577 if (total_data < 12)
3578 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3580 overwrite = (CVAL(pdata,0) ? True : False);
3581 root_fid = IVAL(pdata,4);
3582 len = IVAL(pdata,8);
3583 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
3584 if (!NT_STATUS_IS_OK(status)) {
3585 return ERROR_NT(status);
3588 /* Check the new name has no '/' characters. */
3589 if (strchr_m(newname, '/'))
3590 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3592 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3594 /* Create the base directory. */
3595 pstrcpy(base_name, fname);
3596 p = strrchr_m(base_name, '/');
3599 /* Append the new name. */
3600 pstrcat(base_name, "/");
3601 pstrcat(base_name, newname);
3604 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3605 fsp->fnum, fsp->fsp_name, base_name ));
3606 status = rename_internals_fsp(conn, fsp, base_name, overwrite);
3608 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3610 status = rename_internals(conn, fname, base_name, 0, overwrite);
3612 if (!NT_STATUS_IS_OK(status)) {
3613 return ERROR_NT(status);
3615 process_pending_change_notify_queue((time_t)0);
3617 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3621 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3624 /* get some defaults (no modifications) if any info is zero or -1. */
3625 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
3626 tvs.actime = sbuf.st_atime;
3628 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3629 tvs.modtime = sbuf.st_mtime;
3631 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3632 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3633 DEBUG(6,("size: %.0f ", (double)size));
3636 if (S_ISDIR(sbuf.st_mode))
3642 DEBUG(6,("dosmode: %x\n" , dosmode));
3644 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3645 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3646 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3647 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3650 * Only do this test if we are not explicitly
3651 * changing the size of a file.
3654 size = get_file_size(sbuf);
3658 * Try and set the times, size and mode of this file -
3659 * if they are different from the current values
3661 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3664 * This was a setfileinfo on an open file.
3665 * NT does this a lot. It's actually pointless
3666 * setting the time here, as it will be overwritten
3667 * on the next write, so we save the request
3668 * away and will set it on file close. JRA.
3671 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3672 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3673 fsp->pending_modtime = tvs.modtime;
3678 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3680 if(file_utime(conn, fname, &tvs)!=0)
3681 return(UNIXERROR(ERRDOS,ERRnoaccess));
3685 /* check the mode isn't different, before changing it */
3686 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3688 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3690 if(file_set_dosmode(conn, fname, dosmode, NULL)) {
3691 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
3692 return(UNIXERROR(ERRDOS,ERRnoaccess));
3696 if (size != get_file_size(sbuf)) {
3700 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3701 fname, (double)size ));
3704 files_struct *new_fsp = NULL;
3705 int access_mode = 0;
3708 if(global_oplock_break) {
3709 /* Queue this file modify as we are the process of an oplock break. */
3711 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3712 DEBUGADD(2,( "in oplock break state.\n"));
3714 push_oplock_pending_smb_message(inbuf, length);
3718 new_fsp = open_file_shared(conn, fname, &sbuf,
3719 SET_OPEN_MODE(DOS_OPEN_RDWR),
3720 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3721 FILE_ATTRIBUTE_NORMAL,
3722 0, &access_mode, &action);
3724 if (new_fsp == NULL)
3725 return(UNIXERROR(ERRDOS,ERRbadpath));
3726 ret = vfs_set_filelen(new_fsp, size);
3727 close_file(new_fsp,True);
3729 ret = vfs_set_filelen(fsp, size);
3733 return (UNIXERROR(ERRHRD,ERRdiskfull));
3737 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3742 /****************************************************************************
3743 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3744 ****************************************************************************/
3746 static int call_trans2mkdir(connection_struct *conn,
3747 char *inbuf, char *outbuf, int length, int bufsize,
3748 char **pparams, int total_params, char **ppdata, int total_data)
3750 char *params = *pparams;
3753 SMB_STRUCT_STAT sbuf;
3754 BOOL bad_path = False;
3755 NTSTATUS status = NT_STATUS_OK;
3757 if (!CAN_WRITE(conn))
3758 return ERROR_DOS(ERRSRV,ERRaccess);
3760 if (total_params < 4)
3761 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3763 srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status);
3764 if (!NT_STATUS_IS_OK(status)) {
3765 return ERROR_NT(status);
3768 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3770 unix_convert(directory,conn,0,&bad_path,&sbuf);
3771 if (check_name(directory,conn))
3772 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3775 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3776 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
3779 /* Realloc the parameter and data sizes */
3780 params = Realloc(*pparams,2);
3782 return ERROR_DOS(ERRDOS,ERRnomem);
3787 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3792 /****************************************************************************
3793 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3794 We don't actually do this - we just send a null response.
3795 ****************************************************************************/
3797 static int call_trans2findnotifyfirst(connection_struct *conn,
3798 char *inbuf, char *outbuf, int length, int bufsize,
3799 char **pparams, int total_params, char **ppdata, int total_data)
3801 static uint16 fnf_handle = 257;
3802 char *params = *pparams;
3805 if (total_params < 6)
3806 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3808 info_level = SVAL(params,4);
3809 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3811 switch (info_level) {
3816 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3819 /* Realloc the parameter and data sizes */
3820 params = Realloc(*pparams,6);
3822 return ERROR_DOS(ERRDOS,ERRnomem);
3825 SSVAL(params,0,fnf_handle);
3826 SSVAL(params,2,0); /* No changes */
3827 SSVAL(params,4,0); /* No EA errors */
3834 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3839 /****************************************************************************
3840 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3841 changes). Currently this does nothing.
3842 ****************************************************************************/
3844 static int call_trans2findnotifynext(connection_struct *conn,
3845 char *inbuf, char *outbuf, int length, int bufsize,
3846 char **pparams, int total_params, char **ppdata, int total_data)
3848 char *params = *pparams;
3850 DEBUG(3,("call_trans2findnotifynext\n"));
3852 /* Realloc the parameter and data sizes */
3853 params = Realloc(*pparams,4);
3855 return ERROR_DOS(ERRDOS,ERRnomem);
3858 SSVAL(params,0,0); /* No changes */
3859 SSVAL(params,2,0); /* No EA errors */
3861 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3866 /****************************************************************************
3867 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3868 ****************************************************************************/
3870 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3871 char* outbuf, int length, int bufsize,
3872 char **pparams, int total_params, char **ppdata, int total_data)
3874 char *params = *pparams;
3877 int max_referral_level;
3879 DEBUG(10,("call_trans2getdfsreferral\n"));
3881 if (total_params < 2)
3882 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3884 max_referral_level = SVAL(params,0);
3886 if(!lp_host_msdfs())
3887 return ERROR_DOS(ERRDOS,ERRbadfunc);
3889 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
3890 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
3891 return UNIXERROR(ERRDOS,ERRbadfile);
3893 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3894 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3899 #define LMCAT_SPL 0x53
3900 #define LMFUNC_GETJOBID 0x60
3902 /****************************************************************************
3903 Reply to a TRANS2_IOCTL - used for OS/2 printing.
3904 ****************************************************************************/
3906 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3907 char* outbuf, int length, int bufsize,
3908 char **pparams, int total_params, char **ppdata, int total_data)
3910 char *pdata = *ppdata;
3911 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3913 /* check for an invalid fid before proceeding */
3916 return(ERROR_DOS(ERRDOS,ERRbadfid));
3918 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3919 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3920 pdata = Realloc(*ppdata, 32);
3922 return ERROR_DOS(ERRDOS,ERRnomem);
3925 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3926 CAN ACCEPT THIS IN UNICODE. JRA. */
3928 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
3929 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3930 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3931 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3934 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3935 return ERROR_DOS(ERRSRV,ERRerror);
3939 /****************************************************************************
3940 Reply to a SMBfindclose (stop trans2 directory search).
3941 ****************************************************************************/
3943 int reply_findclose(connection_struct *conn,
3944 char *inbuf,char *outbuf,int length,int bufsize)
3947 int dptr_num=SVALS(inbuf,smb_vwv0);
3948 START_PROFILE(SMBfindclose);
3950 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3952 dptr_close(&dptr_num);
3954 outsize = set_message(outbuf,0,0,True);
3956 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3958 END_PROFILE(SMBfindclose);
3962 /****************************************************************************
3963 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3964 ****************************************************************************/
3966 int reply_findnclose(connection_struct *conn,
3967 char *inbuf,char *outbuf,int length,int bufsize)
3971 START_PROFILE(SMBfindnclose);
3973 dptr_num = SVAL(inbuf,smb_vwv0);
3975 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3977 /* We never give out valid handles for a
3978 findnotifyfirst - so any dptr_num is ok here.
3981 outsize = set_message(outbuf,0,0,True);
3983 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3985 END_PROFILE(SMBfindnclose);
3989 /****************************************************************************
3990 Reply to a SMBtranss2 - just ignore it!
3991 ****************************************************************************/
3993 int reply_transs2(connection_struct *conn,
3994 char *inbuf,char *outbuf,int length,int bufsize)
3996 START_PROFILE(SMBtranss2);
3997 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3998 END_PROFILE(SMBtranss2);
4002 /****************************************************************************
4003 Reply to a SMBtrans2.
4004 ****************************************************************************/
4006 int reply_trans2(connection_struct *conn,
4007 char *inbuf,char *outbuf,int length,int bufsize)
4010 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4011 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4013 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4014 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
4015 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4016 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4017 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4018 int32 timeout = IVALS(inbuf,smb_timeout);
4020 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4021 unsigned int tran_call = SVAL(inbuf, smb_setup0);
4022 char *params = NULL, *data = NULL;
4023 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4024 START_PROFILE(SMBtrans2);
4026 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4027 /* Queue this open message as we are the process of an
4030 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4031 DEBUGADD(2,( "in oplock break state.\n"));
4033 push_oplock_pending_smb_message(inbuf, length);
4034 END_PROFILE(SMBtrans2);
4038 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4039 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4040 END_PROFILE(SMBtrans2);
4041 return ERROR_DOS(ERRSRV,ERRaccess);
4044 outsize = set_message(outbuf,0,0,True);
4046 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4047 is so as a sanity check */
4050 * Need to have rc=0 for ioctl to get job id for OS/2.
4051 * Network printing will fail if function is not successful.
4052 * Similar function in reply.c will be used if protocol
4053 * is LANMAN1.0 instead of LM1.2X002.
4054 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4055 * outbuf doesn't have to be set(only job id is used).
4057 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4058 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4059 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4060 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4062 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4063 DEBUG(2,("Transaction is %d\n",tran_call));
4064 END_PROFILE(SMBtrans2);
4065 ERROR_DOS(ERRDOS,ERRinvalidparam);
4069 /* Allocate the space for the maximum needed parameters and data */
4070 if (total_params > 0)
4071 params = (char *)malloc(total_params);
4073 data = (char *)malloc(total_data);
4075 if ((total_params && !params) || (total_data && !data)) {
4076 DEBUG(2,("Out of memory in reply_trans2\n"));
4079 END_PROFILE(SMBtrans2);
4080 return ERROR_DOS(ERRDOS,ERRnomem);
4083 /* Copy the param and data bytes sent with this request into
4084 the params buffer */
4085 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4086 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4088 if (num_params > total_params || num_data > total_data)
4089 exit_server("invalid params in reply_trans2");
4092 unsigned int psoff = SVAL(inbuf, smb_psoff);
4093 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4095 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4096 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4098 memcpy( params, smb_base(inbuf) + psoff, num_params);
4101 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4102 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4104 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4105 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4107 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4110 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4112 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4113 /* We need to send an interim response then receive the rest
4114 of the parameter/data bytes */
4115 outsize = set_message(outbuf,0,0,True);
4116 srv_signing_trans_stop();
4117 if (!send_smb(smbd_server_fd(),outbuf))
4118 exit_server("reply_trans2: send_smb failed.");
4120 while (num_data_sofar < total_data ||
4121 num_params_sofar < total_params) {
4123 unsigned int param_disp;
4124 unsigned int param_off;
4125 unsigned int data_disp;
4126 unsigned int data_off;
4128 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4131 * The sequence number for the trans reply is always
4132 * based on the last secondary received.
4135 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4138 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4139 outsize = set_message(outbuf,0,0,True);
4141 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4143 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4144 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4148 /* Revise total_params and total_data in case
4149 they have changed downwards */
4150 if (SVAL(inbuf, smb_tpscnt) < total_params)
4151 total_params = SVAL(inbuf, smb_tpscnt);
4152 if (SVAL(inbuf, smb_tdscnt) < total_data)
4153 total_data = SVAL(inbuf, smb_tdscnt);
4155 num_params = SVAL(inbuf,smb_spscnt);
4156 param_off = SVAL(inbuf, smb_spsoff);
4157 param_disp = SVAL(inbuf, smb_spsdisp);
4158 num_params_sofar += num_params;
4160 num_data = SVAL(inbuf, smb_sdscnt);
4161 data_off = SVAL(inbuf, smb_sdsoff);
4162 data_disp = SVAL(inbuf, smb_sdsdisp);
4163 num_data_sofar += num_data;
4165 if (num_params_sofar > total_params || num_data_sofar > total_data)
4169 if (param_disp + num_params >= total_params)
4171 if ((param_disp + num_params < param_disp) ||
4172 (param_disp + num_params < num_params))
4174 if (param_disp > total_params)
4176 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4177 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4179 if (params + param_disp < params)
4182 memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
4185 if (data_disp + num_data >= total_data)
4187 if ((data_disp + num_data < data_disp) ||
4188 (data_disp + num_data < num_data))
4190 if (data_disp > total_data)
4192 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4193 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4195 if (data + data_disp < data)
4198 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4203 if (Protocol >= PROTOCOL_NT1) {
4204 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4207 /* Now we must call the relevant TRANS2 function */
4209 case TRANSACT2_OPEN:
4210 START_PROFILE_NESTED(Trans2_open);
4211 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4212 ¶ms, total_params, &data, total_data);
4213 END_PROFILE_NESTED(Trans2_open);
4216 case TRANSACT2_FINDFIRST:
4217 START_PROFILE_NESTED(Trans2_findfirst);
4218 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4219 ¶ms, total_params, &data, total_data);
4220 END_PROFILE_NESTED(Trans2_findfirst);
4223 case TRANSACT2_FINDNEXT:
4224 START_PROFILE_NESTED(Trans2_findnext);
4225 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4226 ¶ms, total_params, &data, total_data);
4227 END_PROFILE_NESTED(Trans2_findnext);
4230 case TRANSACT2_QFSINFO:
4231 START_PROFILE_NESTED(Trans2_qfsinfo);
4232 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4233 ¶ms, total_params, &data, total_data);
4234 END_PROFILE_NESTED(Trans2_qfsinfo);
4237 #ifdef HAVE_SYS_QUOTAS
4238 case TRANSACT2_SETFSINFO:
4239 START_PROFILE_NESTED(Trans2_setfsinfo);
4240 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4241 ¶ms, total_params, &data, total_data);
4242 END_PROFILE_NESTED(Trans2_setfsinfo);
4245 case TRANSACT2_QPATHINFO:
4246 case TRANSACT2_QFILEINFO:
4247 START_PROFILE_NESTED(Trans2_qpathinfo);
4248 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4249 ¶ms, total_params, &data, total_data);
4250 END_PROFILE_NESTED(Trans2_qpathinfo);
4252 case TRANSACT2_SETPATHINFO:
4253 case TRANSACT2_SETFILEINFO:
4254 START_PROFILE_NESTED(Trans2_setpathinfo);
4255 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4256 ¶ms, total_params, &data, total_data);
4257 END_PROFILE_NESTED(Trans2_setpathinfo);
4260 case TRANSACT2_FINDNOTIFYFIRST:
4261 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4262 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4263 ¶ms, total_params, &data, total_data);
4264 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4267 case TRANSACT2_FINDNOTIFYNEXT:
4268 START_PROFILE_NESTED(Trans2_findnotifynext);
4269 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4270 ¶ms, total_params, &data, total_data);
4271 END_PROFILE_NESTED(Trans2_findnotifynext);
4273 case TRANSACT2_MKDIR:
4274 START_PROFILE_NESTED(Trans2_mkdir);
4275 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4276 ¶ms, total_params, &data, total_data);
4277 END_PROFILE_NESTED(Trans2_mkdir);
4280 case TRANSACT2_GET_DFS_REFERRAL:
4281 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4282 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4283 ¶ms, total_params, &data, total_data);
4284 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4286 case TRANSACT2_IOCTL:
4287 START_PROFILE_NESTED(Trans2_ioctl);
4288 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4289 ¶ms, total_params, &data, total_data);
4290 END_PROFILE_NESTED(Trans2_ioctl);
4293 /* Error in request */
4294 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4297 END_PROFILE(SMBtrans2);
4298 srv_signing_trans_stop();
4299 return ERROR_DOS(ERRSRV,ERRerror);
4302 /* As we do not know how many data packets will need to be
4303 returned here the various call_trans2xxxx calls
4304 must send their own. Thus a call_trans2xxx routine only
4305 returns a value other than -1 when it wants to send
4309 srv_signing_trans_stop();
4313 END_PROFILE(SMBtrans2);
4314 return outsize; /* If a correct response was needed the
4315 call_trans2xxx calls have already sent
4316 it. If outsize != -1 then it is returning */
4320 srv_signing_trans_stop();
4323 END_PROFILE(SMBtrans2);
4324 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);