2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2001
6 Extensively modified by Andrew Tridgell, 1995
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 extern BOOL case_sensitive;
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 pstring global_myname;
33 /* given a stat buffer return the allocated size on disk, taking into
34 account sparse files */
35 SMB_OFF_T get_allocation_size(SMB_STRUCT_STAT *sbuf)
38 ret = sbuf->st_blksize * (SMB_OFF_T)sbuf->st_blocks;
39 ret = SMB_ROUNDUP_ALLOCATION(ret);
44 /****************************************************************************
45 Send the required number of replies back.
46 We assume all fields other than the data fields are
47 set correctly for the type of call.
48 HACK ! Always assumes smb_setup field is zero.
49 ****************************************************************************/
51 static int send_trans2_replies(char *outbuf,
58 /* As we are using a protocol > LANMAN1 then the max_send
59 variable must have been set in the sessetupX call.
60 This takes precedence over the max_xmit field in the
61 global struct. These different max_xmit variables should
62 be merged as this is now too confusing */
65 int data_to_send = datasize;
66 int params_to_send = paramsize;
70 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
71 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
72 int data_alignment_offset = 0;
74 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
76 set_message(outbuf,10,0,True);
78 /* If there genuinely are no parameters or data to send just send the empty packet */
80 if(params_to_send == 0 && data_to_send == 0) {
81 if (!send_smb(smbd_server_fd(),outbuf))
82 exit_server("send_trans2_replies: send_smb failed.");
86 /* When sending params and data ensure that both are nicely aligned */
87 /* Only do this alignment when there is also data to send - else
88 can cause NT redirector problems. */
90 if (((params_to_send % 4) != 0) && (data_to_send != 0))
91 data_alignment_offset = 4 - (params_to_send % 4);
93 /* Space is bufsize minus Netbios over TCP header minus SMB header */
94 /* The alignment_offset is to align the param bytes on an even byte
95 boundary. NT 4.0 Beta needs this to work correctly. */
97 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
99 /* useable_space can never be more than max_send minus the alignment offset. */
101 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
103 while (params_to_send || data_to_send) {
104 /* Calculate whether we will totally or partially fill this packet */
106 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
108 /* We can never send more than useable_space */
110 * Note that 'useable_space' does not include the alignment offsets,
111 * but we must include the alignment offsets in the calculation of
112 * the length of the data we send over the wire, as the alignment offsets
113 * are sent here. Fix from Marc_Jacobsen@hp.com.
116 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
118 set_message(outbuf, 10, total_sent_thistime, True);
120 /* Set total params and data to be sent */
121 SSVAL(outbuf,smb_tprcnt,paramsize);
122 SSVAL(outbuf,smb_tdrcnt,datasize);
124 /* Calculate how many parameters and data we can fit into
125 * this packet. Parameters get precedence
128 params_sent_thistime = MIN(params_to_send,useable_space);
129 data_sent_thistime = useable_space - params_sent_thistime;
130 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
132 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
134 /* smb_proff is the offset from the start of the SMB header to the
135 parameter bytes, however the first 4 bytes of outbuf are
136 the Netbios over TCP header. Thus use smb_base() to subtract
137 them from the calculation */
139 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
141 if(params_sent_thistime == 0)
142 SSVAL(outbuf,smb_prdisp,0);
144 /* Absolute displacement of param bytes sent in this packet */
145 SSVAL(outbuf,smb_prdisp,pp - params);
147 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
148 if(data_sent_thistime == 0) {
149 SSVAL(outbuf,smb_droff,0);
150 SSVAL(outbuf,smb_drdisp, 0);
152 /* The offset of the data bytes is the offset of the
153 parameter bytes plus the number of parameters being sent this time */
154 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
155 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
156 SSVAL(outbuf,smb_drdisp, pd - pdata);
159 /* Copy the param bytes into the packet */
161 if(params_sent_thistime)
162 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
164 /* Copy in the data bytes */
165 if(data_sent_thistime)
166 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
167 data_alignment_offset,pd,data_sent_thistime);
169 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
170 params_sent_thistime, data_sent_thistime, useable_space));
171 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
172 params_to_send, data_to_send, paramsize, datasize));
174 /* Send the packet */
175 if (!send_smb(smbd_server_fd(),outbuf))
176 exit_server("send_trans2_replies: send_smb failed.");
178 pp += params_sent_thistime;
179 pd += data_sent_thistime;
181 params_to_send -= params_sent_thistime;
182 data_to_send -= data_sent_thistime;
185 if(params_to_send < 0 || data_to_send < 0) {
186 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
187 params_to_send, data_to_send));
195 /****************************************************************************
196 Reply to a TRANSACT2_OPEN.
197 ****************************************************************************/
199 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
200 char **pparams, int total_params, char **ppdata, int total_data)
202 char *params = *pparams;
207 BOOL return_additional_info;
217 int fmode=0,mtime=0,rmode;
219 SMB_STRUCT_STAT sbuf;
221 BOOL bad_path = False;
225 * Ensure we have enough parameters to perform the operation.
228 if (total_params < 29)
229 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
231 open_mode = SVAL(params, 2);
232 open_attr = SVAL(params,6);
233 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
235 return_additional_info = BITSETW(params,0);
236 open_sattr = SVAL(params, 4);
237 open_time = make_unix_date3(params+8);
239 open_ofun = SVAL(params,12);
240 open_size = IVAL(params,14);
243 srvstr_pull(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE);
245 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
246 fname,open_mode, open_attr, open_ofun, open_size));
249 return(ERROR_DOS(ERRSRV,ERRaccess));
251 /* XXXX we need to handle passed times, sattr and flags */
253 unix_convert(fname,conn,0,&bad_path,&sbuf);
255 if (!check_name(fname,conn)) {
256 set_bad_path_error(errno, bad_path);
257 return(UNIXERROR(ERRDOS,ERRnoaccess));
260 unixmode = unix_mode(conn,open_attr | aARCH, fname);
262 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode,
263 oplock_request, &rmode,&smb_action);
266 set_bad_path_error(errno, bad_path);
267 return(UNIXERROR(ERRDOS,ERRnoaccess));
271 fmode = dos_mode(conn,fname,&sbuf);
272 mtime = sbuf.st_mtime;
275 close_file(fsp,False);
276 return(ERROR_DOS(ERRDOS,ERRnoaccess));
279 /* Realloc the size of parameters and data we will return */
280 params = Realloc(*pparams, 28);
282 return(ERROR_DOS(ERRDOS,ERRnomem));
285 memset((char *)params,'\0',28);
286 SSVAL(params,0,fsp->fnum);
287 SSVAL(params,2,fmode);
288 put_dos_date2(params,4, mtime);
289 SIVAL(params,8, (uint32)size);
290 SSVAL(params,12,rmode);
292 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
293 smb_action |= EXTENDED_OPLOCK_GRANTED;
295 SSVAL(params,18,smb_action);
298 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
300 SIVAL(params,20,inode);
302 /* Send the required number of replies */
303 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
308 /*********************************************************
309 Routine to check if a given string matches exactly.
310 as a special case a mask of "." does NOT match. That
311 is required for correct wildcard semantics
312 Case can be significant or not.
313 **********************************************************/
315 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
317 if (mask[0] == '.' && mask[1] == 0)
320 return strcmp(str,mask)==0;
321 return strcasecmp(str,mask) == 0;
324 /****************************************************************************
325 Return the filetype for UNIX extensions.
326 ****************************************************************************/
328 static uint32 unix_filetype(mode_t mode)
331 return UNIX_TYPE_FILE;
332 else if(S_ISDIR(mode))
333 return UNIX_TYPE_DIR;
335 else if(S_ISLNK(mode))
336 return UNIX_TYPE_SYMLINK;
339 else if(S_ISCHR(mode))
340 return UNIX_TYPE_CHARDEV;
343 else if(S_ISBLK(mode))
344 return UNIX_TYPE_BLKDEV;
347 else if(S_ISFIFO(mode))
348 return UNIX_TYPE_FIFO;
351 else if(S_ISSOCK(mode))
352 return UNIX_TYPE_SOCKET;
355 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
356 return UNIX_TYPE_UNKNOWN;
359 /****************************************************************************
360 Return the major devicenumber for UNIX extensions.
361 ****************************************************************************/
363 static uint32 unix_dev_major(SMB_DEV_T dev)
365 #if defined(HAVE_DEVICE_MAJOR_FN)
366 return (uint32)major(dev);
368 return (uint32)(dev >> 8);
372 /****************************************************************************
373 Return the minor devicenumber for UNIX extensions.
374 ****************************************************************************/
376 static uint32 unix_dev_minor(SMB_DEV_T dev)
378 #if defined(HAVE_DEVICE_MINOR_FN)
379 return (uint32)minor(dev);
381 return (uint32)(dev & 0xff);
385 /****************************************************************************
386 Map wire perms onto standard UNIX permissions. Obey share restrictions.
387 ****************************************************************************/
389 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
393 if (perms == SMB_MODE_NO_CHANGE)
396 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
397 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
398 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
399 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
400 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
401 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
402 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
403 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
404 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
406 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
409 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
412 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
415 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
416 ret &= lp_dir_mask(SNUM(conn));
417 /* Add in force bits */
418 ret |= lp_force_dir_mode(SNUM(conn));
420 /* Apply mode mask */
421 ret &= lp_create_mask(SNUM(conn));
422 /* Add in force bits */
423 ret |= lp_force_create_mode(SNUM(conn));
429 /****************************************************************************
430 checks for SMB_TIME_NO_CHANGE and if not found
431 calls interpret_long_date
432 ****************************************************************************/
433 time_t interpret_long_unix_date(char *p)
435 DEBUG(1,("interpret_long_unix_date\n"));
436 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
437 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
440 return interpret_long_date(p);
444 /****************************************************************************
445 Get a level dependent lanman2 dir entry.
446 ****************************************************************************/
448 static BOOL get_lanman2_dir_entry(connection_struct *conn,
449 void *inbuf, void *outbuf,
450 char *path_mask,int dirtype,int info_level,
451 int requires_resume_key,
452 BOOL dont_descend,char **ppdata,
453 char *base_data, int space_remaining,
454 BOOL *out_of_space, BOOL *got_exact_match,
459 SMB_STRUCT_STAT sbuf;
463 char *p, *q, *pdata = *ppdata;
468 SMB_OFF_T allocation_size = 0;
470 time_t mdate=0, adate=0, cdate=0;
473 int nt_extmode; /* Used for NT connections instead of mode */
474 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
477 *out_of_space = False;
478 *got_exact_match = False;
483 p = strrchr_m(path_mask,'/');
490 pstrcpy(mask, path_mask);
495 /* Needed if we run out of space */
496 prev_dirpos = TellDir(conn->dirptr);
497 dname = ReadDirName(conn->dirptr);
500 * Due to bugs in NT client redirectors we are not using
501 * resume keys any more - set them to zero.
502 * Check out the related comments in findfirst/findnext.
508 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
509 (long)conn->dirptr,TellDir(conn->dirptr)));
514 pstrcpy(fname,dname);
516 if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
517 got_match = mask_match(fname, mask, case_sensitive);
519 if(!got_match && !mangle_is_8_3(fname, False)) {
522 * It turns out that NT matches wildcards against
523 * both long *and* short names. This may explain some
524 * of the wildcard wierdness from old DOS clients
525 * that some people have been seeing.... JRA.
529 pstrcpy( newname, fname);
530 mangle_map( newname, True, False, SNUM(conn));
531 if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
532 got_match = mask_match(newname, mask, case_sensitive);
536 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
537 if (dont_descend && !isdots)
540 pstrcpy(pathreal,conn->dirpath);
542 pstrcat(pathreal,"/");
543 pstrcat(pathreal,dname);
545 if (INFO_LEVEL_IS_UNIX(info_level)) {
546 if (vfs_lstat(conn,pathreal,&sbuf) != 0) {
547 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
548 pathreal,strerror(errno)));
551 } else if (vfs_stat(conn,pathreal,&sbuf) != 0) {
553 /* Needed to show the msdfs symlinks as
556 if(lp_host_msdfs() &&
557 lp_msdfs_root(SNUM(conn)) &&
558 is_msdfs_link(conn, pathreal, NULL, NULL,
561 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
562 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
566 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
567 pathreal,strerror(errno)));
572 mode = dos_mode(conn,pathreal,&sbuf);
574 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
575 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
580 allocation_size = get_allocation_size(&sbuf);
581 mdate = sbuf.st_mtime;
582 adate = sbuf.st_atime;
583 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
585 if (lp_dos_filetime_resolution(SNUM(conn))) {
594 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
600 mangle_map(fname,False,True,SNUM(conn));
605 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
607 switch (info_level) {
608 case SMB_INFO_STANDARD:
609 if(requires_resume_key) {
613 put_dos_date2(p,l1_fdateCreation,cdate);
614 put_dos_date2(p,l1_fdateLastAccess,adate);
615 put_dos_date2(p,l1_fdateLastWrite,mdate);
616 SIVAL(p,l1_cbFile,(uint32)size);
617 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
618 SSVAL(p,l1_attrFile,mode);
621 p += align_string(outbuf, p, 0);
622 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
623 SCVAL(nameptr, -1, len);
627 case SMB_INFO_QUERY_EA_SIZE:
628 if(requires_resume_key) {
632 put_dos_date2(p,l2_fdateCreation,cdate);
633 put_dos_date2(p,l2_fdateLastAccess,adate);
634 put_dos_date2(p,l2_fdateLastWrite,mdate);
635 SIVAL(p,l2_cbFile,(uint32)size);
636 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
637 SSVAL(p,l2_attrFile,mode);
638 SIVAL(p,l2_cbList,0); /* No extended attributes */
641 len = srvstr_push(outbuf, p, fname, -1, STR_NOALIGN);
644 *p++ = 0; /* craig from unisys pointed out we need this */
647 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
648 was_8_3 = mangle_is_8_3(fname, True);
650 SIVAL(p,0,reskey); p += 4;
651 put_long_date(p,cdate); p += 8;
652 put_long_date(p,adate); p += 8;
653 put_long_date(p,mdate); p += 8;
654 put_long_date(p,mdate); p += 8;
656 SOFF_T(p,8,allocation_size);
658 SIVAL(p,0,nt_extmode); p += 4;
660 SIVAL(p,0,0); p += 4;
662 pstring mangled_name;
663 pstrcpy(mangled_name, fname);
664 mangle_map(mangled_name,True,True,SNUM(conn));
665 mangled_name[12] = 0;
666 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER);
673 len = srvstr_push(outbuf, p, fname, -1, 0);
676 len = PTR_DIFF(p, pdata);
677 len = (len + 3) & ~3;
682 case SMB_FIND_FILE_DIRECTORY_INFO:
684 SIVAL(p,0,reskey); p += 4;
685 put_long_date(p,cdate); p += 8;
686 put_long_date(p,adate); p += 8;
687 put_long_date(p,mdate); p += 8;
688 put_long_date(p,mdate); p += 8;
690 SOFF_T(p,8,allocation_size);
692 SIVAL(p,0,nt_extmode); p += 4;
694 len = srvstr_push(outbuf, p, fname, -1, 0);
697 len = PTR_DIFF(p, pdata);
698 len = (len + 3) & ~3;
703 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
705 SIVAL(p,0,reskey); p += 4;
706 put_long_date(p,cdate); p += 8;
707 put_long_date(p,adate); p += 8;
708 put_long_date(p,mdate); p += 8;
709 put_long_date(p,mdate); p += 8;
711 SOFF_T(p,8,allocation_size);
713 SIVAL(p,0,nt_extmode); p += 4;
715 SIVAL(p,0,0); p += 4;
717 len = srvstr_push(outbuf, p, fname, -1, 0);
721 len = PTR_DIFF(p, pdata);
722 len = (len + 3) & ~3;
727 case SMB_FIND_FILE_NAMES_INFO:
729 SIVAL(p,0,reskey); p += 4;
731 /* this must *not* be null terminated or w2k gets in a loop trying to set an
732 acl on a dir (tridge) */
733 len = srvstr_push(outbuf, p, fname, -1, 0);
736 len = PTR_DIFF(p, pdata);
737 len = (len + 3) & ~3;
742 /* CIFS UNIX Extension. */
744 case SMB_FIND_FILE_UNIX:
746 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
748 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
749 SOFF_T(p,0,sbuf.st_size); /* File size 64 Bit */
752 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
753 SOFF_T(p,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */
755 /* Can't get the value - fake it using size. */
756 SOFF_T(p,0,sbuf.st_size); /* Number of bytes used on disk - 64 Bit */
760 put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */
761 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
762 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
765 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
769 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
773 SIVAL(p,0,unix_filetype(sbuf.st_mode));
776 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
780 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
784 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
787 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
791 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
795 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
798 len = PTR_DIFF(p, pdata);
799 len = (len + 3) & ~3;
800 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
802 /* End of SMB_QUERY_FILE_UNIX_BASIC */
811 if (PTR_DIFF(p,pdata) > space_remaining) {
812 /* Move the dirptr back to prev_dirpos */
813 SeekDir(conn->dirptr, prev_dirpos);
814 *out_of_space = True;
815 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
816 return False; /* Not finished - just out of space */
819 /* Setup the last_filename pointer, as an offset from base_data */
820 *last_name_off = PTR_DIFF(nameptr,base_data);
821 /* Advance the data pointer to the next slot */
827 /****************************************************************************
828 Reply to a TRANS2_FINDFIRST.
829 ****************************************************************************/
831 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
832 char **pparams, int total_params, char **ppdata, int total_data)
834 /* We must be careful here that we don't return more than the
835 allowed number of data bytes. If this means returning fewer than
836 maxentries then so be it. We assume that the redirector has
837 enough room for the fixed number of parameter bytes it has
839 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
840 char *params = *pparams;
841 char *pdata = *ppdata;
842 int dirtype = SVAL(params,0);
843 int maxentries = SVAL(params,2);
844 BOOL close_after_first = BITSETW(params+4,0);
845 BOOL close_if_end = BITSETW(params+4,1);
846 BOOL requires_resume_key = BITSETW(params+4,2);
847 int info_level = SVAL(params,6);
855 BOOL finished = False;
856 BOOL dont_descend = False;
857 BOOL out_of_space = False;
859 BOOL bad_path = False;
860 SMB_STRUCT_STAT sbuf;
862 if (total_params < 12)
863 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
865 *directory = *mask = 0;
867 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
868 close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
869 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
870 info_level, max_data_bytes));
872 switch (info_level) {
873 case SMB_INFO_STANDARD:
874 case SMB_INFO_QUERY_EA_SIZE:
875 case SMB_FIND_FILE_DIRECTORY_INFO:
876 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
877 case SMB_FIND_FILE_NAMES_INFO:
878 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
880 case SMB_FIND_FILE_UNIX:
881 if (!lp_unix_extensions())
882 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
885 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
888 srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE);
890 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
892 unix_convert(directory,conn,0,&bad_path,&sbuf);
893 if(!check_name(directory,conn)) {
894 set_bad_path_error(errno, bad_path);
895 return(UNIXERROR(ERRDOS,ERRbadpath));
898 p = strrchr_m(directory,'/');
900 pstrcpy(mask,directory);
901 pstrcpy(directory,"./");
907 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
909 pdata = Realloc(*ppdata, max_data_bytes + 1024);
911 return(ERROR_DOS(ERRDOS,ERRnomem));
914 memset((char *)pdata,'\0',max_data_bytes + 1024);
916 /* Realloc the params space */
917 params = Realloc(*pparams, 10);
919 return ERROR_DOS(ERRDOS,ERRnomem);
922 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
924 return(UNIXERROR(ERRDOS,ERRbadfile));
926 /* Save the wildcard match and attribs we are using on this directory -
927 needed as lanman2 assumes these are being saved between calls */
929 if(!(wcard = strdup(mask))) {
930 dptr_close(&dptr_num);
931 return ERROR_DOS(ERRDOS,ERRnomem);
934 dptr_set_wcard(dptr_num, wcard);
935 dptr_set_attr(dptr_num, dirtype);
937 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
939 /* We don't need to check for VOL here as this is returned by
940 a different TRANS2 call. */
942 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
943 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
947 space_remaining = max_data_bytes;
948 out_of_space = False;
950 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
951 BOOL got_exact_match = False;
953 /* this is a heuristic to avoid seeking the dirptr except when
954 absolutely necessary. It allows for a filename of about 40 chars */
955 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
959 finished = !get_lanman2_dir_entry(conn,
961 mask,dirtype,info_level,
962 requires_resume_key,dont_descend,
963 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
967 if (finished && out_of_space)
970 if (!finished && !out_of_space)
974 * As an optimisation if we know we aren't looking
975 * for a wildcard name (ie. the name matches the wildcard exactly)
976 * then we can finish on any (first) match.
977 * This speeds up large directory searches. JRA.
983 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
986 /* Check if we can close the dirptr */
987 if(close_after_first || (finished && close_if_end)) {
988 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
989 dptr_close(&dptr_num);
993 * If there are no matching entries we must return ERRDOS/ERRbadfile -
994 * from observation of NT.
997 if(numentries == 0) {
998 dptr_close(&dptr_num);
999 return ERROR_DOS(ERRDOS,ERRbadfile);
1002 /* At this point pdata points to numentries directory entries. */
1004 /* Set up the return parameter block */
1005 SSVAL(params,0,dptr_num);
1006 SSVAL(params,2,numentries);
1007 SSVAL(params,4,finished);
1008 SSVAL(params,6,0); /* Never an EA error */
1009 SSVAL(params,8,last_name_off);
1011 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1013 if ((! *directory) && dptr_path(dptr_num))
1014 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1016 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1017 smb_fn_name(CVAL(inbuf,smb_com)),
1018 mask, directory, dirtype, numentries ) );
1021 * Force a name mangle here to ensure that the
1022 * mask as an 8.3 name is top of the mangled cache.
1023 * The reasons for this are subtle. Don't remove
1024 * this code unless you know what you are doing
1025 * (see PR#13758). JRA.
1028 if(!mangle_is_8_3_wildcards( mask, False))
1029 mangle_map(mask, True, True, SNUM(conn));
1034 /****************************************************************************
1035 Reply to a TRANS2_FINDNEXT.
1036 ****************************************************************************/
1038 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1039 char **pparams, int total_params, char **ppdata, int total_data)
1041 /* We must be careful here that we don't return more than the
1042 allowed number of data bytes. If this means returning fewer than
1043 maxentries then so be it. We assume that the redirector has
1044 enough room for the fixed number of parameter bytes it has
1046 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1047 char *params = *pparams;
1048 char *pdata = *ppdata;
1049 int dptr_num = SVAL(params,0);
1050 int maxentries = SVAL(params,2);
1051 uint16 info_level = SVAL(params,4);
1052 uint32 resume_key = IVAL(params,6);
1053 BOOL close_after_request = BITSETW(params+10,0);
1054 BOOL close_if_end = BITSETW(params+10,1);
1055 BOOL requires_resume_key = BITSETW(params+10,2);
1056 BOOL continue_bit = BITSETW(params+10,3);
1057 pstring resume_name;
1063 int i, last_name_off=0;
1064 BOOL finished = False;
1065 BOOL dont_descend = False;
1066 BOOL out_of_space = False;
1067 int space_remaining;
1069 if (total_params < 12)
1070 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1072 *mask = *directory = *resume_name = 0;
1074 srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE);
1076 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1077 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1078 resume_key = %d resume name = %s continue=%d level = %d\n",
1079 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1080 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1082 switch (info_level) {
1083 case SMB_INFO_STANDARD:
1084 case SMB_INFO_QUERY_EA_SIZE:
1085 case SMB_FIND_FILE_DIRECTORY_INFO:
1086 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1087 case SMB_FIND_FILE_NAMES_INFO:
1088 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1090 case SMB_FIND_FILE_UNIX:
1091 if (!lp_unix_extensions())
1092 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1095 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1098 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1100 return ERROR_DOS(ERRDOS,ERRnomem);
1103 memset((char *)pdata,'\0',max_data_bytes + 1024);
1105 /* Realloc the params space */
1106 params = Realloc(*pparams, 6*SIZEOFWORD);
1107 if( params == NULL )
1108 return ERROR_DOS(ERRDOS,ERRnomem);
1112 /* Check that the dptr is valid */
1113 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1114 return ERROR_DOS(ERRDOS,ERRnofiles);
1116 string_set(&conn->dirpath,dptr_path(dptr_num));
1118 /* Get the wildcard mask from the dptr */
1119 if((p = dptr_wcard(dptr_num))== NULL) {
1120 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1121 return ERROR_DOS(ERRDOS,ERRnofiles);
1125 pstrcpy(directory,conn->dirpath);
1127 /* Get the attr mask from the dptr */
1128 dirtype = dptr_attr(dptr_num);
1130 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1131 dptr_num, mask, dirtype,
1133 TellDir(conn->dirptr)));
1135 /* We don't need to check for VOL here as this is returned by
1136 a different TRANS2 call. */
1138 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1139 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1140 dont_descend = True;
1143 space_remaining = max_data_bytes;
1144 out_of_space = False;
1147 * Seek to the correct position. We no longer use the resume key but
1148 * depend on the last file name instead.
1151 if(requires_resume_key && *resume_name && !continue_bit) {
1154 * Fix for NT redirector problem triggered by resume key indexes
1155 * changing between directory scans. We now return a resume key of 0
1156 * and instead look for the filename to continue from (also given
1157 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1158 * findfirst/findnext (as is usual) then the directory pointer
1159 * should already be at the correct place. Check this by scanning
1160 * backwards looking for an exact (ie. case sensitive) filename match.
1161 * If we get to the beginning of the directory and haven't found it then scan
1162 * forwards again looking for a match. JRA.
1165 int current_pos, start_pos;
1167 void *dirptr = conn->dirptr;
1168 start_pos = TellDir(dirptr);
1169 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1170 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1172 SeekDir(dirptr, current_pos);
1173 dname = ReadDirName(dirptr);
1176 * Remember, mangle_map is called by
1177 * get_lanman2_dir_entry(), so the resume name
1178 * could be mangled. Ensure we do the same
1183 mangle_map( dname, False, True, SNUM(conn));
1185 if(dname && strcsequal( resume_name, dname)) {
1186 SeekDir(dirptr, current_pos+1);
1187 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1193 * Scan forward from start if not found going backwards.
1196 if(current_pos < 0) {
1197 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1198 SeekDir(dirptr, start_pos);
1199 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1202 * Remember, mangle_map is called by
1203 * get_lanman2_dir_entry(), so the resume name
1204 * could be mangled. Ensure we do the same
1209 mangle_map( dname, False, True, SNUM(conn));
1211 if(dname && strcsequal( resume_name, dname)) {
1212 SeekDir(dirptr, current_pos+1);
1213 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1217 } /* end if current_pos */
1218 } /* end if requires_resume_key && !continue_bit */
1220 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1221 BOOL got_exact_match = False;
1223 /* this is a heuristic to avoid seeking the dirptr except when
1224 absolutely necessary. It allows for a filename of about 40 chars */
1225 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1226 out_of_space = True;
1229 finished = !get_lanman2_dir_entry(conn,
1231 mask,dirtype,info_level,
1232 requires_resume_key,dont_descend,
1233 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1237 if (finished && out_of_space)
1240 if (!finished && !out_of_space)
1244 * As an optimisation if we know we aren't looking
1245 * for a wildcard name (ie. the name matches the wildcard exactly)
1246 * then we can finish on any (first) match.
1247 * This speeds up large directory searches. JRA.
1253 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1256 /* Check if we can close the dirptr */
1257 if(close_after_request || (finished && close_if_end)) {
1258 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1259 dptr_close(&dptr_num); /* This frees up the saved mask */
1263 /* Set up the return parameter block */
1264 SSVAL(params,0,numentries);
1265 SSVAL(params,2,finished);
1266 SSVAL(params,4,0); /* Never an EA error */
1267 SSVAL(params,6,last_name_off);
1269 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1271 if ((! *directory) && dptr_path(dptr_num))
1272 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1274 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1275 smb_fn_name(CVAL(inbuf,smb_com)),
1276 mask, directory, dirtype, numentries ) );
1281 /****************************************************************************
1282 Reply to a TRANS2_QFSINFO (query filesystem info).
1283 ****************************************************************************/
1285 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1286 int length, int bufsize,
1287 char **pparams, int total_params, char **ppdata, int total_data)
1289 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1290 char *pdata = *ppdata;
1291 char *params = *pparams;
1292 uint16 info_level = SVAL(params,0);
1295 char *vname = volume_label(SNUM(conn));
1296 int snum = SNUM(conn);
1297 char *fstype = lp_fstype(SNUM(conn));
1299 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1301 if(vfs_stat(conn,".",&st)!=0) {
1302 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1303 return ERROR_DOS(ERRSRV,ERRinvdevice);
1306 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1307 if ( pdata == NULL )
1308 return ERROR_DOS(ERRDOS,ERRnomem);
1311 memset((char *)pdata,'\0',max_data_bytes + 1024);
1313 switch (info_level) {
1314 case SMB_INFO_ALLOCATION:
1316 SMB_BIG_UINT dfree,dsize,bsize;
1318 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1319 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1320 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1321 SIVAL(pdata,l1_cUnit,dsize);
1322 SIVAL(pdata,l1_cUnitAvail,dfree);
1323 SSVAL(pdata,l1_cbSector,512);
1324 DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1325 (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1326 (unsigned int)dfree, 512));
1330 case SMB_INFO_VOLUME:
1331 /* Return volume name */
1333 * Add volume serial number - hash of a combination of
1334 * the called hostname and the service name.
1336 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1337 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_TERMINATE);
1338 SCVAL(pdata,l2_vol_cch,len);
1339 data_len = l2_vol_szVolLabel + len;
1340 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1341 (unsigned)st.st_ctime, len, vname));
1344 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1345 case SMB_FS_ATTRIBUTE_INFORMATION:
1347 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1348 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */
1349 SIVAL(pdata,4,255); /* Max filename component length */
1350 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1351 and will think we can't do long filenames */
1352 len = srvstr_push(outbuf, pdata+12, fstype, -1, 0);
1354 data_len = 12 + len;
1357 case SMB_QUERY_FS_LABEL_INFO:
1358 case SMB_FS_LABEL_INFORMATION:
1359 len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE);
1364 case SMB_QUERY_FS_VOLUME_INFO:
1365 case SMB_FS_VOLUME_INFORMATION:
1368 * Add volume serial number - hash of a combination of
1369 * the called hostname and the service name.
1371 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1372 (str_checksum(local_machine)<<16));
1374 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE);
1375 SIVAL(pdata,12,len);
1377 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1378 (int)strlen(vname),vname, lp_servicename(snum)));
1381 case SMB_QUERY_FS_SIZE_INFO:
1382 case SMB_FS_SIZE_INFORMATION:
1384 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1386 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1387 block_size = lp_block_size(snum);
1388 if (bsize < block_size) {
1389 SMB_BIG_UINT factor = block_size/bsize;
1394 if (bsize > block_size) {
1395 SMB_BIG_UINT factor = bsize/block_size;
1400 bytes_per_sector = 512;
1401 sectors_per_unit = bsize/bytes_per_sector;
1402 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1403 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1404 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1405 SBIG_UINT(pdata,0,dsize);
1406 SBIG_UINT(pdata,8,dfree);
1407 SIVAL(pdata,16,sectors_per_unit);
1408 SIVAL(pdata,20,bytes_per_sector);
1412 case SMB_FS_FULL_SIZE_INFORMATION:
1414 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1416 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1417 block_size = lp_block_size(snum);
1418 if (bsize < block_size) {
1419 SMB_BIG_UINT factor = block_size/bsize;
1424 if (bsize > block_size) {
1425 SMB_BIG_UINT factor = bsize/block_size;
1430 bytes_per_sector = 512;
1431 sectors_per_unit = bsize/bytes_per_sector;
1432 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1433 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1434 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1435 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1436 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1437 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1438 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1439 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1443 case SMB_QUERY_FS_DEVICE_INFO:
1444 case SMB_FS_DEVICE_INFORMATION:
1446 SIVAL(pdata,0,0); /* dev type */
1447 SIVAL(pdata,4,0); /* characteristics */
1450 case SMB_FS_OBJECTID_INFORMATION:
1455 * Query the version and capabilities of the CIFS UNIX extensions
1459 case SMB_QUERY_CIFS_UNIX_INFO:
1460 if (!lp_unix_extensions())
1461 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1463 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
1464 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
1465 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
1468 case SMB_MAC_QUERY_FS_INFO:
1470 * Thursby MAC extension... ONLY on NTFS filesystems
1471 * once we do streams then we don't need this
1473 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1475 SIVAL(pdata,84,0x100); /* Don't support mac... */
1480 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1484 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1486 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1491 /****************************************************************************
1492 Reply to a TRANS2_SETFSINFO (set filesystem info).
1493 ****************************************************************************/
1495 static int call_trans2setfsinfo(connection_struct *conn,
1496 char *inbuf, char *outbuf, int length, int bufsize,
1497 char **pparams, int total_params, char **ppdata, int total_data)
1499 /* Just say yes we did it - there is nothing that
1500 can be set here so it doesn't matter. */
1502 DEBUG(3,("call_trans2setfsinfo\n"));
1504 if (!CAN_WRITE(conn))
1505 return ERROR_DOS(ERRSRV,ERRaccess);
1507 outsize = set_message(outbuf,10,0,True);
1512 /****************************************************************************
1513 * Utility function to set bad path error.
1514 ****************************************************************************/
1516 NTSTATUS set_bad_path_error(int err, BOOL bad_path)
1518 if((err == ENOENT) && bad_path) {
1519 unix_ERR_class = ERRDOS;
1520 unix_ERR_code = ERRbadpath;
1521 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1523 return NT_STATUS_OK;
1526 /****************************************************************************
1527 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1528 file name or file id).
1529 ****************************************************************************/
1531 static int call_trans2qfilepathinfo(connection_struct *conn,
1532 char *inbuf, char *outbuf, int length,
1534 char **pparams, int total_params, char **ppdata, int total_data)
1536 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1537 char *params = *pparams;
1538 char *pdata = *ppdata;
1539 uint16 tran_call = SVAL(inbuf, smb_setup0);
1542 SMB_OFF_T file_size=0;
1543 SMB_OFF_T allocation_size=0;
1544 unsigned int data_size;
1545 SMB_STRUCT_STAT sbuf;
1546 pstring fname, dos_fname;
1551 BOOL bad_path = False;
1552 BOOL delete_pending = False;
1557 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1559 if (tran_call == TRANSACT2_QFILEINFO) {
1560 files_struct *fsp = file_fsp(params,0);
1561 info_level = SVAL(params,2);
1563 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1565 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1567 * This is actually a QFILEINFO on a directory
1568 * handle (returned from an NT SMB). NT5.0 seems
1569 * to do this call. JRA.
1571 pstrcpy(fname, fsp->fsp_name);
1572 unix_convert(fname,conn,0,&bad_path,&sbuf);
1573 if (!check_name(fname,conn)) {
1574 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1575 set_bad_path_error(errno, bad_path);
1576 return(UNIXERROR(ERRDOS,ERRbadpath));
1579 if (INFO_LEVEL_IS_UNIX(info_level)) {
1580 /* Always do lstat for UNIX calls. */
1581 if (vfs_lstat(conn,fname,&sbuf)) {
1582 DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
1583 set_bad_path_error(errno, bad_path);
1584 return(UNIXERROR(ERRDOS,ERRbadpath));
1586 } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
1587 DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
1588 set_bad_path_error(errno, bad_path);
1589 return(UNIXERROR(ERRDOS,ERRbadpath));
1592 delete_pending = fsp->directory_delete_on_close;
1595 * Original code - this is an open file.
1597 CHECK_FSP(fsp,conn);
1599 pstrcpy(fname, fsp->fsp_name);
1600 if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) {
1601 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
1602 return(UNIXERROR(ERRDOS,ERRbadfid));
1604 if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1605 return(UNIXERROR(ERRDOS,ERRnoaccess));
1607 delete_pending = fsp->delete_on_close;
1611 if (total_params < 6)
1612 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1614 info_level = SVAL(params,0);
1616 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1618 srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE);
1620 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1622 unix_convert(fname,conn,0,&bad_path,&sbuf);
1623 if (!check_name(fname,conn)) {
1624 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1625 set_bad_path_error(errno, bad_path);
1626 return(UNIXERROR(ERRDOS,ERRbadpath));
1629 if (INFO_LEVEL_IS_UNIX(info_level)) {
1630 /* Always do lstat for UNIX calls. */
1631 if (vfs_lstat(conn,fname,&sbuf)) {
1632 DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
1633 set_bad_path_error(errno, bad_path);
1634 return(UNIXERROR(ERRDOS,ERRbadpath));
1636 } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
1637 DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
1638 set_bad_path_error(errno, bad_path);
1639 return(UNIXERROR(ERRDOS,ERRbadpath));
1643 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
1644 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1646 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1647 fname,info_level,tran_call,total_data));
1649 p = strrchr_m(fname,'/');
1655 mode = dos_mode(conn,fname,&sbuf);
1656 fullpathname = fname;
1657 file_size = sbuf.st_size;
1658 allocation_size = get_allocation_size(&sbuf);
1662 params = Realloc(*pparams,2);
1664 return ERROR_DOS(ERRDOS,ERRnomem);
1666 memset((char *)params,'\0',2);
1667 data_size = max_data_bytes + 1024;
1668 pdata = Realloc(*ppdata, data_size);
1669 if ( pdata == NULL )
1670 return ERROR_DOS(ERRDOS,ERRnomem);
1673 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1674 /* uggh, EAs for OS2 */
1675 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1676 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1679 memset((char *)pdata,'\0',data_size);
1681 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1683 if (lp_dos_filetime_resolution(SNUM(conn))) {
1685 sbuf.st_atime &= ~1;
1686 sbuf.st_mtime &= ~1;
1687 sbuf.st_mtime &= ~1;
1690 /* NT expects the name to be in an exact form of the *full*
1691 filename. See the trans2 torture test */
1692 if (strequal(base_name,".")) {
1693 pstrcpy(dos_fname, "\\");
1695 snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname);
1696 string_replace(dos_fname, '/', '\\');
1699 switch (info_level) {
1700 case SMB_INFO_STANDARD:
1701 case SMB_INFO_QUERY_EA_SIZE:
1702 data_size = (info_level==1?22:26);
1703 put_dos_date2(pdata,l1_fdateCreation,c_time);
1704 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1705 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1706 SIVAL(pdata,l1_cbFile,(uint32)file_size);
1707 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
1708 SSVAL(pdata,l1_attrFile,mode);
1709 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1712 case SMB_INFO_QUERY_EAS_FROM_LIST:
1714 put_dos_date2(pdata,0,c_time);
1715 put_dos_date2(pdata,4,sbuf.st_atime);
1716 put_dos_date2(pdata,8,sbuf.st_mtime);
1717 SIVAL(pdata,12,(uint32)file_size);
1718 SIVAL(pdata,16,(uint32)allocation_size);
1719 SIVAL(pdata,20,mode);
1722 case SMB_INFO_QUERY_ALL_EAS:
1724 SIVAL(pdata,0,data_size);
1728 return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */
1730 case SMB_FILE_BASIC_INFORMATION:
1731 case SMB_QUERY_FILE_BASIC_INFO:
1733 if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1734 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1739 put_long_date(pdata,c_time);
1740 put_long_date(pdata+8,sbuf.st_atime);
1741 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1742 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1743 SIVAL(pdata,32,mode);
1745 DEBUG(5,("SMB_QFBI - "));
1747 time_t create_time = c_time;
1748 DEBUG(5,("create: %s ", ctime(&create_time)));
1750 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1751 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1752 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1753 DEBUG(5,("mode: %x\n", mode));
1757 case SMB_FILE_STANDARD_INFORMATION:
1758 case SMB_QUERY_FILE_STANDARD_INFO:
1761 SOFF_T(pdata,0,allocation_size);
1762 SOFF_T(pdata,8,file_size);
1763 SIVAL(pdata,16,sbuf.st_nlink);
1765 SCVAL(pdata,21,(mode&aDIR)?1:0);
1768 case SMB_FILE_EA_INFORMATION:
1769 case SMB_QUERY_FILE_EA_INFO:
1773 /* Get the 8.3 name - used if NT SMB was negotiated. */
1774 case SMB_QUERY_FILE_ALT_NAME_INFO:
1778 pstrcpy(short_name,base_name);
1779 /* Mangle if not already 8.3 */
1780 if(!mangle_is_8_3(short_name, True)) {
1781 mangle_map(short_name,True,True,SNUM(conn));
1783 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_TERMINATE|STR_UPPER);
1784 data_size = 4 + len;
1789 case SMB_QUERY_FILE_NAME_INFO:
1791 this must be *exactly* right for ACLs on mapped drives to work
1793 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
1794 data_size = 4 + len;
1798 case SMB_FILE_ALLOCATION_INFORMATION:
1799 case SMB_QUERY_FILE_ALLOCATION_INFO:
1801 SOFF_T(pdata,0,allocation_size);
1804 case SMB_FILE_END_OF_FILE_INFORMATION:
1805 case SMB_QUERY_FILE_END_OF_FILEINFO:
1807 SOFF_T(pdata,0,file_size);
1810 case SMB_QUERY_FILE_ALL_INFO:
1811 put_long_date(pdata,c_time);
1812 put_long_date(pdata+8,sbuf.st_atime);
1813 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1814 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1815 SIVAL(pdata,32,mode);
1817 SOFF_T(pdata,0,allocation_size);
1818 SOFF_T(pdata,8,file_size);
1819 SIVAL(pdata,16,sbuf.st_nlink);
1820 SCVAL(pdata,20,delete_pending);
1821 SCVAL(pdata,21,(mode&aDIR)?1:0);
1823 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);
1824 pdata += 8; /* index number */
1825 pdata += 4; /* EA info */
1827 SIVAL(pdata,0,0xA9);
1829 SIVAL(pdata,0,0xd01BF);
1831 SOFF_T(pdata,0,pos); /* current offset */
1833 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1835 pdata += 4; /* alignment */
1836 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_TERMINATE);
1839 data_size = PTR_DIFF(pdata,(*ppdata));
1842 case SMB_FILE_INTERNAL_INFORMATION:
1843 /* This should be an index number - looks like dev/ino to me :-) */
1844 SIVAL(pdata,0,sbuf.st_dev);
1845 SIVAL(pdata,4,sbuf.st_ino);
1849 case SMB_FILE_ACCESS_INFORMATION:
1850 SIVAL(pdata,0,0x12019F); /* ??? */
1854 case SMB_FILE_NAME_INFORMATION:
1855 /* Pathname with leading '\'. */
1858 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
1859 SIVAL(pdata,0,byte_len);
1860 data_size = 4 + byte_len;
1864 case SMB_FILE_DISPOSITION_INFORMATION:
1866 SCVAL(pdata,0,delete_pending);
1869 case SMB_FILE_POSITION_INFORMATION:
1871 SOFF_T(pdata,0,pos);
1874 case SMB_FILE_MODE_INFORMATION:
1875 SIVAL(pdata,0,mode);
1879 case SMB_FILE_ALIGNMENT_INFORMATION:
1880 SIVAL(pdata,0,0); /* No alignment needed. */
1885 /* Not yet finished... JRA */
1888 put_long_date(pdata,c_time);
1889 put_long_date(pdata+8,sbuf.st_atime);
1890 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1891 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1892 SIVAL(pdata,32,mode);
1893 SIVAL(pdata,36,0); /* ??? */
1894 SIVAL(pdata,40,0x20); /* ??? */
1895 SIVAL(pdata,44,0); /* ??? */
1896 SOFF_T(pdata,48,size);
1897 SIVAL(pdata,56,0x1); /* ??? */
1898 SIVAL(pdata,60,0); /* ??? */
1899 SIVAL(pdata,64,0); /* ??? */
1900 SIVAL(pdata,68,length); /* Following string length in bytes. */
1901 dos_PutUniCode(pdata+72,,False);
1906 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
1907 /* Last component of pathname. */
1909 size_t byte_len = dos_PutUniCode(pdata+4,fname,max_data_bytes,False);
1910 SIVAL(pdata,0,byte_len);
1911 data_size = 4 + byte_len;
1917 * NT4 server just returns "invalid query" to this - if we try to answer
1918 * it then NTws gets a BSOD! (tridge).
1919 * W2K seems to want this. JRA.
1921 case SMB_QUERY_FILE_STREAM_INFO:
1923 case SMB_FILE_STREAM_INFORMATION:
1927 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
1928 SIVAL(pdata,0,0); /* ??? */
1929 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
1930 SOFF_T(pdata,8,file_size);
1931 SIVAL(pdata,16,allocation_size);
1932 SIVAL(pdata,20,0); /* ??? */
1933 data_size = 24 + byte_len;
1937 case SMB_FILE_COMPRESSION_INFORMATION:
1938 SOFF_T(pdata,0,allocation_size);
1939 SIVAL(pdata,8,0); /* ??? */
1940 SIVAL(pdata,12,0); /* ??? */
1944 case SMB_FILE_NETWORK_OPEN_INFORMATION:
1945 put_long_date(pdata,c_time);
1946 put_long_date(pdata+8,sbuf.st_atime);
1947 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1948 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1949 SIVAL(pdata,32,allocation_size);
1950 SOFF_T(pdata,40,file_size);
1951 SIVAL(pdata,48,mode);
1952 SIVAL(pdata,52,0); /* ??? */
1956 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
1957 SIVAL(pdata,0,mode);
1963 * CIFS UNIX Extensions.
1966 case SMB_QUERY_FILE_UNIX_BASIC:
1968 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
1970 SOFF_T(pdata,0,sbuf.st_size); /* File size 64 Bit */
1973 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1974 SOFF_T(pdata,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */
1976 /* Can't get the value - fake it using size. */
1977 SOFF_T(pdata,0,sbuf.st_size); /* Number of bytes used on disk - 64 Bit */
1981 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
1982 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
1983 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1986 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
1990 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
1994 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
1997 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2001 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2005 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2008 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2012 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2015 data_size = PTR_DIFF(pdata,(*ppdata));
2019 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2021 for (i=0; i<100; i++)
2022 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2028 case SMB_QUERY_FILE_UNIX_LINK:
2033 if(!S_ISLNK(sbuf.st_mode))
2034 return(UNIXERROR(ERRSRV,ERRbadlink));
2036 return(UNIXERROR(ERRDOS,ERRbadlink));
2038 len = conn->vfs_ops.readlink(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2040 return(UNIXERROR(ERRDOS,ERRnoaccess));
2042 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2044 data_size = PTR_DIFF(pdata,(*ppdata));
2050 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2053 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size);
2058 /****************************************************************************
2059 Deal with the internal needs of setting the delete on close flag. Note that
2060 as the tdb locking is recursive, it is safe to call this from within
2061 open_file_shared. JRA.
2062 ****************************************************************************/
2064 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2067 * Only allow delete on close for writable shares.
2070 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2071 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2073 return NT_STATUS_ACCESS_DENIED;
2076 * Only allow delete on close for files/directories opened with delete intent.
2079 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2080 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2082 return NT_STATUS_ACCESS_DENIED;
2085 if(fsp->is_directory) {
2086 fsp->directory_delete_on_close = delete_on_close;
2087 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2088 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2091 files_struct *iterate_fsp;
2094 * Modify the share mode entry for all files open
2095 * on this device and inode to tell other smbds we have
2096 * changed the delete on close flag. This will be noticed
2097 * in the close code, the last closer will delete the file
2101 DEBUG(10,("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2102 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2104 if (lock_share_entry_fsp(fsp) == False)
2105 return NT_STATUS_ACCESS_DENIED;
2107 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2108 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2110 unlock_share_entry_fsp(fsp);
2111 return NT_STATUS_ACCESS_DENIED;
2118 unlock_share_entry_fsp(fsp);
2121 * Go through all files we have open on the same device and
2122 * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
2123 * Other smbd's that have this file open will look in the share_mode on close.
2124 * take care of this (rare) case in close_file(). See the comment there.
2125 * NB. JRA. We don't really need to do this anymore - all should be taken
2126 * care of in the share_mode changes in the tdb.
2129 for(iterate_fsp = file_find_di_first(fsp->dev, fsp->inode);
2130 iterate_fsp; iterate_fsp = file_find_di_next(iterate_fsp))
2131 fsp->delete_on_close = delete_on_close;
2134 * Set the delete on close flag in the fsp.
2136 fsp->delete_on_close = delete_on_close;
2138 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2139 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2143 return NT_STATUS_OK;
2146 /****************************************************************************
2147 Returns true if this pathname is within the share, and thus safe.
2148 ****************************************************************************/
2150 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2153 char resolved_name[PATH_MAX+1];
2155 pstring resolved_name;
2157 fstring last_component;
2161 BOOL bad_path = False;
2162 SMB_STRUCT_STAT sbuf;
2164 pstrcpy(link_dest, link_dest_in);
2165 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2167 /* Store the UNIX converted path. */
2168 pstrcpy(link_dest_out, link_dest);
2170 p = strrchr(link_dest, '/');
2172 fstrcpy(last_component, p+1);
2175 fstrcpy(last_component, link_dest);
2176 pstrcpy(link_dest, "./");
2179 if (conn->vfs_ops.realpath(conn,link_dest,resolved_name) == NULL)
2182 pstrcpy(link_dest, resolved_name);
2183 pstrcat(link_dest, "/");
2184 pstrcat(link_dest, last_component);
2186 if (*link_dest != '/') {
2187 /* Relative path. */
2188 pstrcpy(link_test, conn->connectpath);
2189 pstrcat(link_test, "/");
2190 pstrcat(link_test, link_dest);
2192 pstrcpy(link_test, link_dest);
2196 * Check if the link is within the share.
2199 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2206 /****************************************************************************
2207 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2208 ****************************************************************************/
2210 static int call_trans2setfilepathinfo(connection_struct *conn,
2211 char *inbuf, char *outbuf, int length, int bufsize,
2212 char **pparams, int total_params, char **ppdata, int total_data)
2214 char *params = *pparams;
2215 char *pdata = *ppdata;
2216 uint16 tran_call = SVAL(inbuf, smb_setup0);
2221 SMB_STRUCT_STAT sbuf;
2224 BOOL bad_path = False;
2225 files_struct *fsp = NULL;
2226 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2227 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2228 mode_t unixmode = 0;
2230 if (tran_call == TRANSACT2_SETFILEINFO) {
2231 fsp = file_fsp(params,0);
2232 info_level = SVAL(params,2);
2234 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2236 * This is actually a SETFILEINFO on a directory
2237 * handle (returned from an NT SMB). NT5.0 seems
2238 * to do this call. JRA.
2240 pstrcpy(fname, fsp->fsp_name);
2241 unix_convert(fname,conn,0,&bad_path,&sbuf);
2242 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2243 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2244 set_bad_path_error(errno, bad_path);
2245 return(UNIXERROR(ERRDOS,ERRbadpath));
2247 } else if (fsp && fsp->print_file) {
2249 * Doing a DELETE_ON_CLOSE should cancel a print job.
2251 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
2252 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2254 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
2257 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2260 return (UNIXERROR(ERRDOS,ERRbadpath));
2263 * Original code - this is an open file.
2265 CHECK_FSP(fsp,conn);
2267 pstrcpy(fname, fsp->fsp_name);
2270 if (vfs_fstat(fsp,fd,&sbuf) != 0) {
2271 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2272 return(UNIXERROR(ERRDOS,ERRbadfid));
2277 if (total_params < 6)
2278 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2280 info_level = SVAL(params,0);
2281 srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE);
2282 unix_convert(fname,conn,0,&bad_path,&sbuf);
2283 if(!check_name(fname, conn)) {
2284 set_bad_path_error(errno, bad_path);
2285 return(UNIXERROR(ERRDOS,ERRbadpath));
2289 * For CIFS UNIX extensions the target name may not exist.
2292 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2293 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
2294 set_bad_path_error(errno, bad_path);
2295 return(UNIXERROR(ERRDOS,ERRbadpath));
2299 if (!CAN_WRITE(conn))
2300 return ERROR_DOS(ERRSRV,ERRaccess);
2302 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2303 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2305 if (VALID_STAT(sbuf))
2306 unixmode = sbuf.st_mode;
2308 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
2309 tran_call,fname,info_level,total_data));
2311 /* Realloc the parameter and data sizes */
2312 params = Realloc(*pparams,2);
2314 return ERROR_DOS(ERRDOS,ERRnomem);
2320 /* the pending modtime overrides the current modtime */
2321 sbuf.st_mtime = fsp->pending_modtime;
2324 size = sbuf.st_size;
2325 tvs.modtime = sbuf.st_mtime;
2326 tvs.actime = sbuf.st_atime;
2327 dosmode = dos_mode(conn,fname,&sbuf);
2328 unixmode = sbuf.st_mode;
2330 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2331 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2333 switch (info_level) {
2334 case SMB_INFO_STANDARD:
2335 case SMB_INFO_QUERY_EA_SIZE:
2337 if (total_data < l1_cbFile+4)
2338 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2341 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2344 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2346 dosmode = SVAL(pdata,l1_attrFile);
2347 size = IVAL(pdata,l1_cbFile);
2352 /* XXXX um, i don't think this is right.
2353 it's also not in the cifs6.txt spec.
2355 case SMB_INFO_QUERY_EAS_FROM_LIST:
2356 if (total_data < 28)
2357 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2359 tvs.actime = make_unix_date2(pdata+8);
2360 tvs.modtime = make_unix_date2(pdata+12);
2361 size = IVAL(pdata,16);
2362 dosmode = IVAL(pdata,24);
2365 /* XXXX nor this. not in cifs6.txt, either. */
2366 case SMB_INFO_QUERY_ALL_EAS:
2367 if (total_data < 28)
2368 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2370 tvs.actime = make_unix_date2(pdata+8);
2371 tvs.modtime = make_unix_date2(pdata+12);
2372 size = IVAL(pdata,16);
2373 dosmode = IVAL(pdata,24);
2376 case SMB_SET_FILE_BASIC_INFO:
2377 case SMB_FILE_BASIC_INFORMATION:
2379 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2381 time_t changed_time;
2383 if (total_data < 36)
2384 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2386 /* Ignore create time at offset pdata. */
2389 tvs.actime = interpret_long_date(pdata+8);
2391 write_time = interpret_long_date(pdata+16);
2392 changed_time = interpret_long_date(pdata+24);
2394 tvs.modtime = MIN(write_time, changed_time);
2396 if (write_time > tvs.modtime && write_time != 0xffffffff) {
2397 tvs.modtime = write_time;
2399 /* Prefer a defined time to an undefined one. */
2400 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2401 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2402 ? changed_time : write_time);
2405 dosmode = IVAL(pdata,32);
2409 case SMB_FILE_ALLOCATION_INFORMATION:
2410 case SMB_SET_FILE_ALLOCATION_INFO:
2413 SMB_OFF_T allocation_size = IVAL(pdata,0);
2416 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2418 #ifdef LARGE_SMB_OFF_T
2419 allocation_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2420 #else /* LARGE_SMB_OFF_T */
2421 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2422 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2423 #endif /* LARGE_SMB_OFF_T */
2424 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2425 fname, (double)allocation_size ));
2427 if(allocation_size != sbuf.st_size) {
2428 SMB_STRUCT_STAT new_sbuf;
2430 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2431 fname, (double)allocation_size ));
2434 files_struct *new_fsp = NULL;
2435 int access_mode = 0;
2438 if(global_oplock_break) {
2439 /* Queue this file modify as we are the process of an oplock break. */
2441 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2442 DEBUGADD(2,( "in oplock break state.\n"));
2444 push_oplock_pending_smb_message(inbuf, length);
2448 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2449 SET_OPEN_MODE(DOS_OPEN_RDWR),
2450 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2451 0, 0, &access_mode, &action);
2453 if (new_fsp == NULL)
2454 return(UNIXERROR(ERRDOS,ERRbadpath));
2455 ret = vfs_allocate_file_space(new_fsp, allocation_size);
2456 if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2457 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2458 new_fsp->fnum, strerror(errno)));
2461 close_file(new_fsp,True);
2463 ret = vfs_allocate_file_space(fsp, allocation_size);
2464 if (vfs_fstat(fsp,fd,&new_sbuf) != 0) {
2465 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2466 fsp->fnum, strerror(errno)));
2471 return ERROR_NT(NT_STATUS_DISK_FULL);
2473 /* Allocate can truncate size... */
2474 size = new_sbuf.st_size;
2480 case SMB_FILE_END_OF_FILE_INFORMATION:
2481 case SMB_SET_FILE_END_OF_FILE_INFO:
2484 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2486 size = IVAL(pdata,0);
2487 #ifdef LARGE_SMB_OFF_T
2488 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2489 #else /* LARGE_SMB_OFF_T */
2490 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2491 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2492 #endif /* LARGE_SMB_OFF_T */
2493 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2497 case SMB_FILE_DISPOSITION_INFORMATION:
2498 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2500 BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
2504 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2506 if (tran_call != TRANSACT2_SETFILEINFO)
2507 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2510 return(UNIXERROR(ERRDOS,ERRbadfid));
2512 status = set_delete_on_close_internal(fsp, delete_on_close);
2514 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2515 return ERROR_NT(status);
2521 * CIFS UNIX extensions.
2524 case SMB_SET_FILE_UNIX_BASIC:
2526 uint32 raw_unixmode;
2528 if (total_data < 100)
2529 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2531 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
2532 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
2533 size=IVAL(pdata,0); /* first 8 Bytes are size */
2534 #ifdef LARGE_SMB_OFF_T
2535 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2536 #else /* LARGE_SMB_OFF_T */
2537 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2538 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2539 #endif /* LARGE_SMB_OFF_T */
2541 pdata+=24; /* ctime & st_blocks are not changed */
2542 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
2543 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
2545 set_owner = (uid_t)IVAL(pdata,0);
2547 set_grp = (gid_t)IVAL(pdata,0);
2549 raw_unixmode = IVAL(pdata,28);
2550 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2551 dosmode = 0; /* Ensure dos mode change doesn't override this. */
2553 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2554 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2555 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2557 if (!VALID_STAT(sbuf)) {
2560 * The only valid use of this is to create character and block
2561 * devices, and named pipes. This is deprecated (IMHO) and
2562 * a new info level should be used for mknod. JRA.
2565 #if !defined(HAVE_MAKEDEV_FN)
2566 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2567 #else /* HAVE_MAKEDEV_FN */
2568 uint32 file_type = IVAL(pdata,0);
2569 uint32 dev_major = IVAL(pdata,4);
2570 uint32 dev_minor = IVAL(pdata,12);
2572 uid_t myuid = geteuid();
2573 gid_t mygid = getegid();
2576 if (tran_call == TRANSACT2_SETFILEINFO)
2577 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2579 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2580 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2582 dev = makedev(dev_major, dev_minor);
2584 /* We can only create as the owner/group we are. */
2586 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2587 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2588 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2589 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2591 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2592 file_type != UNIX_TYPE_FIFO)
2593 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2595 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2596 0%o for file %s\n", (double)dev, unixmode, fname ));
2598 /* Ok - do the mknod. */
2599 if (conn->vfs_ops.mknod(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
2600 return(UNIXERROR(ERRDOS,ERRnoaccess));
2603 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2605 #endif /* HAVE_MAKEDEV_FN */
2610 * Deal with the UNIX specific mode set.
2613 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
2614 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2615 (unsigned int)unixmode, fname ));
2616 if (vfs_chmod(conn,fname,unixmode) != 0)
2617 return(UNIXERROR(ERRDOS,ERRnoaccess));
2621 * Deal with the UNIX specific uid set.
2624 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
2625 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2626 (unsigned int)set_owner, fname ));
2627 if (vfs_chown(conn,fname,set_owner, (gid_t)-1) != 0)
2628 return(UNIXERROR(ERRDOS,ERRnoaccess));
2632 * Deal with the UNIX specific gid set.
2635 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
2636 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2637 (unsigned int)set_owner, fname ));
2638 if (vfs_chown(conn,fname,(uid_t)-1, set_grp) != 0)
2639 return(UNIXERROR(ERRDOS,ERRnoaccess));
2644 case SMB_SET_FILE_UNIX_LINK:
2647 /* Set a symbolic link. */
2648 /* Don't allow this if follow links is false. */
2650 if (!lp_symlinks(SNUM(conn)))
2651 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2653 /* Disallow if already exists. */
2654 if (VALID_STAT(sbuf))
2655 return(ERROR_DOS(ERRDOS,ERRbadpath));
2657 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2659 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2660 return(UNIXERROR(ERRDOS,ERRnoaccess));
2662 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2663 fname, link_dest ));
2665 if (conn->vfs_ops.symlink(conn,link_dest,fname) != 0)
2666 return(UNIXERROR(ERRDOS,ERRnoaccess));
2668 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2672 case SMB_SET_FILE_UNIX_HLINK:
2676 /* Set a hard link. */
2678 /* Disallow if already exists. */
2679 if (VALID_STAT(sbuf))
2680 return(ERROR_DOS(ERRDOS,ERRbadpath));
2682 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2684 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2685 return(UNIXERROR(ERRDOS,ERRnoaccess));
2687 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2688 fname, link_dest ));
2690 if (conn->vfs_ops.link(conn,link_dest,fname) != 0)
2691 return(UNIXERROR(ERRDOS,ERRnoaccess));
2693 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2698 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2701 /* get some defaults (no modifications) if any info is zero or -1. */
2702 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2703 tvs.actime = sbuf.st_atime;
2705 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2706 tvs.modtime = sbuf.st_mtime;
2708 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2709 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2710 DEBUG(6,("size: %.0f ", (double)size));
2712 if (S_ISDIR(sbuf.st_mode))
2717 DEBUG(6,("dosmode: %x\n" , dosmode));
2719 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2720 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2721 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2722 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2725 * Only do this test if we are not explicitly
2726 * changing the size of a file.
2729 size = sbuf.st_size;
2733 * Try and set the times, size and mode of this file -
2734 * if they are different from the current values
2736 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2739 * This was a setfileinfo on an open file.
2740 * NT does this a lot. It's actually pointless
2741 * setting the time here, as it will be overwritten
2742 * on the next write, so we save the request
2743 * away and will set it on file close. JRA.
2746 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2747 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
2748 fsp->pending_modtime = tvs.modtime;
2753 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2755 if(file_utime(conn, fname, &tvs)!=0)
2756 return(UNIXERROR(ERRDOS,ERRnoaccess));
2760 /* check the mode isn't different, before changing it */
2761 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
2763 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
2765 if(file_chmod(conn, fname, dosmode, NULL)) {
2766 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2767 return(UNIXERROR(ERRDOS,ERRnoaccess));
2771 if(size != sbuf.st_size) {
2775 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2776 fname, (double)size ));
2779 files_struct *new_fsp = NULL;
2780 int access_mode = 0;
2783 if(global_oplock_break) {
2784 /* Queue this file modify as we are the process of an oplock break. */
2786 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2787 DEBUGADD(2,( "in oplock break state.\n"));
2789 push_oplock_pending_smb_message(inbuf, length);
2793 new_fsp = open_file_shared(conn, fname, &sbuf,
2794 SET_OPEN_MODE(DOS_OPEN_RDWR),
2795 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2796 0, 0, &access_mode, &action);
2798 if (new_fsp == NULL)
2799 return(UNIXERROR(ERRDOS,ERRbadpath));
2800 ret = vfs_set_filelen(new_fsp, size);
2801 close_file(new_fsp,True);
2803 ret = vfs_set_filelen(fsp, size);
2807 return (UNIXERROR(ERRHRD,ERRdiskfull));
2811 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2816 /****************************************************************************
2817 Reply to a TRANS2_MKDIR (make directory with extended attributes).
2818 ****************************************************************************/
2820 static int call_trans2mkdir(connection_struct *conn,
2821 char *inbuf, char *outbuf, int length, int bufsize,
2822 char **pparams, int total_params, char **ppdata, int total_data)
2824 char *params = *pparams;
2827 SMB_STRUCT_STAT sbuf;
2828 BOOL bad_path = False;
2830 if (!CAN_WRITE(conn))
2831 return ERROR_DOS(ERRSRV,ERRaccess);
2833 if (total_params < 4)
2834 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2836 srvstr_pull(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE);
2838 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
2840 unix_convert(directory,conn,0,&bad_path,&sbuf);
2841 if (check_name(directory,conn))
2842 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2845 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
2846 set_bad_path_error(errno, bad_path);
2847 return(UNIXERROR(ERRDOS,ERRnoaccess));
2850 /* Realloc the parameter and data sizes */
2851 params = Realloc(*pparams,2);
2853 return ERROR_DOS(ERRDOS,ERRnomem);
2858 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2863 /****************************************************************************
2864 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
2865 We don't actually do this - we just send a null response.
2866 ****************************************************************************/
2868 static int call_trans2findnotifyfirst(connection_struct *conn,
2869 char *inbuf, char *outbuf, int length, int bufsize,
2870 char **pparams, int total_params, char **ppdata, int total_data)
2872 static uint16 fnf_handle = 257;
2873 char *params = *pparams;
2876 if (total_params < 6)
2877 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2879 info_level = SVAL(params,4);
2880 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
2882 switch (info_level) {
2887 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2890 /* Realloc the parameter and data sizes */
2891 params = Realloc(*pparams,6);
2893 return ERROR_DOS(ERRDOS,ERRnomem);
2896 SSVAL(params,0,fnf_handle);
2897 SSVAL(params,2,0); /* No changes */
2898 SSVAL(params,4,0); /* No EA errors */
2905 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
2910 /****************************************************************************
2911 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
2912 changes). Currently this does nothing.
2913 ****************************************************************************/
2915 static int call_trans2findnotifynext(connection_struct *conn,
2916 char *inbuf, char *outbuf, int length, int bufsize,
2917 char **pparams, int total_params, char **ppdata, int total_data)
2919 char *params = *pparams;
2921 DEBUG(3,("call_trans2findnotifynext\n"));
2923 /* Realloc the parameter and data sizes */
2924 params = Realloc(*pparams,4);
2926 return ERROR_DOS(ERRDOS,ERRnomem);
2929 SSVAL(params,0,0); /* No changes */
2930 SSVAL(params,2,0); /* No EA errors */
2932 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2937 /****************************************************************************
2938 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
2939 ****************************************************************************/
2941 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
2942 char* outbuf, int length, int bufsize,
2943 char **pparams, int total_params, char **ppdata, int total_data)
2945 char *params = *pparams;
2948 int max_referral_level;
2950 DEBUG(10,("call_trans2getdfsreferral\n"));
2952 if (total_params < 2)
2953 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2955 max_referral_level = SVAL(params,0);
2957 if(!lp_host_msdfs())
2958 return ERROR_DOS(ERRDOS,ERRbadfunc);
2960 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
2962 if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
2963 return ERROR_DOS(ERRDOS,ERRbadfile);
2965 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
2966 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
2971 #define LMCAT_SPL 0x53
2972 #define LMFUNC_GETJOBID 0x60
2974 /****************************************************************************
2975 Reply to a TRANS2_IOCTL - used for OS/2 printing.
2976 ****************************************************************************/
2978 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
2979 char* outbuf, int length, int bufsize,
2980 char **pparams, int total_params, char **ppdata, int total_data)
2982 char *pdata = *ppdata;
2983 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
2985 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
2986 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
2989 pdata = Realloc(*ppdata, 32);
2991 return ERROR_DOS(ERRDOS,ERRnomem);
2994 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
2995 CAN ACCEPT THIS IN UNICODE. JRA. */
2997 rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid); /* Job number */
2998 SSVAL(pdata,0,rap_jobid); /* Job number */
2999 srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3000 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3001 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3004 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3005 return ERROR_DOS(ERRSRV,ERRerror);
3009 /****************************************************************************
3010 Reply to a SMBfindclose (stop trans2 directory search).
3011 ****************************************************************************/
3013 int reply_findclose(connection_struct *conn,
3014 char *inbuf,char *outbuf,int length,int bufsize)
3017 int dptr_num=SVALS(inbuf,smb_vwv0);
3018 START_PROFILE(SMBfindclose);
3020 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3022 dptr_close(&dptr_num);
3024 outsize = set_message(outbuf,0,0,True);
3026 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3028 END_PROFILE(SMBfindclose);
3032 /****************************************************************************
3033 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3034 ****************************************************************************/
3036 int reply_findnclose(connection_struct *conn,
3037 char *inbuf,char *outbuf,int length,int bufsize)
3041 START_PROFILE(SMBfindnclose);
3043 dptr_num = SVAL(inbuf,smb_vwv0);
3045 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3047 /* We never give out valid handles for a
3048 findnotifyfirst - so any dptr_num is ok here.
3051 outsize = set_message(outbuf,0,0,True);
3053 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3055 END_PROFILE(SMBfindnclose);
3059 /****************************************************************************
3060 Reply to a SMBtranss2 - just ignore it!
3061 ****************************************************************************/
3063 int reply_transs2(connection_struct *conn,
3064 char *inbuf,char *outbuf,int length,int bufsize)
3066 START_PROFILE(SMBtranss2);
3067 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3068 END_PROFILE(SMBtranss2);
3072 /****************************************************************************
3073 Reply to a SMBtrans2.
3074 ****************************************************************************/
3076 int reply_trans2(connection_struct *conn,
3077 char *inbuf,char *outbuf,int length,int bufsize)
3080 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3081 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3083 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3084 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3085 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3086 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3087 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3088 int32 timeout = IVALS(inbuf,smb_timeout);
3090 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3091 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3092 char *params = NULL, *data = NULL;
3093 int num_params, num_params_sofar, num_data, num_data_sofar;
3094 START_PROFILE(SMBtrans2);
3096 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3097 /* Queue this open message as we are the process of an
3100 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3101 DEBUGADD(2,( "in oplock break state.\n"));
3103 push_oplock_pending_smb_message(inbuf, length);
3104 END_PROFILE(SMBtrans2);
3108 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3109 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3110 END_PROFILE(SMBtrans2);
3111 return ERROR_DOS(ERRSRV,ERRaccess);
3114 outsize = set_message(outbuf,0,0,True);
3116 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3117 is so as a sanity check */
3120 * Need to have rc=0 for ioctl to get job id for OS/2.
3121 * Network printing will fail if function is not successful.
3122 * Similar function in reply.c will be used if protocol
3123 * is LANMAN1.0 instead of LM1.2X002.
3124 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3125 * outbuf doesn't have to be set(only job id is used).
3127 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3128 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3129 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3130 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3132 DEBUG(2,("Invalid smb_sucnt in trans2 call(%d)\n",suwcnt));
3133 DEBUG(2,("Transaction is %d\n",tran_call));
3134 END_PROFILE(SMBtrans2);
3135 return ERROR_DOS(ERRSRV,ERRerror);
3139 /* Allocate the space for the maximum needed parameters and data */
3140 if (total_params > 0)
3141 params = (char *)malloc(total_params);
3143 data = (char *)malloc(total_data);
3145 if ((total_params && !params) || (total_data && !data)) {
3146 DEBUG(2,("Out of memory in reply_trans2\n"));
3149 END_PROFILE(SMBtrans2);
3150 return ERROR_DOS(ERRDOS,ERRnomem);
3153 /* Copy the param and data bytes sent with this request into
3154 the params buffer */
3155 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3156 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3158 if (num_params > total_params || num_data > total_data)
3159 exit_server("invalid params in reply_trans2");
3162 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
3164 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
3166 if(num_data_sofar < total_data || num_params_sofar < total_params) {
3167 /* We need to send an interim response then receive the rest
3168 of the parameter/data bytes */
3169 outsize = set_message(outbuf,0,0,True);
3170 if (!send_smb(smbd_server_fd(),outbuf))
3171 exit_server("reply_trans2: send_smb failed.");
3173 while (num_data_sofar < total_data ||
3174 num_params_sofar < total_params) {
3177 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3180 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3181 outsize = set_message(outbuf,0,0,True);
3183 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3185 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3186 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3189 END_PROFILE(SMBtrans2);
3190 return ERROR_DOS(ERRSRV,ERRerror);
3193 /* Revise total_params and total_data in case
3194 they have changed downwards */
3195 total_params = SVAL(inbuf, smb_tpscnt);
3196 total_data = SVAL(inbuf, smb_tdscnt);
3197 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
3198 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
3199 if (num_params_sofar > total_params || num_data_sofar > total_data)
3200 exit_server("data overflow in trans2");
3202 memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)],
3203 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
3204 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
3205 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
3209 if (Protocol >= PROTOCOL_NT1) {
3210 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
3213 /* Now we must call the relevant TRANS2 function */
3215 case TRANSACT2_OPEN:
3216 START_PROFILE_NESTED(Trans2_open);
3217 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
3218 ¶ms, total_params, &data, total_data);
3219 END_PROFILE_NESTED(Trans2_open);
3222 case TRANSACT2_FINDFIRST:
3223 START_PROFILE_NESTED(Trans2_findfirst);
3224 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3225 ¶ms, total_params, &data, total_data);
3226 END_PROFILE_NESTED(Trans2_findfirst);
3229 case TRANSACT2_FINDNEXT:
3230 START_PROFILE_NESTED(Trans2_findnext);
3231 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
3232 ¶ms, total_params, &data, total_data);
3233 END_PROFILE_NESTED(Trans2_findnext);
3236 case TRANSACT2_QFSINFO:
3237 START_PROFILE_NESTED(Trans2_qfsinfo);
3238 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3239 ¶ms, total_params, &data, total_data);
3240 END_PROFILE_NESTED(Trans2_qfsinfo);
3243 case TRANSACT2_SETFSINFO:
3244 START_PROFILE_NESTED(Trans2_setfsinfo);
3245 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
3246 ¶ms, total_params, &data, total_data);
3247 END_PROFILE_NESTED(Trans2_setfsinfo);
3250 case TRANSACT2_QPATHINFO:
3251 case TRANSACT2_QFILEINFO:
3252 START_PROFILE_NESTED(Trans2_qpathinfo);
3253 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3254 ¶ms, total_params, &data, total_data);
3255 END_PROFILE_NESTED(Trans2_qpathinfo);
3257 case TRANSACT2_SETPATHINFO:
3258 case TRANSACT2_SETFILEINFO:
3259 START_PROFILE_NESTED(Trans2_setpathinfo);
3260 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3261 ¶ms, total_params, &data, total_data);
3262 END_PROFILE_NESTED(Trans2_setpathinfo);
3265 case TRANSACT2_FINDNOTIFYFIRST:
3266 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3267 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
3268 ¶ms, total_params, &data, total_data);
3269 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3272 case TRANSACT2_FINDNOTIFYNEXT:
3273 START_PROFILE_NESTED(Trans2_findnotifynext);
3274 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
3275 ¶ms, total_params, &data, total_data);
3276 END_PROFILE_NESTED(Trans2_findnotifynext);
3278 case TRANSACT2_MKDIR:
3279 START_PROFILE_NESTED(Trans2_mkdir);
3280 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3281 ¶ms, total_params, &data, total_data);
3282 END_PROFILE_NESTED(Trans2_mkdir);
3285 case TRANSACT2_GET_DFS_REFERRAL:
3286 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3287 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3288 ¶ms, total_params, &data, total_data);
3289 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3291 case TRANSACT2_IOCTL:
3292 START_PROFILE_NESTED(Trans2_ioctl);
3293 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3294 ¶ms, total_params, &data, total_data);
3295 END_PROFILE_NESTED(Trans2_ioctl);
3298 /* Error in request */
3299 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3302 END_PROFILE(SMBtrans2);
3303 return ERROR_DOS(ERRSRV,ERRerror);
3306 /* As we do not know how many data packets will need to be
3307 returned here the various call_trans2xxxx calls
3308 must send their own. Thus a call_trans2xxx routine only
3309 returns a value other than -1 when it wants to send
3315 END_PROFILE(SMBtrans2);
3316 return outsize; /* If a correct response was needed the
3317 call_trans2xxx calls have already sent
3318 it. If outsize != -1 then it is returning */