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;
32 #define get_file_size(sbuf) (sbuf.st_size)
34 /* given a stat buffer return the allocated size on disk, taking into
35 account sparse files */
36 SMB_OFF_T get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
39 #if defined(HAVE_STAT_ST_BLKSIZE) && defined(HAVE_STAT_ST_BLOCKS)
40 ret = sbuf->st_blksize * (SMB_OFF_T)sbuf->st_blocks;
41 #elif defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
42 ret = (SMB_OFF_T)STAT_ST_BLOCKSIZE * (SMB_OFF_T)sbuf->st_blocks;
44 ret = get_file_size(*sbuf);
46 if (!ret && fsp && fsp->initial_allocation_size)
47 ret = fsp->initial_allocation_size;
48 ret = SMB_ROUNDUP(ret,SMB_ROUNDUP_ALLOCATION_SIZE);
52 /****************************************************************************
53 Send the required number of replies back.
54 We assume all fields other than the data fields are
55 set correctly for the type of call.
56 HACK ! Always assumes smb_setup field is zero.
57 ****************************************************************************/
59 static int send_trans2_replies(char *outbuf,
66 /* As we are using a protocol > LANMAN1 then the max_send
67 variable must have been set in the sessetupX call.
68 This takes precedence over the max_xmit field in the
69 global struct. These different max_xmit variables should
70 be merged as this is now too confusing */
73 int data_to_send = datasize;
74 int params_to_send = paramsize;
78 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
79 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
80 int data_alignment_offset = 0;
82 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
84 set_message(outbuf,10,0,True);
86 /* If there genuinely are no parameters or data to send just send the empty packet */
88 if(params_to_send == 0 && data_to_send == 0) {
89 if (!send_smb(smbd_server_fd(),outbuf))
90 exit_server("send_trans2_replies: send_smb failed.");
94 /* When sending params and data ensure that both are nicely aligned */
95 /* Only do this alignment when there is also data to send - else
96 can cause NT redirector problems. */
98 if (((params_to_send % 4) != 0) && (data_to_send != 0))
99 data_alignment_offset = 4 - (params_to_send % 4);
101 /* Space is bufsize minus Netbios over TCP header minus SMB header */
102 /* The alignment_offset is to align the param bytes on an even byte
103 boundary. NT 4.0 Beta needs this to work correctly. */
105 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
107 /* useable_space can never be more than max_send minus the alignment offset. */
109 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
111 while (params_to_send || data_to_send) {
112 /* Calculate whether we will totally or partially fill this packet */
114 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
116 /* We can never send more than useable_space */
118 * Note that 'useable_space' does not include the alignment offsets,
119 * but we must include the alignment offsets in the calculation of
120 * the length of the data we send over the wire, as the alignment offsets
121 * are sent here. Fix from Marc_Jacobsen@hp.com.
124 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
126 set_message(outbuf, 10, total_sent_thistime, True);
128 /* Set total params and data to be sent */
129 SSVAL(outbuf,smb_tprcnt,paramsize);
130 SSVAL(outbuf,smb_tdrcnt,datasize);
132 /* Calculate how many parameters and data we can fit into
133 * this packet. Parameters get precedence
136 params_sent_thistime = MIN(params_to_send,useable_space);
137 data_sent_thistime = useable_space - params_sent_thistime;
138 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
140 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
142 /* smb_proff is the offset from the start of the SMB header to the
143 parameter bytes, however the first 4 bytes of outbuf are
144 the Netbios over TCP header. Thus use smb_base() to subtract
145 them from the calculation */
147 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
149 if(params_sent_thistime == 0)
150 SSVAL(outbuf,smb_prdisp,0);
152 /* Absolute displacement of param bytes sent in this packet */
153 SSVAL(outbuf,smb_prdisp,pp - params);
155 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
156 if(data_sent_thistime == 0) {
157 SSVAL(outbuf,smb_droff,0);
158 SSVAL(outbuf,smb_drdisp, 0);
160 /* The offset of the data bytes is the offset of the
161 parameter bytes plus the number of parameters being sent this time */
162 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
163 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
164 SSVAL(outbuf,smb_drdisp, pd - pdata);
167 /* Copy the param bytes into the packet */
169 if(params_sent_thistime)
170 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
172 /* Copy in the data bytes */
173 if(data_sent_thistime)
174 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
175 data_alignment_offset,pd,data_sent_thistime);
177 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
178 params_sent_thistime, data_sent_thistime, useable_space));
179 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
180 params_to_send, data_to_send, paramsize, datasize));
182 /* Send the packet */
183 if (!send_smb(smbd_server_fd(),outbuf))
184 exit_server("send_trans2_replies: send_smb failed.");
186 pp += params_sent_thistime;
187 pd += data_sent_thistime;
189 params_to_send -= params_sent_thistime;
190 data_to_send -= data_sent_thistime;
193 if(params_to_send < 0 || data_to_send < 0) {
194 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
195 params_to_send, data_to_send));
203 /****************************************************************************
204 Reply to a TRANSACT2_OPEN.
205 ****************************************************************************/
207 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
208 char **pparams, int total_params, char **ppdata, int total_data)
210 char *params = *pparams;
215 BOOL return_additional_info;
225 int fmode=0,mtime=0,rmode;
227 SMB_STRUCT_STAT sbuf;
229 BOOL bad_path = False;
233 * Ensure we have enough parameters to perform the operation.
236 if (total_params < 29)
237 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
239 open_mode = SVAL(params, 2);
240 open_attr = SVAL(params,6);
241 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
243 return_additional_info = BITSETW(params,0);
244 open_sattr = SVAL(params, 4);
245 open_time = make_unix_date3(params+8);
247 open_ofun = SVAL(params,12);
248 open_size = IVAL(params,14);
251 srvstr_pull(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE);
253 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
254 fname,open_mode, open_attr, open_ofun, open_size));
257 return(ERROR_DOS(ERRSRV,ERRaccess));
259 /* XXXX we need to handle passed times, sattr and flags */
261 unix_convert(fname,conn,0,&bad_path,&sbuf);
263 if (!check_name(fname,conn)) {
264 set_bad_path_error(errno, bad_path);
265 return(UNIXERROR(ERRDOS,ERRnoaccess));
268 unixmode = unix_mode(conn,open_attr | aARCH, fname);
270 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode,
271 oplock_request, &rmode,&smb_action);
274 set_bad_path_error(errno, bad_path);
275 return(UNIXERROR(ERRDOS,ERRnoaccess));
278 size = get_file_size(sbuf);
279 fmode = dos_mode(conn,fname,&sbuf);
280 mtime = sbuf.st_mtime;
283 close_file(fsp,False);
284 return(ERROR_DOS(ERRDOS,ERRnoaccess));
287 /* Realloc the size of parameters and data we will return */
288 params = Realloc(*pparams, 28);
290 return(ERROR_DOS(ERRDOS,ERRnomem));
293 memset((char *)params,'\0',28);
294 SSVAL(params,0,fsp->fnum);
295 SSVAL(params,2,fmode);
296 put_dos_date2(params,4, mtime);
297 SIVAL(params,8, (uint32)size);
298 SSVAL(params,12,rmode);
300 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
301 smb_action |= EXTENDED_OPLOCK_GRANTED;
303 SSVAL(params,18,smb_action);
306 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
308 SIVAL(params,20,inode);
310 /* Send the required number of replies */
311 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
316 /*********************************************************
317 Routine to check if a given string matches exactly.
318 as a special case a mask of "." does NOT match. That
319 is required for correct wildcard semantics
320 Case can be significant or not.
321 **********************************************************/
323 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
325 if (mask[0] == '.' && mask[1] == 0)
328 return strcmp(str,mask)==0;
329 return strcasecmp(str,mask) == 0;
332 /****************************************************************************
333 Return the filetype for UNIX extensions.
334 ****************************************************************************/
336 static uint32 unix_filetype(mode_t mode)
339 return UNIX_TYPE_FILE;
340 else if(S_ISDIR(mode))
341 return UNIX_TYPE_DIR;
343 else if(S_ISLNK(mode))
344 return UNIX_TYPE_SYMLINK;
347 else if(S_ISCHR(mode))
348 return UNIX_TYPE_CHARDEV;
351 else if(S_ISBLK(mode))
352 return UNIX_TYPE_BLKDEV;
355 else if(S_ISFIFO(mode))
356 return UNIX_TYPE_FIFO;
359 else if(S_ISSOCK(mode))
360 return UNIX_TYPE_SOCKET;
363 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
364 return UNIX_TYPE_UNKNOWN;
367 /****************************************************************************
368 Return the major devicenumber for UNIX extensions.
369 ****************************************************************************/
371 static uint32 unix_dev_major(SMB_DEV_T dev)
373 #if defined(HAVE_DEVICE_MAJOR_FN)
374 return (uint32)major(dev);
376 return (uint32)(dev >> 8);
380 /****************************************************************************
381 Return the minor devicenumber for UNIX extensions.
382 ****************************************************************************/
384 static uint32 unix_dev_minor(SMB_DEV_T dev)
386 #if defined(HAVE_DEVICE_MINOR_FN)
387 return (uint32)minor(dev);
389 return (uint32)(dev & 0xff);
393 /****************************************************************************
394 Map wire perms onto standard UNIX permissions. Obey share restrictions.
395 ****************************************************************************/
397 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
401 if (perms == SMB_MODE_NO_CHANGE)
404 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
405 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
406 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
407 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
408 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
409 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
410 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
411 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
412 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
414 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
417 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
420 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
423 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
424 ret &= lp_dir_mask(SNUM(conn));
425 /* Add in force bits */
426 ret |= lp_force_dir_mode(SNUM(conn));
428 /* Apply mode mask */
429 ret &= lp_create_mask(SNUM(conn));
430 /* Add in force bits */
431 ret |= lp_force_create_mode(SNUM(conn));
437 /****************************************************************************
438 checks for SMB_TIME_NO_CHANGE and if not found
439 calls interpret_long_date
440 ****************************************************************************/
441 time_t interpret_long_unix_date(char *p)
443 DEBUG(1,("interpret_long_unix_date\n"));
444 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
445 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
448 return interpret_long_date(p);
452 /****************************************************************************
453 Get a level dependent lanman2 dir entry.
454 ****************************************************************************/
456 static BOOL get_lanman2_dir_entry(connection_struct *conn,
457 void *inbuf, void *outbuf,
458 char *path_mask,int dirtype,int info_level,
459 int requires_resume_key,
460 BOOL dont_descend,char **ppdata,
461 char *base_data, int space_remaining,
462 BOOL *out_of_space, BOOL *got_exact_match,
467 SMB_STRUCT_STAT sbuf;
471 char *p, *q, *pdata = *ppdata;
475 SMB_OFF_T file_size = 0;
476 SMB_OFF_T allocation_size = 0;
478 time_t mdate=0, adate=0, cdate=0;
481 int nt_extmode; /* Used for NT connections instead of mode */
482 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
485 *out_of_space = False;
486 *got_exact_match = False;
491 p = strrchr_m(path_mask,'/');
498 pstrcpy(mask, path_mask);
503 /* Needed if we run out of space */
504 prev_dirpos = TellDir(conn->dirptr);
505 dname = ReadDirName(conn->dirptr);
508 * Due to bugs in NT client redirectors we are not using
509 * resume keys any more - set them to zero.
510 * Check out the related comments in findfirst/findnext.
516 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
517 (long)conn->dirptr,TellDir(conn->dirptr)));
522 pstrcpy(fname,dname);
524 if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
525 got_match = mask_match(fname, mask, case_sensitive);
527 if(!got_match && !mangle_is_8_3(fname, False)) {
530 * It turns out that NT matches wildcards against
531 * both long *and* short names. This may explain some
532 * of the wildcard wierdness from old DOS clients
533 * that some people have been seeing.... JRA.
537 pstrcpy( newname, fname);
538 mangle_map( newname, True, False, SNUM(conn));
539 if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
540 got_match = mask_match(newname, mask, case_sensitive);
544 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
545 if (dont_descend && !isdots)
548 pstrcpy(pathreal,conn->dirpath);
550 pstrcat(pathreal,"/");
551 pstrcat(pathreal,dname);
553 if (INFO_LEVEL_IS_UNIX(info_level)) {
554 if (vfs_lstat(conn,pathreal,&sbuf) != 0) {
555 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
556 pathreal,strerror(errno)));
559 } else if (vfs_stat(conn,pathreal,&sbuf) != 0) {
561 /* Needed to show the msdfs symlinks as
564 if(lp_host_msdfs() &&
565 lp_msdfs_root(SNUM(conn)) &&
566 is_msdfs_link(conn, pathreal, NULL, NULL,
569 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
570 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
574 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
575 pathreal,strerror(errno)));
580 mode = dos_mode(conn,pathreal,&sbuf);
582 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
583 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
587 file_size = get_file_size(sbuf);
588 allocation_size = get_allocation_size(NULL,&sbuf);
589 mdate = sbuf.st_mtime;
590 adate = sbuf.st_atime;
591 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
593 if (lp_dos_filetime_resolution(SNUM(conn))) {
602 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
608 mangle_map(fname,False,True,SNUM(conn));
613 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
615 switch (info_level) {
616 case SMB_INFO_STANDARD:
617 if(requires_resume_key) {
621 put_dos_date2(p,l1_fdateCreation,cdate);
622 put_dos_date2(p,l1_fdateLastAccess,adate);
623 put_dos_date2(p,l1_fdateLastWrite,mdate);
624 SIVAL(p,l1_cbFile,(uint32)file_size);
625 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
626 SSVAL(p,l1_attrFile,mode);
629 p += align_string(outbuf, p, 0);
630 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
631 SCVAL(nameptr, -1, len);
635 case SMB_INFO_QUERY_EA_SIZE:
636 if(requires_resume_key) {
640 put_dos_date2(p,l2_fdateCreation,cdate);
641 put_dos_date2(p,l2_fdateLastAccess,adate);
642 put_dos_date2(p,l2_fdateLastWrite,mdate);
643 SIVAL(p,l2_cbFile,(uint32)file_size);
644 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
645 SSVAL(p,l2_attrFile,mode);
646 SIVAL(p,l2_cbList,0); /* No extended attributes */
649 len = srvstr_push(outbuf, p, fname, -1, STR_NOALIGN);
652 *p++ = 0; /* craig from unisys pointed out we need this */
655 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
656 was_8_3 = mangle_is_8_3(fname, True);
658 SIVAL(p,0,reskey); p += 4;
659 put_long_date(p,cdate); p += 8;
660 put_long_date(p,adate); p += 8;
661 put_long_date(p,mdate); p += 8;
662 put_long_date(p,mdate); p += 8;
663 SOFF_T(p,0,file_size);
664 SOFF_T(p,8,allocation_size);
666 SIVAL(p,0,nt_extmode); p += 4;
668 SIVAL(p,0,0); p += 4;
669 /* Clear the short name buffer. This is
670 * IMPORTANT as not doing so will trigger
671 * a Win2k client bug. JRA.
675 pstring mangled_name;
676 pstrcpy(mangled_name, fname);
677 mangle_map(mangled_name,True,True,SNUM(conn));
678 mangled_name[12] = 0;
679 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER);
686 len = srvstr_push(outbuf, p, fname, -1, 0);
689 len = PTR_DIFF(p, pdata);
690 len = (len + 3) & ~3;
695 case SMB_FIND_FILE_DIRECTORY_INFO:
697 SIVAL(p,0,reskey); p += 4;
698 put_long_date(p,cdate); p += 8;
699 put_long_date(p,adate); p += 8;
700 put_long_date(p,mdate); p += 8;
701 put_long_date(p,mdate); p += 8;
702 SOFF_T(p,0,file_size);
703 SOFF_T(p,8,allocation_size);
705 SIVAL(p,0,nt_extmode); p += 4;
707 len = srvstr_push(outbuf, p, fname, -1, 0);
710 len = PTR_DIFF(p, pdata);
711 len = (len + 3) & ~3;
716 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
718 SIVAL(p,0,reskey); p += 4;
719 put_long_date(p,cdate); p += 8;
720 put_long_date(p,adate); p += 8;
721 put_long_date(p,mdate); p += 8;
722 put_long_date(p,mdate); p += 8;
723 SOFF_T(p,0,file_size);
724 SOFF_T(p,8,allocation_size);
726 SIVAL(p,0,nt_extmode); p += 4;
728 SIVAL(p,0,0); p += 4;
730 len = srvstr_push(outbuf, p, fname, -1, 0);
734 len = PTR_DIFF(p, pdata);
735 len = (len + 3) & ~3;
740 case SMB_FIND_FILE_NAMES_INFO:
742 SIVAL(p,0,reskey); p += 4;
744 /* this must *not* be null terminated or w2k gets in a loop trying to set an
745 acl on a dir (tridge) */
746 len = srvstr_push(outbuf, p, fname, -1, 0);
749 len = PTR_DIFF(p, pdata);
750 len = (len + 3) & ~3;
755 /* CIFS UNIX Extension. */
757 case SMB_FIND_FILE_UNIX:
759 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
761 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
762 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
765 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
768 put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */
769 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
770 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
773 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
777 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
781 SIVAL(p,0,unix_filetype(sbuf.st_mode));
784 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
788 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
792 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
795 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
799 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
803 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
806 len = PTR_DIFF(p, pdata);
807 len = (len + 3) & ~3;
808 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
810 /* End of SMB_QUERY_FILE_UNIX_BASIC */
819 if (PTR_DIFF(p,pdata) > space_remaining) {
820 /* Move the dirptr back to prev_dirpos */
821 SeekDir(conn->dirptr, prev_dirpos);
822 *out_of_space = True;
823 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
824 return False; /* Not finished - just out of space */
827 /* Setup the last_filename pointer, as an offset from base_data */
828 *last_name_off = PTR_DIFF(nameptr,base_data);
829 /* Advance the data pointer to the next slot */
835 /****************************************************************************
836 Reply to a TRANS2_FINDFIRST.
837 ****************************************************************************/
839 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
840 char **pparams, int total_params, char **ppdata, int total_data)
842 /* We must be careful here that we don't return more than the
843 allowed number of data bytes. If this means returning fewer than
844 maxentries then so be it. We assume that the redirector has
845 enough room for the fixed number of parameter bytes it has
847 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
848 char *params = *pparams;
849 char *pdata = *ppdata;
850 int dirtype = SVAL(params,0);
851 int maxentries = SVAL(params,2);
852 BOOL close_after_first = BITSETW(params+4,0);
853 BOOL close_if_end = BITSETW(params+4,1);
854 BOOL requires_resume_key = BITSETW(params+4,2);
855 int info_level = SVAL(params,6);
863 BOOL finished = False;
864 BOOL dont_descend = False;
865 BOOL out_of_space = False;
867 BOOL bad_path = False;
868 SMB_STRUCT_STAT sbuf;
870 if (total_params < 12)
871 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
873 *directory = *mask = 0;
875 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
876 close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
877 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
878 info_level, max_data_bytes));
880 switch (info_level) {
881 case SMB_INFO_STANDARD:
882 case SMB_INFO_QUERY_EA_SIZE:
883 case SMB_FIND_FILE_DIRECTORY_INFO:
884 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
885 case SMB_FIND_FILE_NAMES_INFO:
886 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
888 case SMB_FIND_FILE_UNIX:
889 if (!lp_unix_extensions())
890 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
893 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
896 srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE);
898 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
900 unix_convert(directory,conn,0,&bad_path,&sbuf);
901 if(!check_name(directory,conn)) {
902 set_bad_path_error(errno, bad_path);
903 return(UNIXERROR(ERRDOS,ERRbadpath));
906 p = strrchr_m(directory,'/');
908 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
909 if((directory[0] == '.') && (directory[1] == '\0'))
912 pstrcpy(mask,directory);
913 pstrcpy(directory,"./");
919 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
921 pdata = Realloc(*ppdata, max_data_bytes + 1024);
923 return(ERROR_DOS(ERRDOS,ERRnomem));
926 memset((char *)pdata,'\0',max_data_bytes + 1024);
928 /* Realloc the params space */
929 params = Realloc(*pparams, 10);
931 return ERROR_DOS(ERRDOS,ERRnomem);
934 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
936 return(UNIXERROR(ERRDOS,ERRbadfile));
938 /* Save the wildcard match and attribs we are using on this directory -
939 needed as lanman2 assumes these are being saved between calls */
941 if(!(wcard = strdup(mask))) {
942 dptr_close(&dptr_num);
943 return ERROR_DOS(ERRDOS,ERRnomem);
946 dptr_set_wcard(dptr_num, wcard);
947 dptr_set_attr(dptr_num, dirtype);
949 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
951 /* We don't need to check for VOL here as this is returned by
952 a different TRANS2 call. */
954 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
955 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
959 space_remaining = max_data_bytes;
960 out_of_space = False;
962 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
963 BOOL got_exact_match = False;
965 /* this is a heuristic to avoid seeking the dirptr except when
966 absolutely necessary. It allows for a filename of about 40 chars */
967 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
971 finished = !get_lanman2_dir_entry(conn,
973 mask,dirtype,info_level,
974 requires_resume_key,dont_descend,
975 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
979 if (finished && out_of_space)
982 if (!finished && !out_of_space)
986 * As an optimisation if we know we aren't looking
987 * for a wildcard name (ie. the name matches the wildcard exactly)
988 * then we can finish on any (first) match.
989 * This speeds up large directory searches. JRA.
995 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
998 /* Check if we can close the dirptr */
999 if(close_after_first || (finished && close_if_end)) {
1000 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1001 dptr_close(&dptr_num);
1005 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1006 * from observation of NT.
1009 if(numentries == 0) {
1010 dptr_close(&dptr_num);
1011 return ERROR_DOS(ERRDOS,ERRbadfile);
1014 /* At this point pdata points to numentries directory entries. */
1016 /* Set up the return parameter block */
1017 SSVAL(params,0,dptr_num);
1018 SSVAL(params,2,numentries);
1019 SSVAL(params,4,finished);
1020 SSVAL(params,6,0); /* Never an EA error */
1021 SSVAL(params,8,last_name_off);
1023 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1025 if ((! *directory) && dptr_path(dptr_num))
1026 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1028 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1029 smb_fn_name(CVAL(inbuf,smb_com)),
1030 mask, directory, dirtype, numentries ) );
1033 * Force a name mangle here to ensure that the
1034 * mask as an 8.3 name is top of the mangled cache.
1035 * The reasons for this are subtle. Don't remove
1036 * this code unless you know what you are doing
1037 * (see PR#13758). JRA.
1040 if(!mangle_is_8_3_wildcards( mask, False))
1041 mangle_map(mask, True, True, SNUM(conn));
1046 /****************************************************************************
1047 Reply to a TRANS2_FINDNEXT.
1048 ****************************************************************************/
1050 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1051 char **pparams, int total_params, char **ppdata, int total_data)
1053 /* We must be careful here that we don't return more than the
1054 allowed number of data bytes. If this means returning fewer than
1055 maxentries then so be it. We assume that the redirector has
1056 enough room for the fixed number of parameter bytes it has
1058 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1059 char *params = *pparams;
1060 char *pdata = *ppdata;
1061 int dptr_num = SVAL(params,0);
1062 int maxentries = SVAL(params,2);
1063 uint16 info_level = SVAL(params,4);
1064 uint32 resume_key = IVAL(params,6);
1065 BOOL close_after_request = BITSETW(params+10,0);
1066 BOOL close_if_end = BITSETW(params+10,1);
1067 BOOL requires_resume_key = BITSETW(params+10,2);
1068 BOOL continue_bit = BITSETW(params+10,3);
1069 pstring resume_name;
1075 int i, last_name_off=0;
1076 BOOL finished = False;
1077 BOOL dont_descend = False;
1078 BOOL out_of_space = False;
1079 int space_remaining;
1081 if (total_params < 12)
1082 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1084 *mask = *directory = *resume_name = 0;
1086 srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE);
1088 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1089 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1090 resume_key = %d resume name = %s continue=%d level = %d\n",
1091 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1092 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1094 switch (info_level) {
1095 case SMB_INFO_STANDARD:
1096 case SMB_INFO_QUERY_EA_SIZE:
1097 case SMB_FIND_FILE_DIRECTORY_INFO:
1098 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1099 case SMB_FIND_FILE_NAMES_INFO:
1100 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1102 case SMB_FIND_FILE_UNIX:
1103 if (!lp_unix_extensions())
1104 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1107 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1110 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1112 return ERROR_DOS(ERRDOS,ERRnomem);
1115 memset((char *)pdata,'\0',max_data_bytes + 1024);
1117 /* Realloc the params space */
1118 params = Realloc(*pparams, 6*SIZEOFWORD);
1119 if( params == NULL )
1120 return ERROR_DOS(ERRDOS,ERRnomem);
1124 /* Check that the dptr is valid */
1125 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1126 return ERROR_DOS(ERRDOS,ERRnofiles);
1128 string_set(&conn->dirpath,dptr_path(dptr_num));
1130 /* Get the wildcard mask from the dptr */
1131 if((p = dptr_wcard(dptr_num))== NULL) {
1132 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1133 return ERROR_DOS(ERRDOS,ERRnofiles);
1137 pstrcpy(directory,conn->dirpath);
1139 /* Get the attr mask from the dptr */
1140 dirtype = dptr_attr(dptr_num);
1142 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1143 dptr_num, mask, dirtype,
1145 TellDir(conn->dirptr)));
1147 /* We don't need to check for VOL here as this is returned by
1148 a different TRANS2 call. */
1150 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1151 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1152 dont_descend = True;
1155 space_remaining = max_data_bytes;
1156 out_of_space = False;
1159 * Seek to the correct position. We no longer use the resume key but
1160 * depend on the last file name instead.
1163 if(requires_resume_key && *resume_name && !continue_bit) {
1166 * Fix for NT redirector problem triggered by resume key indexes
1167 * changing between directory scans. We now return a resume key of 0
1168 * and instead look for the filename to continue from (also given
1169 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1170 * findfirst/findnext (as is usual) then the directory pointer
1171 * should already be at the correct place. Check this by scanning
1172 * backwards looking for an exact (ie. case sensitive) filename match.
1173 * If we get to the beginning of the directory and haven't found it then scan
1174 * forwards again looking for a match. JRA.
1177 int current_pos, start_pos;
1179 void *dirptr = conn->dirptr;
1180 start_pos = TellDir(dirptr);
1181 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1182 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1184 SeekDir(dirptr, current_pos);
1185 dname = ReadDirName(dirptr);
1188 * Remember, mangle_map is called by
1189 * get_lanman2_dir_entry(), so the resume name
1190 * could be mangled. Ensure we do the same
1195 mangle_map( dname, False, True, SNUM(conn));
1197 if(dname && strcsequal( resume_name, dname)) {
1198 SeekDir(dirptr, current_pos+1);
1199 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1205 * Scan forward from start if not found going backwards.
1208 if(current_pos < 0) {
1209 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1210 SeekDir(dirptr, start_pos);
1211 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1214 * Remember, mangle_map is called by
1215 * get_lanman2_dir_entry(), so the resume name
1216 * could be mangled. Ensure we do the same
1221 mangle_map( dname, False, True, SNUM(conn));
1223 if(dname && strcsequal( resume_name, dname)) {
1224 SeekDir(dirptr, current_pos+1);
1225 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1229 } /* end if current_pos */
1230 } /* end if requires_resume_key && !continue_bit */
1232 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1233 BOOL got_exact_match = False;
1235 /* this is a heuristic to avoid seeking the dirptr except when
1236 absolutely necessary. It allows for a filename of about 40 chars */
1237 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1238 out_of_space = True;
1241 finished = !get_lanman2_dir_entry(conn,
1243 mask,dirtype,info_level,
1244 requires_resume_key,dont_descend,
1245 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1249 if (finished && out_of_space)
1252 if (!finished && !out_of_space)
1256 * As an optimisation if we know we aren't looking
1257 * for a wildcard name (ie. the name matches the wildcard exactly)
1258 * then we can finish on any (first) match.
1259 * This speeds up large directory searches. JRA.
1265 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1268 /* Check if we can close the dirptr */
1269 if(close_after_request || (finished && close_if_end)) {
1270 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1271 dptr_close(&dptr_num); /* This frees up the saved mask */
1275 /* Set up the return parameter block */
1276 SSVAL(params,0,numentries);
1277 SSVAL(params,2,finished);
1278 SSVAL(params,4,0); /* Never an EA error */
1279 SSVAL(params,6,last_name_off);
1281 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1283 if ((! *directory) && dptr_path(dptr_num))
1284 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1286 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1287 smb_fn_name(CVAL(inbuf,smb_com)),
1288 mask, directory, dirtype, numentries ) );
1293 /****************************************************************************
1294 Reply to a TRANS2_QFSINFO (query filesystem info).
1295 ****************************************************************************/
1297 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1298 int length, int bufsize,
1299 char **pparams, int total_params, char **ppdata, int total_data)
1301 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1302 char *pdata = *ppdata;
1303 char *params = *pparams;
1304 uint16 info_level = SVAL(params,0);
1307 char *vname = volume_label(SNUM(conn));
1308 int snum = SNUM(conn);
1309 char *fstype = lp_fstype(SNUM(conn));
1311 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1313 if(vfs_stat(conn,".",&st)!=0) {
1314 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1315 return ERROR_DOS(ERRSRV,ERRinvdevice);
1318 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1319 if ( pdata == NULL )
1320 return ERROR_DOS(ERRDOS,ERRnomem);
1323 memset((char *)pdata,'\0',max_data_bytes + 1024);
1325 switch (info_level) {
1326 case SMB_INFO_ALLOCATION:
1328 SMB_BIG_UINT dfree,dsize,bsize;
1330 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1331 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1332 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1333 SIVAL(pdata,l1_cUnit,dsize);
1334 SIVAL(pdata,l1_cUnitAvail,dfree);
1335 SSVAL(pdata,l1_cbSector,512);
1336 DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1337 (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1338 (unsigned int)dfree, 512));
1342 case SMB_INFO_VOLUME:
1343 /* Return volume name */
1345 * Add volume serial number - hash of a combination of
1346 * the called hostname and the service name.
1348 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1349 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_TERMINATE);
1350 SCVAL(pdata,l2_vol_cch,len);
1351 data_len = l2_vol_szVolLabel + len;
1352 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1353 (unsigned)st.st_ctime, len, vname));
1356 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1357 case SMB_FS_ATTRIBUTE_INFORMATION:
1359 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1360 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */
1361 SIVAL(pdata,4,255); /* Max filename component length */
1362 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1363 and will think we can't do long filenames */
1364 len = srvstr_push(outbuf, pdata+12, fstype, -1, 0);
1366 data_len = 12 + len;
1369 case SMB_QUERY_FS_LABEL_INFO:
1370 case SMB_FS_LABEL_INFORMATION:
1371 len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE);
1376 case SMB_QUERY_FS_VOLUME_INFO:
1377 case SMB_FS_VOLUME_INFORMATION:
1380 * Add volume serial number - hash of a combination of
1381 * the called hostname and the service name.
1383 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1384 (str_checksum(local_machine)<<16));
1386 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE);
1387 SIVAL(pdata,12,len);
1389 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1390 (int)strlen(vname),vname, lp_servicename(snum)));
1393 case SMB_QUERY_FS_SIZE_INFO:
1394 case SMB_FS_SIZE_INFORMATION:
1396 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1398 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1399 block_size = lp_block_size(snum);
1400 if (bsize < block_size) {
1401 SMB_BIG_UINT factor = block_size/bsize;
1406 if (bsize > block_size) {
1407 SMB_BIG_UINT factor = bsize/block_size;
1412 bytes_per_sector = 512;
1413 sectors_per_unit = bsize/bytes_per_sector;
1414 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1415 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1416 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1417 SBIG_UINT(pdata,0,dsize);
1418 SBIG_UINT(pdata,8,dfree);
1419 SIVAL(pdata,16,sectors_per_unit);
1420 SIVAL(pdata,20,bytes_per_sector);
1424 case SMB_FS_FULL_SIZE_INFORMATION:
1426 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1428 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1429 block_size = lp_block_size(snum);
1430 if (bsize < block_size) {
1431 SMB_BIG_UINT factor = block_size/bsize;
1436 if (bsize > block_size) {
1437 SMB_BIG_UINT factor = bsize/block_size;
1442 bytes_per_sector = 512;
1443 sectors_per_unit = bsize/bytes_per_sector;
1444 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1445 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1446 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1447 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1448 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1449 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1450 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1451 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1455 case SMB_QUERY_FS_DEVICE_INFO:
1456 case SMB_FS_DEVICE_INFORMATION:
1458 SIVAL(pdata,0,0); /* dev type */
1459 SIVAL(pdata,4,0); /* characteristics */
1462 case SMB_FS_OBJECTID_INFORMATION:
1467 * Query the version and capabilities of the CIFS UNIX extensions
1471 case SMB_QUERY_CIFS_UNIX_INFO:
1472 if (!lp_unix_extensions())
1473 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1475 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
1476 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
1477 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
1480 case SMB_MAC_QUERY_FS_INFO:
1482 * Thursby MAC extension... ONLY on NTFS filesystems
1483 * once we do streams then we don't need this
1485 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1487 SIVAL(pdata,84,0x100); /* Don't support mac... */
1492 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1496 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1498 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1503 /****************************************************************************
1504 Reply to a TRANS2_SETFSINFO (set filesystem info).
1505 ****************************************************************************/
1507 static int call_trans2setfsinfo(connection_struct *conn,
1508 char *inbuf, char *outbuf, int length, int bufsize,
1509 char **pparams, int total_params, char **ppdata, int total_data)
1511 /* Just say yes we did it - there is nothing that
1512 can be set here so it doesn't matter. */
1514 DEBUG(3,("call_trans2setfsinfo\n"));
1516 if (!CAN_WRITE(conn))
1517 return ERROR_DOS(ERRSRV,ERRaccess);
1519 outsize = set_message(outbuf,10,0,True);
1524 /****************************************************************************
1525 * Utility function to set bad path error.
1526 ****************************************************************************/
1528 NTSTATUS set_bad_path_error(int err, BOOL bad_path)
1530 if((err == ENOENT) && bad_path) {
1531 unix_ERR_class = ERRDOS;
1532 unix_ERR_code = ERRbadpath;
1533 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1535 return NT_STATUS_OK;
1538 /****************************************************************************
1539 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1540 file name or file id).
1541 ****************************************************************************/
1543 static int call_trans2qfilepathinfo(connection_struct *conn,
1544 char *inbuf, char *outbuf, int length,
1546 char **pparams, int total_params, char **ppdata, int total_data)
1548 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1549 char *params = *pparams;
1550 char *pdata = *ppdata;
1551 uint16 tran_call = SVAL(inbuf, smb_setup0);
1554 SMB_OFF_T file_size=0;
1555 SMB_OFF_T allocation_size=0;
1556 unsigned int data_size;
1557 SMB_STRUCT_STAT sbuf;
1558 pstring fname, dos_fname;
1563 BOOL bad_path = False;
1564 BOOL delete_pending = False;
1567 files_struct *fsp = NULL;
1570 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1572 if (tran_call == TRANSACT2_QFILEINFO) {
1573 if (total_params < 4)
1574 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1576 fsp = file_fsp(params,0);
1577 info_level = SVAL(params,2);
1579 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1581 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1583 * This is actually a QFILEINFO on a directory
1584 * handle (returned from an NT SMB). NT5.0 seems
1585 * to do this call. JRA.
1587 pstrcpy(fname, fsp->fsp_name);
1588 unix_convert(fname,conn,0,&bad_path,&sbuf);
1589 if (!check_name(fname,conn)) {
1590 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1591 set_bad_path_error(errno, bad_path);
1592 return(UNIXERROR(ERRDOS,ERRbadpath));
1595 if (INFO_LEVEL_IS_UNIX(info_level)) {
1596 /* Always do lstat for UNIX calls. */
1597 if (vfs_lstat(conn,fname,&sbuf)) {
1598 DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
1599 set_bad_path_error(errno, bad_path);
1600 return(UNIXERROR(ERRDOS,ERRbadpath));
1602 } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
1603 DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
1604 set_bad_path_error(errno, bad_path);
1605 return(UNIXERROR(ERRDOS,ERRbadpath));
1608 delete_pending = fsp->directory_delete_on_close;
1611 * Original code - this is an open file.
1613 CHECK_FSP(fsp,conn);
1615 pstrcpy(fname, fsp->fsp_name);
1616 if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) {
1617 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
1618 return(UNIXERROR(ERRDOS,ERRbadfid));
1620 if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1621 return(UNIXERROR(ERRDOS,ERRnoaccess));
1623 delete_pending = fsp->delete_on_close;
1627 if (total_params < 6)
1628 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1630 info_level = SVAL(params,0);
1632 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1634 srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE);
1636 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1638 unix_convert(fname,conn,0,&bad_path,&sbuf);
1639 if (!check_name(fname,conn)) {
1640 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1641 set_bad_path_error(errno, bad_path);
1642 return(UNIXERROR(ERRDOS,ERRbadpath));
1645 if (INFO_LEVEL_IS_UNIX(info_level)) {
1646 /* Always do lstat for UNIX calls. */
1647 if (vfs_lstat(conn,fname,&sbuf)) {
1648 DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
1649 set_bad_path_error(errno, bad_path);
1650 return(UNIXERROR(ERRDOS,ERRbadpath));
1652 } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
1653 DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
1654 set_bad_path_error(errno, bad_path);
1655 return(UNIXERROR(ERRDOS,ERRbadpath));
1659 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
1660 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1662 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1663 fname,info_level,tran_call,total_data));
1665 p = strrchr_m(fname,'/');
1671 mode = dos_mode(conn,fname,&sbuf);
1672 fullpathname = fname;
1673 file_size = get_file_size(sbuf);
1674 allocation_size = get_allocation_size(fsp,&sbuf);
1678 params = Realloc(*pparams,2);
1680 return ERROR_DOS(ERRDOS,ERRnomem);
1682 memset((char *)params,'\0',2);
1683 data_size = max_data_bytes + 1024;
1684 pdata = Realloc(*ppdata, data_size);
1685 if ( pdata == NULL )
1686 return ERROR_DOS(ERRDOS,ERRnomem);
1689 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1690 /* uggh, EAs for OS2 */
1691 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1692 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1695 memset((char *)pdata,'\0',data_size);
1697 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1699 if (lp_dos_filetime_resolution(SNUM(conn))) {
1701 sbuf.st_atime &= ~1;
1702 sbuf.st_mtime &= ~1;
1703 sbuf.st_mtime &= ~1;
1706 /* NT expects the name to be in an exact form of the *full*
1707 filename. See the trans2 torture test */
1708 if (strequal(base_name,".")) {
1709 pstrcpy(dos_fname, "\\");
1711 snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname);
1712 string_replace(dos_fname, '/', '\\');
1715 switch (info_level) {
1716 case SMB_INFO_STANDARD:
1717 case SMB_INFO_QUERY_EA_SIZE:
1718 data_size = (info_level==1?22:26);
1719 put_dos_date2(pdata,l1_fdateCreation,c_time);
1720 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1721 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1722 SIVAL(pdata,l1_cbFile,(uint32)file_size);
1723 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
1724 SSVAL(pdata,l1_attrFile,mode);
1725 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1728 case SMB_INFO_QUERY_EAS_FROM_LIST:
1730 put_dos_date2(pdata,0,c_time);
1731 put_dos_date2(pdata,4,sbuf.st_atime);
1732 put_dos_date2(pdata,8,sbuf.st_mtime);
1733 SIVAL(pdata,12,(uint32)file_size);
1734 SIVAL(pdata,16,(uint32)allocation_size);
1735 SIVAL(pdata,20,mode);
1738 case SMB_INFO_QUERY_ALL_EAS:
1740 SIVAL(pdata,0,data_size);
1744 return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */
1746 case SMB_FILE_BASIC_INFORMATION:
1747 case SMB_QUERY_FILE_BASIC_INFO:
1749 if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1750 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1755 put_long_date(pdata,c_time);
1756 put_long_date(pdata+8,sbuf.st_atime);
1757 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1758 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1759 SIVAL(pdata,32,mode);
1761 DEBUG(5,("SMB_QFBI - "));
1763 time_t create_time = c_time;
1764 DEBUG(5,("create: %s ", ctime(&create_time)));
1766 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1767 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1768 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1769 DEBUG(5,("mode: %x\n", mode));
1773 case SMB_FILE_STANDARD_INFORMATION:
1774 case SMB_QUERY_FILE_STANDARD_INFO:
1777 SOFF_T(pdata,0,allocation_size);
1778 SOFF_T(pdata,8,file_size);
1779 SIVAL(pdata,16,sbuf.st_nlink);
1781 SCVAL(pdata,21,(mode&aDIR)?1:0);
1784 case SMB_FILE_EA_INFORMATION:
1785 case SMB_QUERY_FILE_EA_INFO:
1789 /* Get the 8.3 name - used if NT SMB was negotiated. */
1790 case SMB_QUERY_FILE_ALT_NAME_INFO:
1794 pstrcpy(short_name,base_name);
1795 /* Mangle if not already 8.3 */
1796 if(!mangle_is_8_3(short_name, True)) {
1797 mangle_map(short_name,True,True,SNUM(conn));
1799 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_TERMINATE|STR_UPPER);
1800 data_size = 4 + len;
1805 case SMB_QUERY_FILE_NAME_INFO:
1807 this must be *exactly* right for ACLs on mapped drives to work
1809 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
1810 data_size = 4 + len;
1814 case SMB_FILE_ALLOCATION_INFORMATION:
1815 case SMB_QUERY_FILE_ALLOCATION_INFO:
1817 SOFF_T(pdata,0,allocation_size);
1820 case SMB_FILE_END_OF_FILE_INFORMATION:
1821 case SMB_QUERY_FILE_END_OF_FILEINFO:
1823 SOFF_T(pdata,0,file_size);
1826 case SMB_QUERY_FILE_ALL_INFO:
1827 put_long_date(pdata,c_time);
1828 put_long_date(pdata+8,sbuf.st_atime);
1829 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1830 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1831 SIVAL(pdata,32,mode);
1833 SOFF_T(pdata,0,allocation_size);
1834 SOFF_T(pdata,8,file_size);
1835 SIVAL(pdata,16,sbuf.st_nlink);
1836 SCVAL(pdata,20,delete_pending);
1837 SCVAL(pdata,21,(mode&aDIR)?1:0);
1839 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);
1840 pdata += 8; /* index number */
1841 pdata += 4; /* EA info */
1843 SIVAL(pdata,0,0xA9);
1845 SIVAL(pdata,0,0xd01BF);
1847 SOFF_T(pdata,0,pos); /* current offset */
1849 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1851 pdata += 4; /* alignment */
1852 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_TERMINATE);
1855 data_size = PTR_DIFF(pdata,(*ppdata));
1858 case SMB_FILE_INTERNAL_INFORMATION:
1859 /* This should be an index number - looks like
1862 I think this causes us to fail the IFSKIT
1863 BasicFileInformationTest. -tpot */
1865 SIVAL(pdata,0,sbuf.st_dev);
1866 SIVAL(pdata,4,sbuf.st_ino);
1870 case SMB_FILE_ACCESS_INFORMATION:
1871 SIVAL(pdata,0,0x12019F); /* ??? */
1875 case SMB_FILE_NAME_INFORMATION:
1876 /* Pathname with leading '\'. */
1879 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
1880 SIVAL(pdata,0,byte_len);
1881 data_size = 4 + byte_len;
1885 case SMB_FILE_DISPOSITION_INFORMATION:
1887 SCVAL(pdata,0,delete_pending);
1890 case SMB_FILE_POSITION_INFORMATION:
1892 SOFF_T(pdata,0,pos);
1895 case SMB_FILE_MODE_INFORMATION:
1896 SIVAL(pdata,0,mode);
1900 case SMB_FILE_ALIGNMENT_INFORMATION:
1901 SIVAL(pdata,0,0); /* No alignment needed. */
1906 /* Not yet finished... JRA */
1909 put_long_date(pdata,c_time);
1910 put_long_date(pdata+8,sbuf.st_atime);
1911 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1912 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1913 SIVAL(pdata,32,mode);
1914 SIVAL(pdata,36,0); /* ??? */
1915 SIVAL(pdata,40,0x20); /* ??? */
1916 SIVAL(pdata,44,0); /* ??? */
1917 SOFF_T(pdata,48,size);
1918 SIVAL(pdata,56,0x1); /* ??? */
1919 SIVAL(pdata,60,0); /* ??? */
1920 SIVAL(pdata,64,0); /* ??? */
1921 SIVAL(pdata,68,length); /* Following string length in bytes. */
1922 dos_PutUniCode(pdata+72,,False);
1927 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
1928 /* Last component of pathname. */
1930 size_t byte_len = dos_PutUniCode(pdata+4,fname,max_data_bytes,False);
1931 SIVAL(pdata,0,byte_len);
1932 data_size = 4 + byte_len;
1938 * NT4 server just returns "invalid query" to this - if we try to answer
1939 * it then NTws gets a BSOD! (tridge).
1940 * W2K seems to want this. JRA.
1942 case SMB_QUERY_FILE_STREAM_INFO:
1944 case SMB_FILE_STREAM_INFORMATION:
1948 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
1949 SIVAL(pdata,0,0); /* ??? */
1950 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
1951 SOFF_T(pdata,8,file_size);
1952 SIVAL(pdata,16,allocation_size);
1953 SIVAL(pdata,20,0); /* ??? */
1954 data_size = 24 + byte_len;
1958 case SMB_FILE_COMPRESSION_INFORMATION:
1959 SOFF_T(pdata,0,allocation_size);
1960 SIVAL(pdata,8,0); /* ??? */
1961 SIVAL(pdata,12,0); /* ??? */
1965 case SMB_FILE_NETWORK_OPEN_INFORMATION:
1966 put_long_date(pdata,c_time);
1967 put_long_date(pdata+8,sbuf.st_atime);
1968 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1969 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1970 SIVAL(pdata,32,allocation_size);
1971 SOFF_T(pdata,40,file_size);
1972 SIVAL(pdata,48,mode);
1973 SIVAL(pdata,52,0); /* ??? */
1977 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
1978 SIVAL(pdata,0,mode);
1984 * CIFS UNIX Extensions.
1987 case SMB_QUERY_FILE_UNIX_BASIC:
1989 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
1991 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
1994 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1997 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
1998 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
1999 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2002 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2006 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2010 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2013 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2017 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2021 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2024 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2028 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2031 data_size = PTR_DIFF(pdata,(*ppdata));
2035 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2037 for (i=0; i<100; i++)
2038 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2044 case SMB_QUERY_FILE_UNIX_LINK:
2049 if(!S_ISLNK(sbuf.st_mode))
2050 return(UNIXERROR(ERRSRV,ERRbadlink));
2052 return(UNIXERROR(ERRDOS,ERRbadlink));
2054 len = conn->vfs_ops.readlink(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2056 return(UNIXERROR(ERRDOS,ERRnoaccess));
2058 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2060 data_size = PTR_DIFF(pdata,(*ppdata));
2066 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2069 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size);
2074 /****************************************************************************
2075 Deal with the internal needs of setting the delete on close flag. Note that
2076 as the tdb locking is recursive, it is safe to call this from within
2077 open_file_shared. JRA.
2078 ****************************************************************************/
2080 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2083 * Only allow delete on close for writable shares.
2086 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2087 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2089 return NT_STATUS_ACCESS_DENIED;
2092 * Only allow delete on close for files/directories opened with delete intent.
2095 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2096 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2098 return NT_STATUS_ACCESS_DENIED;
2101 if(fsp->is_directory) {
2102 fsp->directory_delete_on_close = delete_on_close;
2103 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2104 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2107 files_struct *iterate_fsp;
2110 * Modify the share mode entry for all files open
2111 * on this device and inode to tell other smbds we have
2112 * changed the delete on close flag. This will be noticed
2113 * in the close code, the last closer will delete the file
2117 DEBUG(10,("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2118 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2120 if (lock_share_entry_fsp(fsp) == False)
2121 return NT_STATUS_ACCESS_DENIED;
2123 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2124 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2126 unlock_share_entry_fsp(fsp);
2127 return NT_STATUS_ACCESS_DENIED;
2134 unlock_share_entry_fsp(fsp);
2137 * Go through all files we have open on the same device and
2138 * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
2139 * Other smbd's that have this file open will look in the share_mode on close.
2140 * take care of this (rare) case in close_file(). See the comment there.
2141 * NB. JRA. We don't really need to do this anymore - all should be taken
2142 * care of in the share_mode changes in the tdb.
2145 for(iterate_fsp = file_find_di_first(fsp->dev, fsp->inode);
2146 iterate_fsp; iterate_fsp = file_find_di_next(iterate_fsp))
2147 fsp->delete_on_close = delete_on_close;
2150 * Set the delete on close flag in the fsp.
2152 fsp->delete_on_close = delete_on_close;
2154 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2155 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2159 return NT_STATUS_OK;
2162 /****************************************************************************
2163 Returns true if this pathname is within the share, and thus safe.
2164 ****************************************************************************/
2166 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2169 char resolved_name[PATH_MAX+1];
2171 pstring resolved_name;
2173 fstring last_component;
2177 BOOL bad_path = False;
2178 SMB_STRUCT_STAT sbuf;
2180 pstrcpy(link_dest, link_dest_in);
2181 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2183 /* Store the UNIX converted path. */
2184 pstrcpy(link_dest_out, link_dest);
2186 p = strrchr(link_dest, '/');
2188 fstrcpy(last_component, p+1);
2191 fstrcpy(last_component, link_dest);
2192 pstrcpy(link_dest, "./");
2195 if (conn->vfs_ops.realpath(conn,link_dest,resolved_name) == NULL)
2198 pstrcpy(link_dest, resolved_name);
2199 pstrcat(link_dest, "/");
2200 pstrcat(link_dest, last_component);
2202 if (*link_dest != '/') {
2203 /* Relative path. */
2204 pstrcpy(link_test, conn->connectpath);
2205 pstrcat(link_test, "/");
2206 pstrcat(link_test, link_dest);
2208 pstrcpy(link_test, link_dest);
2212 * Check if the link is within the share.
2215 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2222 /****************************************************************************
2223 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2224 ****************************************************************************/
2226 static int call_trans2setfilepathinfo(connection_struct *conn,
2227 char *inbuf, char *outbuf, int length, int bufsize,
2228 char **pparams, int total_params, char **ppdata, int total_data)
2230 char *params = *pparams;
2231 char *pdata = *ppdata;
2232 uint16 tran_call = SVAL(inbuf, smb_setup0);
2237 SMB_STRUCT_STAT sbuf;
2240 BOOL bad_path = False;
2241 files_struct *fsp = NULL;
2242 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2243 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2244 mode_t unixmode = 0;
2246 if (tran_call == TRANSACT2_SETFILEINFO) {
2247 fsp = file_fsp(params,0);
2248 info_level = SVAL(params,2);
2250 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2252 * This is actually a SETFILEINFO on a directory
2253 * handle (returned from an NT SMB). NT5.0 seems
2254 * to do this call. JRA.
2256 pstrcpy(fname, fsp->fsp_name);
2257 unix_convert(fname,conn,0,&bad_path,&sbuf);
2258 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2259 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2260 set_bad_path_error(errno, bad_path);
2261 return(UNIXERROR(ERRDOS,ERRbadpath));
2263 } else if (fsp && fsp->print_file) {
2265 * Doing a DELETE_ON_CLOSE should cancel a print job.
2267 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
2268 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2270 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
2273 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2276 return (UNIXERROR(ERRDOS,ERRbadpath));
2279 * Original code - this is an open file.
2281 CHECK_FSP(fsp,conn);
2283 pstrcpy(fname, fsp->fsp_name);
2286 if (vfs_fstat(fsp,fd,&sbuf) != 0) {
2287 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2288 return(UNIXERROR(ERRDOS,ERRbadfid));
2293 if (total_params < 6)
2294 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2296 info_level = SVAL(params,0);
2297 srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE);
2298 unix_convert(fname,conn,0,&bad_path,&sbuf);
2299 if(!check_name(fname, conn)) {
2300 set_bad_path_error(errno, bad_path);
2301 return(UNIXERROR(ERRDOS,ERRbadpath));
2305 * For CIFS UNIX extensions the target name may not exist.
2308 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2309 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
2310 set_bad_path_error(errno, bad_path);
2311 return(UNIXERROR(ERRDOS,ERRbadpath));
2315 if (!CAN_WRITE(conn))
2316 return ERROR_DOS(ERRSRV,ERRaccess);
2318 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2319 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2321 if (VALID_STAT(sbuf))
2322 unixmode = sbuf.st_mode;
2324 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
2325 tran_call,fname,info_level,total_data));
2327 /* Realloc the parameter and data sizes */
2328 params = Realloc(*pparams,2);
2330 return ERROR_DOS(ERRDOS,ERRnomem);
2336 /* the pending modtime overrides the current modtime */
2337 sbuf.st_mtime = fsp->pending_modtime;
2340 size = get_file_size(sbuf);
2341 tvs.modtime = sbuf.st_mtime;
2342 tvs.actime = sbuf.st_atime;
2343 dosmode = dos_mode(conn,fname,&sbuf);
2344 unixmode = sbuf.st_mode;
2346 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2347 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2349 switch (info_level) {
2350 case SMB_INFO_STANDARD:
2352 if (total_data < l1_cbFile+4)
2353 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2356 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2359 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2361 dosmode = SVAL(pdata,l1_attrFile);
2362 size = IVAL(pdata,l1_cbFile);
2367 case SMB_INFO_SET_EA:
2368 return(ERROR_DOS(ERRDOS,ERReasnotsupported));
2370 /* XXXX um, i don't think this is right.
2371 it's also not in the cifs6.txt spec.
2373 case SMB_INFO_QUERY_EAS_FROM_LIST:
2374 if (total_data < 28)
2375 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2377 tvs.actime = make_unix_date2(pdata+8);
2378 tvs.modtime = make_unix_date2(pdata+12);
2379 size = IVAL(pdata,16);
2380 dosmode = IVAL(pdata,24);
2383 /* XXXX nor this. not in cifs6.txt, either. */
2384 case SMB_INFO_QUERY_ALL_EAS:
2385 if (total_data < 28)
2386 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2388 tvs.actime = make_unix_date2(pdata+8);
2389 tvs.modtime = make_unix_date2(pdata+12);
2390 size = IVAL(pdata,16);
2391 dosmode = IVAL(pdata,24);
2394 case SMB_SET_FILE_BASIC_INFO:
2395 case SMB_FILE_BASIC_INFORMATION:
2397 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2399 time_t changed_time;
2401 if (total_data < 36)
2402 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2404 /* Ignore create time at offset pdata. */
2407 tvs.actime = interpret_long_date(pdata+8);
2409 write_time = interpret_long_date(pdata+16);
2410 changed_time = interpret_long_date(pdata+24);
2412 tvs.modtime = MIN(write_time, changed_time);
2414 if (write_time > tvs.modtime && write_time != 0xffffffff) {
2415 tvs.modtime = write_time;
2417 /* Prefer a defined time to an undefined one. */
2418 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2419 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2420 ? changed_time : write_time);
2423 dosmode = IVAL(pdata,32);
2427 case SMB_FILE_ALLOCATION_INFORMATION:
2428 case SMB_SET_FILE_ALLOCATION_INFO:
2431 SMB_OFF_T allocation_size;
2434 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2436 allocation_size = IVAL(pdata,0);
2437 #ifdef LARGE_SMB_OFF_T
2438 allocation_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2439 #else /* LARGE_SMB_OFF_T */
2440 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2441 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2442 #endif /* LARGE_SMB_OFF_T */
2443 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2444 fname, (double)allocation_size ));
2446 if (allocation_size)
2447 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
2449 if(allocation_size != get_file_size(sbuf)) {
2450 SMB_STRUCT_STAT new_sbuf;
2452 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2453 fname, (double)allocation_size ));
2456 files_struct *new_fsp = NULL;
2457 int access_mode = 0;
2460 if(global_oplock_break) {
2461 /* Queue this file modify as we are the process of an oplock break. */
2463 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2464 DEBUGADD(2,( "in oplock break state.\n"));
2466 push_oplock_pending_smb_message(inbuf, length);
2470 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2471 SET_OPEN_MODE(DOS_OPEN_RDWR),
2472 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2473 0, 0, &access_mode, &action);
2475 if (new_fsp == NULL)
2476 return(UNIXERROR(ERRDOS,ERRbadpath));
2477 ret = vfs_allocate_file_space(new_fsp, allocation_size);
2478 if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2479 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2480 new_fsp->fnum, strerror(errno)));
2483 close_file(new_fsp,True);
2485 ret = vfs_allocate_file_space(fsp, allocation_size);
2486 if (vfs_fstat(fsp,fd,&new_sbuf) != 0) {
2487 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2488 fsp->fnum, strerror(errno)));
2493 return ERROR_NT(NT_STATUS_DISK_FULL);
2495 /* Allocate can truncate size... */
2496 size = get_file_size(new_sbuf);
2502 case SMB_FILE_END_OF_FILE_INFORMATION:
2503 case SMB_SET_FILE_END_OF_FILE_INFO:
2506 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2508 size = IVAL(pdata,0);
2509 #ifdef LARGE_SMB_OFF_T
2510 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2511 #else /* LARGE_SMB_OFF_T */
2512 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2513 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2514 #endif /* LARGE_SMB_OFF_T */
2515 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2519 case SMB_FILE_DISPOSITION_INFORMATION:
2520 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2522 BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
2526 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2528 if (tran_call != TRANSACT2_SETFILEINFO)
2529 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2532 return(UNIXERROR(ERRDOS,ERRbadfid));
2534 status = set_delete_on_close_internal(fsp, delete_on_close);
2536 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2537 return ERROR_NT(status);
2543 * CIFS UNIX extensions.
2546 case SMB_SET_FILE_UNIX_BASIC:
2548 uint32 raw_unixmode;
2550 if (total_data < 100)
2551 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2553 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
2554 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
2555 size=IVAL(pdata,0); /* first 8 Bytes are size */
2556 #ifdef LARGE_SMB_OFF_T
2557 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2558 #else /* LARGE_SMB_OFF_T */
2559 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2560 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2561 #endif /* LARGE_SMB_OFF_T */
2563 pdata+=24; /* ctime & st_blocks are not changed */
2564 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
2565 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
2567 set_owner = (uid_t)IVAL(pdata,0);
2569 set_grp = (gid_t)IVAL(pdata,0);
2571 raw_unixmode = IVAL(pdata,28);
2572 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2573 dosmode = 0; /* Ensure dos mode change doesn't override this. */
2575 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2576 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2577 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2579 if (!VALID_STAT(sbuf)) {
2582 * The only valid use of this is to create character and block
2583 * devices, and named pipes. This is deprecated (IMHO) and
2584 * a new info level should be used for mknod. JRA.
2587 #if !defined(HAVE_MAKEDEV_FN)
2588 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2589 #else /* HAVE_MAKEDEV_FN */
2590 uint32 file_type = IVAL(pdata,0);
2591 uint32 dev_major = IVAL(pdata,4);
2592 uint32 dev_minor = IVAL(pdata,12);
2594 uid_t myuid = geteuid();
2595 gid_t mygid = getegid();
2598 if (tran_call == TRANSACT2_SETFILEINFO)
2599 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2601 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2602 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2604 dev = makedev(dev_major, dev_minor);
2606 /* We can only create as the owner/group we are. */
2608 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2609 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2610 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2611 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2613 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2614 file_type != UNIX_TYPE_FIFO)
2615 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2617 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2618 0%o for file %s\n", (double)dev, unixmode, fname ));
2620 /* Ok - do the mknod. */
2621 if (conn->vfs_ops.mknod(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
2622 return(UNIXERROR(ERRDOS,ERRnoaccess));
2624 inherit_access_acl(conn, fname, unixmode);
2627 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2629 #endif /* HAVE_MAKEDEV_FN */
2634 * Deal with the UNIX specific mode set.
2637 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
2638 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2639 (unsigned int)unixmode, fname ));
2640 if (vfs_chmod(conn,fname,unixmode) != 0)
2641 return(UNIXERROR(ERRDOS,ERRnoaccess));
2645 * Deal with the UNIX specific uid set.
2648 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
2649 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2650 (unsigned int)set_owner, fname ));
2651 if (vfs_chown(conn,fname,set_owner, (gid_t)-1) != 0)
2652 return(UNIXERROR(ERRDOS,ERRnoaccess));
2656 * Deal with the UNIX specific gid set.
2659 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
2660 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2661 (unsigned int)set_owner, fname ));
2662 if (vfs_chown(conn,fname,(uid_t)-1, set_grp) != 0)
2663 return(UNIXERROR(ERRDOS,ERRnoaccess));
2668 case SMB_SET_FILE_UNIX_LINK:
2671 /* Set a symbolic link. */
2672 /* Don't allow this if follow links is false. */
2674 if (!lp_symlinks(SNUM(conn)))
2675 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2677 /* Disallow if already exists. */
2678 if (VALID_STAT(sbuf))
2679 return(ERROR_DOS(ERRDOS,ERRbadpath));
2681 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2683 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2684 return(UNIXERROR(ERRDOS,ERRnoaccess));
2686 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2687 fname, link_dest ));
2689 if (conn->vfs_ops.symlink(conn,link_dest,fname) != 0)
2690 return(UNIXERROR(ERRDOS,ERRnoaccess));
2692 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2696 case SMB_SET_FILE_UNIX_HLINK:
2700 /* Set a hard link. */
2702 /* Disallow if already exists. */
2703 if (VALID_STAT(sbuf))
2704 return(ERROR_DOS(ERRDOS,ERRbadpath));
2706 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2708 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2709 return(UNIXERROR(ERRDOS,ERRnoaccess));
2711 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2712 fname, link_dest ));
2714 if (conn->vfs_ops.link(conn,link_dest,fname) != 0)
2715 return(UNIXERROR(ERRDOS,ERRnoaccess));
2717 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2722 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2725 /* get some defaults (no modifications) if any info is zero or -1. */
2726 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2727 tvs.actime = sbuf.st_atime;
2729 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2730 tvs.modtime = sbuf.st_mtime;
2732 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2733 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2734 DEBUG(6,("size: %.0f ", (double)size));
2736 if (S_ISDIR(sbuf.st_mode))
2741 DEBUG(6,("dosmode: %x\n" , dosmode));
2743 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2744 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2745 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2746 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2749 * Only do this test if we are not explicitly
2750 * changing the size of a file.
2753 size = get_file_size(sbuf);
2757 * Try and set the times, size and mode of this file -
2758 * if they are different from the current values
2760 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2763 * This was a setfileinfo on an open file.
2764 * NT does this a lot. It's actually pointless
2765 * setting the time here, as it will be overwritten
2766 * on the next write, so we save the request
2767 * away and will set it on file close. JRA.
2770 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2771 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
2772 fsp->pending_modtime = tvs.modtime;
2777 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2779 if(file_utime(conn, fname, &tvs)!=0)
2780 return(UNIXERROR(ERRDOS,ERRnoaccess));
2784 /* check the mode isn't different, before changing it */
2785 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
2787 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
2789 if(file_chmod(conn, fname, dosmode, NULL)) {
2790 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2791 return(UNIXERROR(ERRDOS,ERRnoaccess));
2795 if (size != get_file_size(sbuf)) {
2799 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2800 fname, (double)size ));
2803 files_struct *new_fsp = NULL;
2804 int access_mode = 0;
2807 if(global_oplock_break) {
2808 /* Queue this file modify as we are the process of an oplock break. */
2810 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2811 DEBUGADD(2,( "in oplock break state.\n"));
2813 push_oplock_pending_smb_message(inbuf, length);
2817 new_fsp = open_file_shared(conn, fname, &sbuf,
2818 SET_OPEN_MODE(DOS_OPEN_RDWR),
2819 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2820 0, 0, &access_mode, &action);
2822 if (new_fsp == NULL)
2823 return(UNIXERROR(ERRDOS,ERRbadpath));
2824 ret = vfs_set_filelen(new_fsp, size);
2825 close_file(new_fsp,True);
2827 ret = vfs_set_filelen(fsp, size);
2831 return (UNIXERROR(ERRHRD,ERRdiskfull));
2835 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2840 /****************************************************************************
2841 Reply to a TRANS2_MKDIR (make directory with extended attributes).
2842 ****************************************************************************/
2844 static int call_trans2mkdir(connection_struct *conn,
2845 char *inbuf, char *outbuf, int length, int bufsize,
2846 char **pparams, int total_params, char **ppdata, int total_data)
2848 char *params = *pparams;
2851 SMB_STRUCT_STAT sbuf;
2852 BOOL bad_path = False;
2854 if (!CAN_WRITE(conn))
2855 return ERROR_DOS(ERRSRV,ERRaccess);
2857 if (total_params < 4)
2858 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2860 srvstr_pull(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE);
2862 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
2864 unix_convert(directory,conn,0,&bad_path,&sbuf);
2865 if (check_name(directory,conn))
2866 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2869 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
2870 set_bad_path_error(errno, bad_path);
2871 return(UNIXERROR(ERRDOS,ERRnoaccess));
2874 /* Realloc the parameter and data sizes */
2875 params = Realloc(*pparams,2);
2877 return ERROR_DOS(ERRDOS,ERRnomem);
2882 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2887 /****************************************************************************
2888 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
2889 We don't actually do this - we just send a null response.
2890 ****************************************************************************/
2892 static int call_trans2findnotifyfirst(connection_struct *conn,
2893 char *inbuf, char *outbuf, int length, int bufsize,
2894 char **pparams, int total_params, char **ppdata, int total_data)
2896 static uint16 fnf_handle = 257;
2897 char *params = *pparams;
2900 if (total_params < 6)
2901 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2903 info_level = SVAL(params,4);
2904 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
2906 switch (info_level) {
2911 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2914 /* Realloc the parameter and data sizes */
2915 params = Realloc(*pparams,6);
2917 return ERROR_DOS(ERRDOS,ERRnomem);
2920 SSVAL(params,0,fnf_handle);
2921 SSVAL(params,2,0); /* No changes */
2922 SSVAL(params,4,0); /* No EA errors */
2929 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
2934 /****************************************************************************
2935 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
2936 changes). Currently this does nothing.
2937 ****************************************************************************/
2939 static int call_trans2findnotifynext(connection_struct *conn,
2940 char *inbuf, char *outbuf, int length, int bufsize,
2941 char **pparams, int total_params, char **ppdata, int total_data)
2943 char *params = *pparams;
2945 DEBUG(3,("call_trans2findnotifynext\n"));
2947 /* Realloc the parameter and data sizes */
2948 params = Realloc(*pparams,4);
2950 return ERROR_DOS(ERRDOS,ERRnomem);
2953 SSVAL(params,0,0); /* No changes */
2954 SSVAL(params,2,0); /* No EA errors */
2956 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2961 /****************************************************************************
2962 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
2963 ****************************************************************************/
2965 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
2966 char* outbuf, int length, int bufsize,
2967 char **pparams, int total_params, char **ppdata, int total_data)
2969 char *params = *pparams;
2972 int max_referral_level;
2974 DEBUG(10,("call_trans2getdfsreferral\n"));
2976 if (total_params < 2)
2977 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2979 max_referral_level = SVAL(params,0);
2981 if(!lp_host_msdfs())
2982 return ERROR_DOS(ERRDOS,ERRbadfunc);
2984 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
2986 if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
2987 return ERROR_DOS(ERRDOS,ERRbadfile);
2989 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
2990 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
2995 #define LMCAT_SPL 0x53
2996 #define LMFUNC_GETJOBID 0x60
2998 /****************************************************************************
2999 Reply to a TRANS2_IOCTL - used for OS/2 printing.
3000 ****************************************************************************/
3002 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3003 char* outbuf, int length, int bufsize,
3004 char **pparams, int total_params, char **ppdata, int total_data)
3006 char *pdata = *ppdata;
3007 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3009 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3010 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3013 pdata = Realloc(*ppdata, 32);
3015 return ERROR_DOS(ERRDOS,ERRnomem);
3018 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3019 CAN ACCEPT THIS IN UNICODE. JRA. */
3021 rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid); /* Job number */
3022 SSVAL(pdata,0,rap_jobid); /* Job number */
3023 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3024 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3025 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3028 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3029 return ERROR_DOS(ERRSRV,ERRerror);
3033 /****************************************************************************
3034 Reply to a SMBfindclose (stop trans2 directory search).
3035 ****************************************************************************/
3037 int reply_findclose(connection_struct *conn,
3038 char *inbuf,char *outbuf,int length,int bufsize)
3041 int dptr_num=SVALS(inbuf,smb_vwv0);
3042 START_PROFILE(SMBfindclose);
3044 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3046 dptr_close(&dptr_num);
3048 outsize = set_message(outbuf,0,0,True);
3050 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3052 END_PROFILE(SMBfindclose);
3056 /****************************************************************************
3057 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3058 ****************************************************************************/
3060 int reply_findnclose(connection_struct *conn,
3061 char *inbuf,char *outbuf,int length,int bufsize)
3065 START_PROFILE(SMBfindnclose);
3067 dptr_num = SVAL(inbuf,smb_vwv0);
3069 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3071 /* We never give out valid handles for a
3072 findnotifyfirst - so any dptr_num is ok here.
3075 outsize = set_message(outbuf,0,0,True);
3077 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3079 END_PROFILE(SMBfindnclose);
3083 /****************************************************************************
3084 Reply to a SMBtranss2 - just ignore it!
3085 ****************************************************************************/
3087 int reply_transs2(connection_struct *conn,
3088 char *inbuf,char *outbuf,int length,int bufsize)
3090 START_PROFILE(SMBtranss2);
3091 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3092 END_PROFILE(SMBtranss2);
3096 /****************************************************************************
3097 Reply to a SMBtrans2.
3098 ****************************************************************************/
3100 int reply_trans2(connection_struct *conn,
3101 char *inbuf,char *outbuf,int length,int bufsize)
3104 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3105 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3107 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3108 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3109 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3110 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3111 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3112 int32 timeout = IVALS(inbuf,smb_timeout);
3114 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3115 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3116 char *params = NULL, *data = NULL;
3117 int num_params, num_params_sofar, num_data, num_data_sofar;
3118 START_PROFILE(SMBtrans2);
3120 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3121 /* Queue this open message as we are the process of an
3124 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3125 DEBUGADD(2,( "in oplock break state.\n"));
3127 push_oplock_pending_smb_message(inbuf, length);
3128 END_PROFILE(SMBtrans2);
3132 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3133 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3134 END_PROFILE(SMBtrans2);
3135 return ERROR_DOS(ERRSRV,ERRaccess);
3138 outsize = set_message(outbuf,0,0,True);
3140 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3141 is so as a sanity check */
3144 * Need to have rc=0 for ioctl to get job id for OS/2.
3145 * Network printing will fail if function is not successful.
3146 * Similar function in reply.c will be used if protocol
3147 * is LANMAN1.0 instead of LM1.2X002.
3148 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3149 * outbuf doesn't have to be set(only job id is used).
3151 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3152 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3153 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3154 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3156 DEBUG(2,("Invalid smb_sucnt in trans2 call(%d)\n",suwcnt));
3157 DEBUG(2,("Transaction is %d\n",tran_call));
3158 END_PROFILE(SMBtrans2);
3159 return ERROR_DOS(ERRSRV,ERRerror);
3163 /* Allocate the space for the maximum needed parameters and data */
3164 if (total_params > 0)
3165 params = (char *)malloc(total_params);
3167 data = (char *)malloc(total_data);
3169 if ((total_params && !params) || (total_data && !data)) {
3170 DEBUG(2,("Out of memory in reply_trans2\n"));
3173 END_PROFILE(SMBtrans2);
3174 return ERROR_DOS(ERRDOS,ERRnomem);
3177 /* Copy the param and data bytes sent with this request into
3178 the params buffer */
3179 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3180 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3182 if (num_params > total_params || num_data > total_data)
3183 exit_server("invalid params in reply_trans2");
3186 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
3188 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
3190 if(num_data_sofar < total_data || num_params_sofar < total_params) {
3191 /* We need to send an interim response then receive the rest
3192 of the parameter/data bytes */
3193 outsize = set_message(outbuf,0,0,True);
3194 if (!send_smb(smbd_server_fd(),outbuf))
3195 exit_server("reply_trans2: send_smb failed.");
3197 while (num_data_sofar < total_data ||
3198 num_params_sofar < total_params) {
3201 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3204 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3205 outsize = set_message(outbuf,0,0,True);
3207 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3209 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3210 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3213 END_PROFILE(SMBtrans2);
3214 return ERROR_DOS(ERRSRV,ERRerror);
3217 /* Revise total_params and total_data in case
3218 they have changed downwards */
3219 total_params = SVAL(inbuf, smb_tpscnt);
3220 total_data = SVAL(inbuf, smb_tdscnt);
3221 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
3222 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
3223 if (num_params_sofar > total_params || num_data_sofar > total_data)
3224 exit_server("data overflow in trans2");
3226 memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)],
3227 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
3228 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
3229 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
3233 if (Protocol >= PROTOCOL_NT1) {
3234 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
3237 /* Now we must call the relevant TRANS2 function */
3239 case TRANSACT2_OPEN:
3240 START_PROFILE_NESTED(Trans2_open);
3241 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
3242 ¶ms, total_params, &data, total_data);
3243 END_PROFILE_NESTED(Trans2_open);
3246 case TRANSACT2_FINDFIRST:
3247 START_PROFILE_NESTED(Trans2_findfirst);
3248 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3249 ¶ms, total_params, &data, total_data);
3250 END_PROFILE_NESTED(Trans2_findfirst);
3253 case TRANSACT2_FINDNEXT:
3254 START_PROFILE_NESTED(Trans2_findnext);
3255 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
3256 ¶ms, total_params, &data, total_data);
3257 END_PROFILE_NESTED(Trans2_findnext);
3260 case TRANSACT2_QFSINFO:
3261 START_PROFILE_NESTED(Trans2_qfsinfo);
3262 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3263 ¶ms, total_params, &data, total_data);
3264 END_PROFILE_NESTED(Trans2_qfsinfo);
3267 case TRANSACT2_SETFSINFO:
3268 START_PROFILE_NESTED(Trans2_setfsinfo);
3269 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
3270 ¶ms, total_params, &data, total_data);
3271 END_PROFILE_NESTED(Trans2_setfsinfo);
3274 case TRANSACT2_QPATHINFO:
3275 case TRANSACT2_QFILEINFO:
3276 START_PROFILE_NESTED(Trans2_qpathinfo);
3277 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3278 ¶ms, total_params, &data, total_data);
3279 END_PROFILE_NESTED(Trans2_qpathinfo);
3281 case TRANSACT2_SETPATHINFO:
3282 case TRANSACT2_SETFILEINFO:
3283 START_PROFILE_NESTED(Trans2_setpathinfo);
3284 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3285 ¶ms, total_params, &data, total_data);
3286 END_PROFILE_NESTED(Trans2_setpathinfo);
3289 case TRANSACT2_FINDNOTIFYFIRST:
3290 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3291 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
3292 ¶ms, total_params, &data, total_data);
3293 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3296 case TRANSACT2_FINDNOTIFYNEXT:
3297 START_PROFILE_NESTED(Trans2_findnotifynext);
3298 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
3299 ¶ms, total_params, &data, total_data);
3300 END_PROFILE_NESTED(Trans2_findnotifynext);
3302 case TRANSACT2_MKDIR:
3303 START_PROFILE_NESTED(Trans2_mkdir);
3304 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3305 ¶ms, total_params, &data, total_data);
3306 END_PROFILE_NESTED(Trans2_mkdir);
3309 case TRANSACT2_GET_DFS_REFERRAL:
3310 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3311 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3312 ¶ms, total_params, &data, total_data);
3313 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3315 case TRANSACT2_IOCTL:
3316 START_PROFILE_NESTED(Trans2_ioctl);
3317 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3318 ¶ms, total_params, &data, total_data);
3319 END_PROFILE_NESTED(Trans2_ioctl);
3322 /* Error in request */
3323 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3326 END_PROFILE(SMBtrans2);
3327 return ERROR_DOS(ERRSRV,ERRerror);
3330 /* As we do not know how many data packets will need to be
3331 returned here the various call_trans2xxxx calls
3332 must send their own. Thus a call_trans2xxx routine only
3333 returns a value other than -1 when it wants to send
3339 END_PROFILE(SMBtrans2);
3340 return outsize; /* If a correct response was needed the
3341 call_trans2xxx calls have already sent
3342 it. If outsize != -1 then it is returning */