2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2001
6 Extensively modified by Andrew Tridgell, 1995
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 extern BOOL case_sensitive;
27 extern int smb_read_error;
28 extern fstring local_machine;
29 extern int global_oplock_break;
30 extern uint32 global_client_caps;
31 extern pstring global_myname;
33 /****************************************************************************
34 Send the required number of replies back.
35 We assume all fields other than the data fields are
36 set correctly for the type of call.
37 HACK ! Always assumes smb_setup field is zero.
38 ****************************************************************************/
40 static int send_trans2_replies(char *outbuf,
47 /* As we are using a protocol > LANMAN1 then the max_send
48 variable must have been set in the sessetupX call.
49 This takes precedence over the max_xmit field in the
50 global struct. These different max_xmit variables should
51 be merged as this is now too confusing */
54 int data_to_send = datasize;
55 int params_to_send = paramsize;
59 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
60 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
61 int data_alignment_offset = 0;
63 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
65 set_message(outbuf,10,0,True);
67 /* If there genuinely are no parameters or data to send just send the empty packet */
69 if(params_to_send == 0 && data_to_send == 0) {
70 if (!send_smb(smbd_server_fd(),outbuf))
71 exit_server("send_trans2_replies: send_smb failed.");
75 /* When sending params and data ensure that both are nicely aligned */
76 /* Only do this alignment when there is also data to send - else
77 can cause NT redirector problems. */
79 if (((params_to_send % 4) != 0) && (data_to_send != 0))
80 data_alignment_offset = 4 - (params_to_send % 4);
82 /* Space is bufsize minus Netbios over TCP header minus SMB header */
83 /* The alignment_offset is to align the param bytes on an even byte
84 boundary. NT 4.0 Beta needs this to work correctly. */
86 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
88 /* useable_space can never be more than max_send minus the alignment offset. */
90 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
92 while (params_to_send || data_to_send) {
93 /* Calculate whether we will totally or partially fill this packet */
95 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
97 /* We can never send more than useable_space */
99 * Note that 'useable_space' does not include the alignment offsets,
100 * but we must include the alignment offsets in the calculation of
101 * the length of the data we send over the wire, as the alignment offsets
102 * are sent here. Fix from Marc_Jacobsen@hp.com.
105 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
107 set_message(outbuf, 10, total_sent_thistime, True);
109 /* Set total params and data to be sent */
110 SSVAL(outbuf,smb_tprcnt,paramsize);
111 SSVAL(outbuf,smb_tdrcnt,datasize);
113 /* Calculate how many parameters and data we can fit into
114 * this packet. Parameters get precedence
117 params_sent_thistime = MIN(params_to_send,useable_space);
118 data_sent_thistime = useable_space - params_sent_thistime;
119 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
121 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
123 /* smb_proff is the offset from the start of the SMB header to the
124 parameter bytes, however the first 4 bytes of outbuf are
125 the Netbios over TCP header. Thus use smb_base() to subtract
126 them from the calculation */
128 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
130 if(params_sent_thistime == 0)
131 SSVAL(outbuf,smb_prdisp,0);
133 /* Absolute displacement of param bytes sent in this packet */
134 SSVAL(outbuf,smb_prdisp,pp - params);
136 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
137 if(data_sent_thistime == 0) {
138 SSVAL(outbuf,smb_droff,0);
139 SSVAL(outbuf,smb_drdisp, 0);
141 /* The offset of the data bytes is the offset of the
142 parameter bytes plus the number of parameters being sent this time */
143 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
144 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
145 SSVAL(outbuf,smb_drdisp, pd - pdata);
148 /* Copy the param bytes into the packet */
150 if(params_sent_thistime)
151 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
153 /* Copy in the data bytes */
154 if(data_sent_thistime)
155 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
156 data_alignment_offset,pd,data_sent_thistime);
158 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
159 params_sent_thistime, data_sent_thistime, useable_space));
160 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
161 params_to_send, data_to_send, paramsize, datasize));
163 /* Send the packet */
164 if (!send_smb(smbd_server_fd(),outbuf))
165 exit_server("send_trans2_replies: send_smb failed.");
167 pp += params_sent_thistime;
168 pd += data_sent_thistime;
170 params_to_send -= params_sent_thistime;
171 data_to_send -= data_sent_thistime;
174 if(params_to_send < 0 || data_to_send < 0) {
175 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
176 params_to_send, data_to_send));
184 /****************************************************************************
185 Reply to a TRANSACT2_OPEN.
186 ****************************************************************************/
188 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
189 char **pparams, int total_params, char **ppdata, int total_data)
191 char *params = *pparams;
196 BOOL return_additional_info;
206 int fmode=0,mtime=0,rmode;
208 SMB_STRUCT_STAT sbuf;
210 BOOL bad_path = False;
214 * Ensure we have enough parameters to perform the operation.
217 if (total_params < 29)
218 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
220 open_mode = SVAL(params, 2);
221 open_attr = SVAL(params,6);
222 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
224 return_additional_info = BITSETW(params,0);
225 open_sattr = SVAL(params, 4);
226 open_time = make_unix_date3(params+8);
228 open_ofun = SVAL(params,12);
229 open_size = IVAL(params,14);
232 srvstr_pull(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE);
234 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
235 fname,open_mode, open_attr, open_ofun, open_size));
238 return(ERROR_DOS(ERRSRV,ERRaccess));
240 /* XXXX we need to handle passed times, sattr and flags */
242 unix_convert(fname,conn,0,&bad_path,&sbuf);
244 if (!check_name(fname,conn)) {
245 set_bad_path_error(errno, bad_path);
246 return(UNIXERROR(ERRDOS,ERRnoaccess));
249 unixmode = unix_mode(conn,open_attr | aARCH, fname);
251 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode,
252 oplock_request, &rmode,&smb_action);
255 set_bad_path_error(errno, bad_path);
256 return(UNIXERROR(ERRDOS,ERRnoaccess));
260 fmode = dos_mode(conn,fname,&sbuf);
261 mtime = sbuf.st_mtime;
264 close_file(fsp,False);
265 return(ERROR_DOS(ERRDOS,ERRnoaccess));
268 /* Realloc the size of parameters and data we will return */
269 params = Realloc(*pparams, 28);
271 return(ERROR_DOS(ERRDOS,ERRnomem));
274 memset((char *)params,'\0',28);
275 SSVAL(params,0,fsp->fnum);
276 SSVAL(params,2,fmode);
277 put_dos_date2(params,4, mtime);
278 SIVAL(params,8, (uint32)size);
279 SSVAL(params,12,rmode);
281 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
282 smb_action |= EXTENDED_OPLOCK_GRANTED;
284 SSVAL(params,18,smb_action);
287 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
289 SIVAL(params,20,inode);
291 /* Send the required number of replies */
292 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
297 /*********************************************************
298 Routine to check if a given string matches exactly.
299 as a special case a mask of "." does NOT match. That
300 is required for correct wildcard semantics
301 Case can be significant or not.
302 **********************************************************/
304 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
306 if (mask[0] == '.' && mask[1] == 0)
309 return strcmp(str,mask)==0;
310 return strcasecmp(str,mask) == 0;
313 /****************************************************************************
314 Return the filetype for UNIX extensions.
315 ****************************************************************************/
317 static uint32 unix_filetype(mode_t mode)
320 return UNIX_TYPE_FILE;
321 else if(S_ISDIR(mode))
322 return UNIX_TYPE_DIR;
324 else if(S_ISLNK(mode))
325 return UNIX_TYPE_SYMLINK;
328 else if(S_ISCHR(mode))
329 return UNIX_TYPE_CHARDEV;
332 else if(S_ISBLK(mode))
333 return UNIX_TYPE_BLKDEV;
336 else if(S_ISFIFO(mode))
337 return UNIX_TYPE_FIFO;
340 else if(S_ISSOCK(mode))
341 return UNIX_TYPE_SOCKET;
344 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
345 return UNIX_TYPE_UNKNOWN;
348 /****************************************************************************
349 Return the major devicenumber for UNIX extensions.
350 ****************************************************************************/
352 static uint32 unix_dev_major(SMB_DEV_T dev)
354 #if defined(HAVE_DEVICE_MAJOR_FN)
355 return (uint32)major(dev);
357 return (uint32)(dev >> 8);
361 /****************************************************************************
362 Return the minor devicenumber for UNIX extensions.
363 ****************************************************************************/
365 static uint32 unix_dev_minor(SMB_DEV_T dev)
367 #if defined(HAVE_DEVICE_MINOR_FN)
368 return (uint32)minor(dev);
370 return (uint32)(dev & 0xff);
374 /****************************************************************************
375 Map wire perms onto standard UNIX permissions. Obey share restrictions.
376 ****************************************************************************/
378 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
382 if (perms == SMB_MODE_NO_CHANGE)
385 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
386 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
387 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
388 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
389 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
390 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
391 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
392 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
393 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
395 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
398 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
401 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
404 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
405 ret &= lp_dir_mask(SNUM(conn));
406 /* Add in force bits */
407 ret |= lp_force_dir_mode(SNUM(conn));
409 /* Apply mode mask */
410 ret &= lp_create_mask(SNUM(conn));
411 /* Add in force bits */
412 ret |= lp_force_create_mode(SNUM(conn));
418 /****************************************************************************
419 checks for SMB_TIME_NO_CHANGE and if not found
420 calls interpret_long_date
421 ****************************************************************************/
422 time_t interpret_long_unix_date(char *p)
424 DEBUG(1,("interpret_long_unix_date\n"));
425 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
426 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
429 return interpret_long_date(p);
433 /****************************************************************************
434 Get a level dependent lanman2 dir entry.
435 ****************************************************************************/
437 static BOOL get_lanman2_dir_entry(connection_struct *conn,
438 void *inbuf, void *outbuf,
439 char *path_mask,int dirtype,int info_level,
440 int requires_resume_key,
441 BOOL dont_descend,char **ppdata,
442 char *base_data, int space_remaining,
443 BOOL *out_of_space, BOOL *got_exact_match,
448 SMB_STRUCT_STAT sbuf;
452 char *p, *q, *pdata = *ppdata;
457 SMB_OFF_T allocation_size = 0;
459 time_t mdate=0, adate=0, cdate=0;
462 int nt_extmode; /* Used for NT connections instead of mode */
463 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
466 *out_of_space = False;
467 *got_exact_match = False;
472 p = strrchr_m(path_mask,'/');
479 pstrcpy(mask, path_mask);
484 /* Needed if we run out of space */
485 prev_dirpos = TellDir(conn->dirptr);
486 dname = ReadDirName(conn->dirptr);
489 * Due to bugs in NT client redirectors we are not using
490 * resume keys any more - set them to zero.
491 * Check out the related comments in findfirst/findnext.
497 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
498 (long)conn->dirptr,TellDir(conn->dirptr)));
503 pstrcpy(fname,dname);
505 if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
506 got_match = mask_match(fname, mask, case_sensitive);
508 if(!got_match && !mangle_is_8_3(fname, False)) {
511 * It turns out that NT matches wildcards against
512 * both long *and* short names. This may explain some
513 * of the wildcard wierdness from old DOS clients
514 * that some people have been seeing.... JRA.
518 pstrcpy( newname, fname);
519 mangle_map( newname, True, False, SNUM(conn));
520 if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
521 got_match = mask_match(newname, mask, case_sensitive);
525 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
526 if (dont_descend && !isdots)
529 pstrcpy(pathreal,conn->dirpath);
531 pstrcat(pathreal,"/");
532 pstrcat(pathreal,dname);
534 if (INFO_LEVEL_IS_UNIX(info_level)) {
535 if (vfs_lstat(conn,pathreal,&sbuf) != 0) {
536 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
537 pathreal,strerror(errno)));
540 } else if (vfs_stat(conn,pathreal,&sbuf) != 0) {
542 /* Needed to show the msdfs symlinks as
545 if(lp_host_msdfs() &&
546 lp_msdfs_root(SNUM(conn)) &&
547 is_msdfs_link(conn, pathreal, NULL, NULL,
550 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
551 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
555 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
556 pathreal,strerror(errno)));
561 mode = dos_mode(conn,pathreal,&sbuf);
563 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
564 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
569 allocation_size = SMB_ROUNDUP_ALLOCATION(sbuf.st_size);
570 mdate = sbuf.st_mtime;
571 adate = sbuf.st_atime;
572 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
574 if (lp_dos_filetime_resolution(SNUM(conn))) {
583 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
589 mangle_map(fname,False,True,SNUM(conn));
594 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
596 switch (info_level) {
597 case SMB_INFO_STANDARD:
598 if(requires_resume_key) {
602 put_dos_date2(p,l1_fdateCreation,cdate);
603 put_dos_date2(p,l1_fdateLastAccess,adate);
604 put_dos_date2(p,l1_fdateLastWrite,mdate);
605 SIVAL(p,l1_cbFile,(uint32)size);
606 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
607 SSVAL(p,l1_attrFile,mode);
610 p += align_string(outbuf, p, 0);
611 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
612 SCVAL(nameptr, -1, len);
616 case SMB_INFO_QUERY_EA_SIZE:
617 if(requires_resume_key) {
621 put_dos_date2(p,l2_fdateCreation,cdate);
622 put_dos_date2(p,l2_fdateLastAccess,adate);
623 put_dos_date2(p,l2_fdateLastWrite,mdate);
624 SIVAL(p,l2_cbFile,(uint32)size);
625 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
626 SSVAL(p,l2_attrFile,mode);
627 SIVAL(p,l2_cbList,0); /* No extended attributes */
630 len = srvstr_push(outbuf, p, fname, -1, STR_NOALIGN);
633 *p++ = 0; /* craig from unisys pointed out we need this */
636 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
637 was_8_3 = mangle_is_8_3(fname, True);
639 SIVAL(p,0,reskey); p += 4;
640 put_long_date(p,cdate); p += 8;
641 put_long_date(p,adate); p += 8;
642 put_long_date(p,mdate); p += 8;
643 put_long_date(p,mdate); p += 8;
645 SOFF_T(p,8,allocation_size);
647 SIVAL(p,0,nt_extmode); p += 4;
649 SIVAL(p,0,0); p += 4;
651 pstring mangled_name;
652 pstrcpy(mangled_name, fname);
653 mangle_map(mangled_name,True,True,SNUM(conn));
654 mangled_name[12] = 0;
655 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER);
662 len = srvstr_push(outbuf, p, fname, -1, 0);
665 len = PTR_DIFF(p, pdata);
666 len = (len + 3) & ~3;
671 case SMB_FIND_FILE_DIRECTORY_INFO:
673 SIVAL(p,0,reskey); p += 4;
674 put_long_date(p,cdate); p += 8;
675 put_long_date(p,adate); p += 8;
676 put_long_date(p,mdate); p += 8;
677 put_long_date(p,mdate); p += 8;
679 SOFF_T(p,8,allocation_size);
681 SIVAL(p,0,nt_extmode); p += 4;
683 len = srvstr_push(outbuf, p, fname, -1, 0);
686 len = PTR_DIFF(p, pdata);
687 len = (len + 3) & ~3;
692 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
694 SIVAL(p,0,reskey); p += 4;
695 put_long_date(p,cdate); p += 8;
696 put_long_date(p,adate); p += 8;
697 put_long_date(p,mdate); p += 8;
698 put_long_date(p,mdate); p += 8;
700 SOFF_T(p,8,allocation_size);
702 SIVAL(p,0,nt_extmode); p += 4;
704 SIVAL(p,0,0); p += 4;
706 len = srvstr_push(outbuf, p, fname, -1, 0);
710 len = PTR_DIFF(p, pdata);
711 len = (len + 3) & ~3;
716 case SMB_FIND_FILE_NAMES_INFO:
718 SIVAL(p,0,reskey); p += 4;
720 /* this must *not* be null terminated or w2k gets in a loop trying to set an
721 acl on a dir (tridge) */
722 len = srvstr_push(outbuf, p, fname, -1, 0);
725 len = PTR_DIFF(p, pdata);
726 len = (len + 3) & ~3;
731 /* CIFS UNIX Extension. */
733 case SMB_FIND_FILE_UNIX:
735 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
737 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
738 SOFF_T(p,0,sbuf.st_size); /* File size 64 Bit */
741 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
742 SOFF_T(p,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */
744 /* Can't get the value - fake it using size. */
745 SOFF_T(p,0,sbuf.st_size); /* Number of bytes used on disk - 64 Bit */
749 put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */
750 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
751 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
754 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
758 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
762 SIVAL(p,0,unix_filetype(sbuf.st_mode));
765 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
769 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
773 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
776 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
780 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
784 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
787 len = PTR_DIFF(p, pdata);
788 len = (len + 3) & ~3;
789 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
791 /* End of SMB_QUERY_FILE_UNIX_BASIC */
800 if (PTR_DIFF(p,pdata) > space_remaining) {
801 /* Move the dirptr back to prev_dirpos */
802 SeekDir(conn->dirptr, prev_dirpos);
803 *out_of_space = True;
804 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
805 return False; /* Not finished - just out of space */
808 /* Setup the last_filename pointer, as an offset from base_data */
809 *last_name_off = PTR_DIFF(nameptr,base_data);
810 /* Advance the data pointer to the next slot */
816 /****************************************************************************
817 Reply to a TRANS2_FINDFIRST.
818 ****************************************************************************/
820 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
821 char **pparams, int total_params, char **ppdata, int total_data)
823 /* We must be careful here that we don't return more than the
824 allowed number of data bytes. If this means returning fewer than
825 maxentries then so be it. We assume that the redirector has
826 enough room for the fixed number of parameter bytes it has
828 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
829 char *params = *pparams;
830 char *pdata = *ppdata;
831 int dirtype = SVAL(params,0);
832 int maxentries = SVAL(params,2);
833 BOOL close_after_first = BITSETW(params+4,0);
834 BOOL close_if_end = BITSETW(params+4,1);
835 BOOL requires_resume_key = BITSETW(params+4,2);
836 int info_level = SVAL(params,6);
844 BOOL finished = False;
845 BOOL dont_descend = False;
846 BOOL out_of_space = False;
848 BOOL bad_path = False;
849 SMB_STRUCT_STAT sbuf;
851 if (total_params < 12)
852 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
854 *directory = *mask = 0;
856 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
857 close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
858 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
859 info_level, max_data_bytes));
861 switch (info_level) {
862 case SMB_INFO_STANDARD:
863 case SMB_INFO_QUERY_EA_SIZE:
864 case SMB_FIND_FILE_DIRECTORY_INFO:
865 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
866 case SMB_FIND_FILE_NAMES_INFO:
867 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
869 case SMB_FIND_FILE_UNIX:
870 if (!lp_unix_extensions())
871 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
874 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
877 srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE);
879 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
881 unix_convert(directory,conn,0,&bad_path,&sbuf);
882 if(!check_name(directory,conn)) {
883 set_bad_path_error(errno, bad_path);
884 return(UNIXERROR(ERRDOS,ERRbadpath));
887 p = strrchr_m(directory,'/');
889 pstrcpy(mask,directory);
890 pstrcpy(directory,"./");
896 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
898 pdata = Realloc(*ppdata, max_data_bytes + 1024);
900 return(ERROR_DOS(ERRDOS,ERRnomem));
903 memset((char *)pdata,'\0',max_data_bytes + 1024);
905 /* Realloc the params space */
906 params = Realloc(*pparams, 10);
908 return ERROR_DOS(ERRDOS,ERRnomem);
911 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
913 return(UNIXERROR(ERRDOS,ERRbadfile));
915 /* Save the wildcard match and attribs we are using on this directory -
916 needed as lanman2 assumes these are being saved between calls */
918 if(!(wcard = strdup(mask))) {
919 dptr_close(&dptr_num);
920 return ERROR_DOS(ERRDOS,ERRnomem);
923 dptr_set_wcard(dptr_num, wcard);
924 dptr_set_attr(dptr_num, dirtype);
926 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
928 /* We don't need to check for VOL here as this is returned by
929 a different TRANS2 call. */
931 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
932 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
936 space_remaining = max_data_bytes;
937 out_of_space = False;
939 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
940 BOOL got_exact_match = False;
942 /* this is a heuristic to avoid seeking the dirptr except when
943 absolutely necessary. It allows for a filename of about 40 chars */
944 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
948 finished = !get_lanman2_dir_entry(conn,
950 mask,dirtype,info_level,
951 requires_resume_key,dont_descend,
952 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
956 if (finished && out_of_space)
959 if (!finished && !out_of_space)
963 * As an optimisation if we know we aren't looking
964 * for a wildcard name (ie. the name matches the wildcard exactly)
965 * then we can finish on any (first) match.
966 * This speeds up large directory searches. JRA.
972 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
975 /* Check if we can close the dirptr */
976 if(close_after_first || (finished && close_if_end)) {
977 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
978 dptr_close(&dptr_num);
982 * If there are no matching entries we must return ERRDOS/ERRbadfile -
983 * from observation of NT.
986 if(numentries == 0) {
987 dptr_close(&dptr_num);
988 return ERROR_DOS(ERRDOS,ERRbadfile);
991 /* At this point pdata points to numentries directory entries. */
993 /* Set up the return parameter block */
994 SSVAL(params,0,dptr_num);
995 SSVAL(params,2,numentries);
996 SSVAL(params,4,finished);
997 SSVAL(params,6,0); /* Never an EA error */
998 SSVAL(params,8,last_name_off);
1000 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1002 if ((! *directory) && dptr_path(dptr_num))
1003 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1005 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1006 smb_fn_name(CVAL(inbuf,smb_com)),
1007 mask, directory, dirtype, numentries ) );
1010 * Force a name mangle here to ensure that the
1011 * mask as an 8.3 name is top of the mangled cache.
1012 * The reasons for this are subtle. Don't remove
1013 * this code unless you know what you are doing
1014 * (see PR#13758). JRA.
1017 if(!mangle_is_8_3_wildcards( mask, False))
1018 mangle_map(mask, True, True, SNUM(conn));
1023 /****************************************************************************
1024 Reply to a TRANS2_FINDNEXT.
1025 ****************************************************************************/
1027 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1028 char **pparams, int total_params, char **ppdata, int total_data)
1030 /* We must be careful here that we don't return more than the
1031 allowed number of data bytes. If this means returning fewer than
1032 maxentries then so be it. We assume that the redirector has
1033 enough room for the fixed number of parameter bytes it has
1035 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1036 char *params = *pparams;
1037 char *pdata = *ppdata;
1038 int dptr_num = SVAL(params,0);
1039 int maxentries = SVAL(params,2);
1040 uint16 info_level = SVAL(params,4);
1041 uint32 resume_key = IVAL(params,6);
1042 BOOL close_after_request = BITSETW(params+10,0);
1043 BOOL close_if_end = BITSETW(params+10,1);
1044 BOOL requires_resume_key = BITSETW(params+10,2);
1045 BOOL continue_bit = BITSETW(params+10,3);
1046 pstring resume_name;
1052 int i, last_name_off=0;
1053 BOOL finished = False;
1054 BOOL dont_descend = False;
1055 BOOL out_of_space = False;
1056 int space_remaining;
1058 if (total_params < 12)
1059 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1061 *mask = *directory = *resume_name = 0;
1063 srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE);
1065 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1066 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1067 resume_key = %d resume name = %s continue=%d level = %d\n",
1068 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1069 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1071 switch (info_level) {
1072 case SMB_INFO_STANDARD:
1073 case SMB_INFO_QUERY_EA_SIZE:
1074 case SMB_FIND_FILE_DIRECTORY_INFO:
1075 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1076 case SMB_FIND_FILE_NAMES_INFO:
1077 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1079 case SMB_FIND_FILE_UNIX:
1080 if (!lp_unix_extensions())
1081 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1084 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1087 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1089 return ERROR_DOS(ERRDOS,ERRnomem);
1092 memset((char *)pdata,'\0',max_data_bytes + 1024);
1094 /* Realloc the params space */
1095 params = Realloc(*pparams, 6*SIZEOFWORD);
1096 if( params == NULL )
1097 return ERROR_DOS(ERRDOS,ERRnomem);
1101 /* Check that the dptr is valid */
1102 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1103 return ERROR_DOS(ERRDOS,ERRnofiles);
1105 string_set(&conn->dirpath,dptr_path(dptr_num));
1107 /* Get the wildcard mask from the dptr */
1108 if((p = dptr_wcard(dptr_num))== NULL) {
1109 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1110 return ERROR_DOS(ERRDOS,ERRnofiles);
1114 pstrcpy(directory,conn->dirpath);
1116 /* Get the attr mask from the dptr */
1117 dirtype = dptr_attr(dptr_num);
1119 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1120 dptr_num, mask, dirtype,
1122 TellDir(conn->dirptr)));
1124 /* We don't need to check for VOL here as this is returned by
1125 a different TRANS2 call. */
1127 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1128 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1129 dont_descend = True;
1132 space_remaining = max_data_bytes;
1133 out_of_space = False;
1136 * Seek to the correct position. We no longer use the resume key but
1137 * depend on the last file name instead.
1140 if(requires_resume_key && *resume_name && !continue_bit) {
1143 * Fix for NT redirector problem triggered by resume key indexes
1144 * changing between directory scans. We now return a resume key of 0
1145 * and instead look for the filename to continue from (also given
1146 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1147 * findfirst/findnext (as is usual) then the directory pointer
1148 * should already be at the correct place. Check this by scanning
1149 * backwards looking for an exact (ie. case sensitive) filename match.
1150 * If we get to the beginning of the directory and haven't found it then scan
1151 * forwards again looking for a match. JRA.
1154 int current_pos, start_pos;
1156 void *dirptr = conn->dirptr;
1157 start_pos = TellDir(dirptr);
1158 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1159 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1161 SeekDir(dirptr, current_pos);
1162 dname = ReadDirName(dirptr);
1165 * Remember, mangle_map is called by
1166 * get_lanman2_dir_entry(), so the resume name
1167 * could be mangled. Ensure we do the same
1172 mangle_map( dname, False, True, SNUM(conn));
1174 if(dname && strcsequal( resume_name, dname)) {
1175 SeekDir(dirptr, current_pos+1);
1176 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1182 * Scan forward from start if not found going backwards.
1185 if(current_pos < 0) {
1186 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1187 SeekDir(dirptr, start_pos);
1188 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1191 * Remember, mangle_map is called by
1192 * get_lanman2_dir_entry(), so the resume name
1193 * could be mangled. Ensure we do the same
1198 mangle_map( dname, False, True, SNUM(conn));
1200 if(dname && strcsequal( resume_name, dname)) {
1201 SeekDir(dirptr, current_pos+1);
1202 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1206 } /* end if current_pos */
1207 } /* end if requires_resume_key && !continue_bit */
1209 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1210 BOOL got_exact_match = False;
1212 /* this is a heuristic to avoid seeking the dirptr except when
1213 absolutely necessary. It allows for a filename of about 40 chars */
1214 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1215 out_of_space = True;
1218 finished = !get_lanman2_dir_entry(conn,
1220 mask,dirtype,info_level,
1221 requires_resume_key,dont_descend,
1222 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1226 if (finished && out_of_space)
1229 if (!finished && !out_of_space)
1233 * As an optimisation if we know we aren't looking
1234 * for a wildcard name (ie. the name matches the wildcard exactly)
1235 * then we can finish on any (first) match.
1236 * This speeds up large directory searches. JRA.
1242 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1245 /* Check if we can close the dirptr */
1246 if(close_after_request || (finished && close_if_end)) {
1247 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1248 dptr_close(&dptr_num); /* This frees up the saved mask */
1252 /* Set up the return parameter block */
1253 SSVAL(params,0,numentries);
1254 SSVAL(params,2,finished);
1255 SSVAL(params,4,0); /* Never an EA error */
1256 SSVAL(params,6,last_name_off);
1258 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1260 if ((! *directory) && dptr_path(dptr_num))
1261 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1263 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1264 smb_fn_name(CVAL(inbuf,smb_com)),
1265 mask, directory, dirtype, numentries ) );
1270 /****************************************************************************
1271 Reply to a TRANS2_QFSINFO (query filesystem info).
1272 ****************************************************************************/
1274 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1275 int length, int bufsize,
1276 char **pparams, int total_params, char **ppdata, int total_data)
1278 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1279 char *pdata = *ppdata;
1280 char *params = *pparams;
1281 uint16 info_level = SVAL(params,0);
1284 char *vname = volume_label(SNUM(conn));
1285 int snum = SNUM(conn);
1286 char *fstype = lp_fstype(SNUM(conn));
1288 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1290 if(vfs_stat(conn,".",&st)!=0) {
1291 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1292 return ERROR_DOS(ERRSRV,ERRinvdevice);
1295 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1296 if ( pdata == NULL )
1297 return ERROR_DOS(ERRDOS,ERRnomem);
1300 memset((char *)pdata,'\0',max_data_bytes + 1024);
1302 switch (info_level) {
1303 case SMB_INFO_ALLOCATION:
1305 SMB_BIG_UINT dfree,dsize,bsize;
1307 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1308 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1309 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1310 SIVAL(pdata,l1_cUnit,dsize);
1311 SIVAL(pdata,l1_cUnitAvail,dfree);
1312 SSVAL(pdata,l1_cbSector,512);
1313 DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1314 (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1315 (unsigned int)dfree, 512));
1319 case SMB_INFO_VOLUME:
1320 /* Return volume name */
1322 * Add volume serial number - hash of a combination of
1323 * the called hostname and the service name.
1325 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1326 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_TERMINATE);
1327 SCVAL(pdata,l2_vol_cch,len);
1328 data_len = l2_vol_szVolLabel + len;
1329 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1330 (unsigned)st.st_ctime, len, vname));
1333 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1334 case SMB_FS_ATTRIBUTE_INFORMATION:
1336 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1337 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */
1338 SIVAL(pdata,4,255); /* Max filename component length */
1339 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1340 and will think we can't do long filenames */
1341 len = srvstr_push(outbuf, pdata+12, fstype, -1, 0);
1343 data_len = 12 + len;
1346 case SMB_QUERY_FS_LABEL_INFO:
1347 case SMB_FS_LABEL_INFORMATION:
1348 len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE);
1353 case SMB_QUERY_FS_VOLUME_INFO:
1354 case SMB_FS_VOLUME_INFORMATION:
1357 * Add volume serial number - hash of a combination of
1358 * the called hostname and the service name.
1360 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1361 (str_checksum(local_machine)<<16));
1363 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE);
1364 SIVAL(pdata,12,len);
1366 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1367 (int)strlen(vname),vname, lp_servicename(snum)));
1370 case SMB_QUERY_FS_SIZE_INFO:
1371 case SMB_FS_SIZE_INFORMATION:
1373 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1375 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1376 block_size = lp_block_size(snum);
1377 if (bsize < block_size) {
1378 SMB_BIG_UINT factor = block_size/bsize;
1383 if (bsize > block_size) {
1384 SMB_BIG_UINT factor = bsize/block_size;
1389 bytes_per_sector = 512;
1390 sectors_per_unit = bsize/bytes_per_sector;
1391 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1392 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1393 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1394 SBIG_UINT(pdata,0,dsize);
1395 SBIG_UINT(pdata,8,dfree);
1396 SIVAL(pdata,16,sectors_per_unit);
1397 SIVAL(pdata,20,bytes_per_sector);
1401 case SMB_FS_FULL_SIZE_INFORMATION:
1403 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1405 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1406 block_size = lp_block_size(snum);
1407 if (bsize < block_size) {
1408 SMB_BIG_UINT factor = block_size/bsize;
1413 if (bsize > block_size) {
1414 SMB_BIG_UINT factor = bsize/block_size;
1419 bytes_per_sector = 512;
1420 sectors_per_unit = bsize/bytes_per_sector;
1421 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1422 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1423 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1424 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1425 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1426 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1427 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1428 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1432 case SMB_QUERY_FS_DEVICE_INFO:
1433 case SMB_FS_DEVICE_INFORMATION:
1435 SIVAL(pdata,0,0); /* dev type */
1436 SIVAL(pdata,4,0); /* characteristics */
1439 case SMB_FS_OBJECTID_INFORMATION:
1444 * Query the version and capabilities of the CIFS UNIX extensions
1448 case SMB_QUERY_CIFS_UNIX_INFO:
1449 if (!lp_unix_extensions())
1450 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1452 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
1453 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
1454 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
1457 case SMB_MAC_QUERY_FS_INFO:
1459 * Thursby MAC extension... ONLY on NTFS filesystems
1460 * once we do streams then we don't need this
1462 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1464 SIVAL(pdata,84,0x100); /* Don't support mac... */
1469 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1473 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1475 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1480 /****************************************************************************
1481 Reply to a TRANS2_SETFSINFO (set filesystem info).
1482 ****************************************************************************/
1484 static int call_trans2setfsinfo(connection_struct *conn,
1485 char *inbuf, char *outbuf, int length, int bufsize,
1486 char **pparams, int total_params, char **ppdata, int total_data)
1488 /* Just say yes we did it - there is nothing that
1489 can be set here so it doesn't matter. */
1491 DEBUG(3,("call_trans2setfsinfo\n"));
1493 if (!CAN_WRITE(conn))
1494 return ERROR_DOS(ERRSRV,ERRaccess);
1496 outsize = set_message(outbuf,10,0,True);
1501 /****************************************************************************
1502 * Utility function to set bad path error.
1503 ****************************************************************************/
1505 NTSTATUS set_bad_path_error(int err, BOOL bad_path)
1507 if((err == ENOENT) && bad_path) {
1508 unix_ERR_class = ERRDOS;
1509 unix_ERR_code = ERRbadpath;
1510 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1512 return NT_STATUS_OK;
1515 /****************************************************************************
1516 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1517 file name or file id).
1518 ****************************************************************************/
1520 static int call_trans2qfilepathinfo(connection_struct *conn,
1521 char *inbuf, char *outbuf, int length,
1523 char **pparams, int total_params, char **ppdata, int total_data)
1525 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1526 char *params = *pparams;
1527 char *pdata = *ppdata;
1528 uint16 tran_call = SVAL(inbuf, smb_setup0);
1532 SMB_OFF_T allocation_size=0;
1533 unsigned int data_size;
1534 SMB_STRUCT_STAT sbuf;
1535 pstring fname, dos_fname;
1540 BOOL bad_path = False;
1541 BOOL delete_pending = False;
1546 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1548 if (tran_call == TRANSACT2_QFILEINFO) {
1549 files_struct *fsp = file_fsp(params,0);
1550 info_level = SVAL(params,2);
1552 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1554 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1556 * This is actually a QFILEINFO on a directory
1557 * handle (returned from an NT SMB). NT5.0 seems
1558 * to do this call. JRA.
1560 pstrcpy(fname, fsp->fsp_name);
1561 unix_convert(fname,conn,0,&bad_path,&sbuf);
1562 if (!check_name(fname,conn)) {
1563 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1564 set_bad_path_error(errno, bad_path);
1565 return(UNIXERROR(ERRDOS,ERRbadpath));
1568 if (INFO_LEVEL_IS_UNIX(info_level)) {
1569 /* Always do lstat for UNIX calls. */
1570 if (vfs_lstat(conn,fname,&sbuf)) {
1571 DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
1572 set_bad_path_error(errno, bad_path);
1573 return(UNIXERROR(ERRDOS,ERRbadpath));
1575 } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
1576 DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
1577 set_bad_path_error(errno, bad_path);
1578 return(UNIXERROR(ERRDOS,ERRbadpath));
1581 delete_pending = fsp->directory_delete_on_close;
1584 * Original code - this is an open file.
1586 CHECK_FSP(fsp,conn);
1588 pstrcpy(fname, fsp->fsp_name);
1589 if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) {
1590 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
1591 return(UNIXERROR(ERRDOS,ERRbadfid));
1593 if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1594 return(UNIXERROR(ERRDOS,ERRnoaccess));
1596 delete_pending = fsp->delete_on_close;
1600 if (total_params < 6)
1601 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1603 info_level = SVAL(params,0);
1605 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1607 srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE);
1609 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1611 unix_convert(fname,conn,0,&bad_path,&sbuf);
1612 if (!check_name(fname,conn)) {
1613 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1614 set_bad_path_error(errno, bad_path);
1615 return(UNIXERROR(ERRDOS,ERRbadpath));
1618 if (INFO_LEVEL_IS_UNIX(info_level)) {
1619 /* Always do lstat for UNIX calls. */
1620 if (vfs_lstat(conn,fname,&sbuf)) {
1621 DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
1622 set_bad_path_error(errno, bad_path);
1623 return(UNIXERROR(ERRDOS,ERRbadpath));
1625 } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
1626 DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
1627 set_bad_path_error(errno, bad_path);
1628 return(UNIXERROR(ERRDOS,ERRbadpath));
1632 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
1633 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1635 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1636 fname,info_level,tran_call,total_data));
1638 p = strrchr_m(fname,'/');
1644 mode = dos_mode(conn,fname,&sbuf);
1645 fullpathname = fname;
1646 size = sbuf.st_size;
1647 allocation_size = SMB_ROUNDUP_ALLOCATION(sbuf.st_size);
1651 params = Realloc(*pparams,2);
1653 return ERROR_DOS(ERRDOS,ERRnomem);
1655 memset((char *)params,'\0',2);
1656 data_size = max_data_bytes + 1024;
1657 pdata = Realloc(*ppdata, data_size);
1658 if ( pdata == NULL )
1659 return ERROR_DOS(ERRDOS,ERRnomem);
1662 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1663 /* uggh, EAs for OS2 */
1664 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1665 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1668 memset((char *)pdata,'\0',data_size);
1670 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1672 if (lp_dos_filetime_resolution(SNUM(conn))) {
1674 sbuf.st_atime &= ~1;
1675 sbuf.st_mtime &= ~1;
1676 sbuf.st_mtime &= ~1;
1679 /* NT expects the name to be in an exact form of the *full*
1680 filename. See the trans2 torture test */
1681 if (strequal(base_name,".")) {
1682 pstrcpy(dos_fname, "\\");
1684 snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname);
1685 string_replace(dos_fname, '/', '\\');
1688 switch (info_level) {
1689 case SMB_INFO_STANDARD:
1690 case SMB_INFO_QUERY_EA_SIZE:
1691 data_size = (info_level==1?22:26);
1692 put_dos_date2(pdata,l1_fdateCreation,c_time);
1693 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1694 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1695 SIVAL(pdata,l1_cbFile,(uint32)size);
1696 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
1697 SSVAL(pdata,l1_attrFile,mode);
1698 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1701 case SMB_INFO_QUERY_EAS_FROM_LIST:
1703 put_dos_date2(pdata,0,c_time);
1704 put_dos_date2(pdata,4,sbuf.st_atime);
1705 put_dos_date2(pdata,8,sbuf.st_mtime);
1706 SIVAL(pdata,12,(uint32)size);
1707 SIVAL(pdata,16,(uint32)allocation_size);
1708 SIVAL(pdata,20,mode);
1711 case SMB_INFO_QUERY_ALL_EAS:
1713 SIVAL(pdata,0,data_size);
1717 return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */
1719 case SMB_FILE_BASIC_INFORMATION:
1720 case SMB_QUERY_FILE_BASIC_INFO:
1722 if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1723 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1728 put_long_date(pdata,c_time);
1729 put_long_date(pdata+8,sbuf.st_atime);
1730 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1731 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1732 SIVAL(pdata,32,mode);
1734 DEBUG(5,("SMB_QFBI - "));
1736 time_t create_time = c_time;
1737 DEBUG(5,("create: %s ", ctime(&create_time)));
1739 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1740 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1741 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1742 DEBUG(5,("mode: %x\n", mode));
1746 case SMB_FILE_STANDARD_INFORMATION:
1747 case SMB_QUERY_FILE_STANDARD_INFO:
1750 /* Fake up allocation size. */
1751 SOFF_T(pdata,0,allocation_size);
1752 SOFF_T(pdata,8,size);
1753 SIVAL(pdata,16,sbuf.st_nlink);
1755 SCVAL(pdata,21,(mode&aDIR)?1:0);
1758 case SMB_FILE_EA_INFORMATION:
1759 case SMB_QUERY_FILE_EA_INFO:
1763 /* Get the 8.3 name - used if NT SMB was negotiated. */
1764 case SMB_QUERY_FILE_ALT_NAME_INFO:
1768 pstrcpy(short_name,base_name);
1769 /* Mangle if not already 8.3 */
1770 if(!mangle_is_8_3(short_name, True)) {
1771 mangle_map(short_name,True,True,SNUM(conn));
1773 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_TERMINATE|STR_UPPER);
1774 data_size = 4 + len;
1779 case SMB_QUERY_FILE_NAME_INFO:
1781 this must be *exactly* right for ACLs on mapped drives to work
1783 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
1784 data_size = 4 + len;
1788 case SMB_FILE_ALLOCATION_INFORMATION:
1789 case SMB_QUERY_FILE_ALLOCATION_INFO:
1791 SOFF_T(pdata,0,allocation_size);
1794 case SMB_FILE_END_OF_FILE_INFORMATION:
1795 case SMB_QUERY_FILE_END_OF_FILEINFO:
1797 SOFF_T(pdata,0,size);
1800 case SMB_QUERY_FILE_ALL_INFO:
1801 put_long_date(pdata,c_time);
1802 put_long_date(pdata+8,sbuf.st_atime);
1803 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1804 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1805 SIVAL(pdata,32,mode);
1807 SOFF_T(pdata,0,allocation_size);
1808 SOFF_T(pdata,8,size);
1809 SIVAL(pdata,16,sbuf.st_nlink);
1810 SCVAL(pdata,20,delete_pending);
1811 SCVAL(pdata,21,(mode&aDIR)?1:0);
1813 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);
1814 pdata += 8; /* index number */
1815 pdata += 4; /* EA info */
1817 SIVAL(pdata,0,0xA9);
1819 SIVAL(pdata,0,0xd01BF);
1821 SOFF_T(pdata,0,pos); /* current offset */
1823 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1825 pdata += 4; /* alignment */
1826 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_TERMINATE);
1829 data_size = PTR_DIFF(pdata,(*ppdata));
1832 case SMB_FILE_INTERNAL_INFORMATION:
1833 /* This should be an index number - looks like dev/ino to me :-) */
1834 SIVAL(pdata,0,sbuf.st_dev);
1835 SIVAL(pdata,4,sbuf.st_ino);
1839 case SMB_FILE_ACCESS_INFORMATION:
1840 SIVAL(pdata,0,0x12019F); /* ??? */
1844 case SMB_FILE_NAME_INFORMATION:
1845 /* Pathname with leading '\'. */
1848 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
1849 SIVAL(pdata,0,byte_len);
1850 data_size = 4 + byte_len;
1854 case SMB_FILE_DISPOSITION_INFORMATION:
1856 SCVAL(pdata,0,delete_pending);
1859 case SMB_FILE_POSITION_INFORMATION:
1861 SOFF_T(pdata,0,pos);
1864 case SMB_FILE_MODE_INFORMATION:
1865 SIVAL(pdata,0,mode);
1869 case SMB_FILE_ALIGNMENT_INFORMATION:
1870 SIVAL(pdata,0,0); /* No alignment needed. */
1875 /* Not yet finished... JRA */
1878 put_long_date(pdata,c_time);
1879 put_long_date(pdata+8,sbuf.st_atime);
1880 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1881 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1882 SIVAL(pdata,32,mode);
1883 SIVAL(pdata,36,0); /* ??? */
1884 SIVAL(pdata,40,0x20); /* ??? */
1885 SIVAL(pdata,44,0); /* ??? */
1886 SOFF_T(pdata,48,size);
1887 SIVAL(pdata,56,0x1); /* ??? */
1888 SIVAL(pdata,60,0); /* ??? */
1889 SIVAL(pdata,64,0); /* ??? */
1890 SIVAL(pdata,68,length); /* Following string length in bytes. */
1891 dos_PutUniCode(pdata+72,,False);
1896 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
1897 /* Last component of pathname. */
1899 size_t byte_len = dos_PutUniCode(pdata+4,fname,max_data_bytes,False);
1900 SIVAL(pdata,0,byte_len);
1901 data_size = 4 + byte_len;
1907 * NT4 server just returns "invalid query" to this - if we try to answer
1908 * it then NTws gets a BSOD! (tridge).
1909 * W2K seems to want this. JRA.
1911 case SMB_QUERY_FILE_STREAM_INFO:
1913 case SMB_FILE_STREAM_INFORMATION:
1917 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
1918 SIVAL(pdata,0,0); /* ??? */
1919 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
1920 SOFF_T(pdata,8,size);
1921 SIVAL(pdata,16,allocation_size);
1922 SIVAL(pdata,20,0); /* ??? */
1923 data_size = 24 + byte_len;
1927 case SMB_FILE_COMPRESSION_INFORMATION:
1928 SOFF_T(pdata,0,size);
1929 SIVAL(pdata,8,0); /* ??? */
1930 SIVAL(pdata,12,0); /* ??? */
1934 case SMB_FILE_NETWORK_OPEN_INFORMATION:
1935 put_long_date(pdata,c_time);
1936 put_long_date(pdata+8,sbuf.st_atime);
1937 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1938 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1939 SIVAL(pdata,32,allocation_size);
1940 SOFF_T(pdata,40,size);
1941 SIVAL(pdata,48,mode);
1942 SIVAL(pdata,52,0); /* ??? */
1946 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
1947 SIVAL(pdata,0,mode);
1953 * CIFS UNIX Extensions.
1956 case SMB_QUERY_FILE_UNIX_BASIC:
1958 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
1960 SOFF_T(pdata,0,sbuf.st_size); /* File size 64 Bit */
1963 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1964 SOFF_T(pdata,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */
1966 /* Can't get the value - fake it using size. */
1967 SOFF_T(pdata,0,sbuf.st_size); /* Number of bytes used on disk - 64 Bit */
1971 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
1972 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
1973 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1976 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
1980 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
1984 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
1987 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1991 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1995 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1998 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2002 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2005 data_size = PTR_DIFF(pdata,(*ppdata));
2009 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2011 for (i=0; i<100; i++)
2012 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2018 case SMB_QUERY_FILE_UNIX_LINK:
2023 if(!S_ISLNK(sbuf.st_mode))
2024 return(UNIXERROR(ERRSRV,ERRbadlink));
2026 return(UNIXERROR(ERRDOS,ERRbadlink));
2028 len = conn->vfs_ops.readlink(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2030 return(UNIXERROR(ERRDOS,ERRnoaccess));
2032 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2034 data_size = PTR_DIFF(pdata,(*ppdata));
2040 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2043 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size);
2048 /****************************************************************************
2049 Deal with the internal needs of setting the delete on close flag. Note that
2050 as the tdb locking is recursive, it is safe to call this from within
2051 open_file_shared. JRA.
2052 ****************************************************************************/
2054 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2057 * Only allow delete on close for writable shares.
2060 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2061 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2063 return NT_STATUS_ACCESS_DENIED;
2066 * Only allow delete on close for files/directories opened with delete intent.
2069 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2070 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2072 return NT_STATUS_ACCESS_DENIED;
2075 if(fsp->is_directory) {
2076 fsp->directory_delete_on_close = delete_on_close;
2077 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2078 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2081 files_struct *iterate_fsp;
2084 * Modify the share mode entry for all files open
2085 * on this device and inode to tell other smbds we have
2086 * changed the delete on close flag. This will be noticed
2087 * in the close code, the last closer will delete the file
2091 DEBUG(10,("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2092 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2094 if (lock_share_entry_fsp(fsp) == False)
2095 return NT_STATUS_ACCESS_DENIED;
2097 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2098 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2100 unlock_share_entry_fsp(fsp);
2101 return NT_STATUS_ACCESS_DENIED;
2108 unlock_share_entry_fsp(fsp);
2111 * Go through all files we have open on the same device and
2112 * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
2113 * Other smbd's that have this file open will look in the share_mode on close.
2114 * take care of this (rare) case in close_file(). See the comment there.
2115 * NB. JRA. We don't really need to do this anymore - all should be taken
2116 * care of in the share_mode changes in the tdb.
2119 for(iterate_fsp = file_find_di_first(fsp->dev, fsp->inode);
2120 iterate_fsp; iterate_fsp = file_find_di_next(iterate_fsp))
2121 fsp->delete_on_close = delete_on_close;
2124 * Set the delete on close flag in the fsp.
2126 fsp->delete_on_close = delete_on_close;
2128 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2129 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2133 return NT_STATUS_OK;
2136 /****************************************************************************
2137 Returns true if this pathname is within the share, and thus safe.
2138 ****************************************************************************/
2140 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2143 char resolved_name[PATH_MAX+1];
2145 pstring resolved_name;
2147 fstring last_component;
2151 BOOL bad_path = False;
2152 SMB_STRUCT_STAT sbuf;
2154 pstrcpy(link_dest, link_dest_in);
2155 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2157 /* Store the UNIX converted path. */
2158 pstrcpy(link_dest_out, link_dest);
2160 p = strrchr(link_dest, '/');
2162 fstrcpy(last_component, p+1);
2165 fstrcpy(last_component, link_dest);
2166 pstrcpy(link_dest, "./");
2169 if (conn->vfs_ops.realpath(conn,link_dest,resolved_name) == NULL)
2172 pstrcpy(link_dest, resolved_name);
2173 pstrcat(link_dest, "/");
2174 pstrcat(link_dest, last_component);
2176 if (*link_dest != '/') {
2177 /* Relative path. */
2178 pstrcpy(link_test, conn->connectpath);
2179 pstrcat(link_test, "/");
2180 pstrcat(link_test, link_dest);
2182 pstrcpy(link_test, link_dest);
2186 * Check if the link is within the share.
2189 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2196 /****************************************************************************
2197 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2198 ****************************************************************************/
2200 static int call_trans2setfilepathinfo(connection_struct *conn,
2201 char *inbuf, char *outbuf, int length, int bufsize,
2202 char **pparams, int total_params, char **ppdata, int total_data)
2204 char *params = *pparams;
2205 char *pdata = *ppdata;
2206 uint16 tran_call = SVAL(inbuf, smb_setup0);
2211 SMB_STRUCT_STAT sbuf;
2214 BOOL bad_path = False;
2215 files_struct *fsp = NULL;
2216 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2217 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2218 mode_t unixmode = 0;
2220 if (tran_call == TRANSACT2_SETFILEINFO) {
2221 fsp = file_fsp(params,0);
2222 info_level = SVAL(params,2);
2224 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2226 * This is actually a SETFILEINFO on a directory
2227 * handle (returned from an NT SMB). NT5.0 seems
2228 * to do this call. JRA.
2230 pstrcpy(fname, fsp->fsp_name);
2231 unix_convert(fname,conn,0,&bad_path,&sbuf);
2232 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2233 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2234 set_bad_path_error(errno, bad_path);
2235 return(UNIXERROR(ERRDOS,ERRbadpath));
2237 } else if (fsp && fsp->print_file) {
2239 * Doing a DELETE_ON_CLOSE should cancel a print job.
2241 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
2242 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2244 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
2247 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2252 * Original code - this is an open file.
2254 CHECK_FSP(fsp,conn);
2256 pstrcpy(fname, fsp->fsp_name);
2259 if (vfs_fstat(fsp,fd,&sbuf) != 0) {
2260 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2261 return(UNIXERROR(ERRDOS,ERRbadfid));
2266 if (total_params < 6)
2267 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2269 info_level = SVAL(params,0);
2270 srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE);
2271 unix_convert(fname,conn,0,&bad_path,&sbuf);
2272 if(!check_name(fname, conn)) {
2273 set_bad_path_error(errno, bad_path);
2274 return(UNIXERROR(ERRDOS,ERRbadpath));
2278 * For CIFS UNIX extensions the target name may not exist.
2281 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2282 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
2283 set_bad_path_error(errno, bad_path);
2284 return(UNIXERROR(ERRDOS,ERRbadpath));
2288 if (!CAN_WRITE(conn))
2289 return ERROR_DOS(ERRSRV,ERRaccess);
2291 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2292 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2294 if (VALID_STAT(sbuf))
2295 unixmode = sbuf.st_mode;
2297 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
2298 tran_call,fname,info_level,total_data));
2300 /* Realloc the parameter and data sizes */
2301 params = Realloc(*pparams,2);
2303 return ERROR_DOS(ERRDOS,ERRnomem);
2309 /* the pending modtime overrides the current modtime */
2310 sbuf.st_mtime = fsp->pending_modtime;
2313 size = sbuf.st_size;
2314 tvs.modtime = sbuf.st_mtime;
2315 tvs.actime = sbuf.st_atime;
2316 dosmode = dos_mode(conn,fname,&sbuf);
2317 unixmode = sbuf.st_mode;
2319 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2320 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2322 switch (info_level) {
2323 case SMB_INFO_STANDARD:
2324 case SMB_INFO_QUERY_EA_SIZE:
2326 if (total_data < l1_cbFile+4)
2327 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2330 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2333 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2335 dosmode = SVAL(pdata,l1_attrFile);
2336 size = IVAL(pdata,l1_cbFile);
2341 /* XXXX um, i don't think this is right.
2342 it's also not in the cifs6.txt spec.
2344 case SMB_INFO_QUERY_EAS_FROM_LIST:
2345 if (total_data < 28)
2346 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2348 tvs.actime = make_unix_date2(pdata+8);
2349 tvs.modtime = make_unix_date2(pdata+12);
2350 size = IVAL(pdata,16);
2351 dosmode = IVAL(pdata,24);
2354 /* XXXX nor this. not in cifs6.txt, either. */
2355 case SMB_INFO_QUERY_ALL_EAS:
2356 if (total_data < 28)
2357 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2359 tvs.actime = make_unix_date2(pdata+8);
2360 tvs.modtime = make_unix_date2(pdata+12);
2361 size = IVAL(pdata,16);
2362 dosmode = IVAL(pdata,24);
2365 case SMB_SET_FILE_BASIC_INFO:
2366 case SMB_FILE_BASIC_INFORMATION:
2368 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2370 time_t changed_time;
2372 if (total_data < 36)
2373 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2375 /* Ignore create time at offset pdata. */
2378 tvs.actime = interpret_long_date(pdata+8);
2380 write_time = interpret_long_date(pdata+16);
2381 changed_time = interpret_long_date(pdata+24);
2383 tvs.modtime = MIN(write_time, changed_time);
2385 if (write_time > tvs.modtime && write_time != 0xffffffff) {
2386 tvs.modtime = write_time;
2388 /* Prefer a defined time to an undefined one. */
2389 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2390 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2391 ? changed_time : write_time);
2394 dosmode = IVAL(pdata,32);
2398 case SMB_FILE_ALLOCATION_INFORMATION:
2399 case SMB_SET_FILE_ALLOCATION_INFO:
2402 SMB_OFF_T allocation_size = IVAL(pdata,0);
2405 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2407 #ifdef LARGE_SMB_OFF_T
2408 allocation_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2409 #else /* LARGE_SMB_OFF_T */
2410 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2411 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2412 #endif /* LARGE_SMB_OFF_T */
2413 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2414 fname, (double)allocation_size ));
2416 if(allocation_size != sbuf.st_size) {
2417 SMB_STRUCT_STAT new_sbuf;
2419 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2420 fname, (double)allocation_size ));
2423 files_struct *new_fsp = NULL;
2424 int access_mode = 0;
2427 if(global_oplock_break) {
2428 /* Queue this file modify as we are the process of an oplock break. */
2430 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2431 DEBUGADD(2,( "in oplock break state.\n"));
2433 push_oplock_pending_smb_message(inbuf, length);
2437 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2438 SET_OPEN_MODE(DOS_OPEN_RDWR),
2439 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2440 0, 0, &access_mode, &action);
2442 if (new_fsp == NULL)
2443 return(UNIXERROR(ERRDOS,ERRbadpath));
2444 ret = vfs_allocate_file_space(new_fsp, allocation_size);
2445 if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2446 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2447 new_fsp->fnum, strerror(errno)));
2450 close_file(new_fsp,True);
2452 ret = vfs_allocate_file_space(fsp, allocation_size);
2453 if (vfs_fstat(fsp,fd,&new_sbuf) != 0) {
2454 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2455 fsp->fnum, strerror(errno)));
2460 return ERROR_NT(NT_STATUS_DISK_FULL);
2462 /* Allocate can trucate size... */
2463 size = new_sbuf.st_size;
2469 case SMB_FILE_END_OF_FILE_INFORMATION:
2470 case SMB_SET_FILE_END_OF_FILE_INFO:
2473 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2475 size = IVAL(pdata,0);
2476 #ifdef LARGE_SMB_OFF_T
2477 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2478 #else /* LARGE_SMB_OFF_T */
2479 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2480 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2481 #endif /* LARGE_SMB_OFF_T */
2482 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2486 case SMB_FILE_DISPOSITION_INFORMATION:
2487 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2489 BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
2493 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2495 if (tran_call != TRANSACT2_SETFILEINFO)
2496 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2499 return(UNIXERROR(ERRDOS,ERRbadfid));
2501 status = set_delete_on_close_internal(fsp, delete_on_close);
2503 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2504 return ERROR_NT(status);
2510 * CIFS UNIX extensions.
2513 case SMB_SET_FILE_UNIX_BASIC:
2515 uint32 raw_unixmode;
2517 if (total_data < 100)
2518 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2520 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
2521 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
2522 size=IVAL(pdata,0); /* first 8 Bytes are size */
2523 #ifdef LARGE_SMB_OFF_T
2524 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2525 #else /* LARGE_SMB_OFF_T */
2526 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2527 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2528 #endif /* LARGE_SMB_OFF_T */
2530 pdata+=24; /* ctime & st_blocks are not changed */
2531 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
2532 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
2534 set_owner = (uid_t)IVAL(pdata,0);
2536 set_grp = (gid_t)IVAL(pdata,0);
2538 raw_unixmode = IVAL(pdata,28);
2539 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2540 dosmode = 0; /* Ensure dos mode change doesn't override this. */
2542 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2543 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2544 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2546 if (!VALID_STAT(sbuf)) {
2549 * The only valid use of this is to create character and block
2550 * devices, and named pipes. This is deprecated (IMHO) and
2551 * a new info level should be used for mknod. JRA.
2554 #if !defined(HAVE_MAKEDEV_FN)
2555 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2556 #else /* HAVE_MAKEDEV_FN */
2557 uint32 file_type = IVAL(pdata,0);
2558 uint32 dev_major = IVAL(pdata,4);
2559 uint32 dev_minor = IVAL(pdata,12);
2561 uid_t myuid = geteuid();
2562 gid_t mygid = getegid();
2565 if (tran_call == TRANSACT2_SETFILEINFO)
2566 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2568 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2569 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2571 dev = makedev(dev_major, dev_minor);
2573 /* We can only create as the owner/group we are. */
2575 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2576 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2577 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2578 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2580 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2581 file_type != UNIX_TYPE_FIFO)
2582 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2584 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2585 0%o for file %s\n", (double)dev, unixmode, fname ));
2587 /* Ok - do the mknod. */
2588 if (conn->vfs_ops.mknod(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
2589 return(UNIXERROR(ERRDOS,ERRnoaccess));
2592 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2594 #endif /* HAVE_MAKEDEV_FN */
2599 * Deal with the UNIX specific mode set.
2602 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
2603 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2604 (unsigned int)unixmode, fname ));
2605 if (vfs_chmod(conn,fname,unixmode) != 0)
2606 return(UNIXERROR(ERRDOS,ERRnoaccess));
2610 * Deal with the UNIX specific uid set.
2613 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
2614 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2615 (unsigned int)set_owner, fname ));
2616 if (vfs_chown(conn,fname,set_owner, (gid_t)-1) != 0)
2617 return(UNIXERROR(ERRDOS,ERRnoaccess));
2621 * Deal with the UNIX specific gid set.
2624 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
2625 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2626 (unsigned int)set_owner, fname ));
2627 if (vfs_chown(conn,fname,(uid_t)-1, set_grp) != 0)
2628 return(UNIXERROR(ERRDOS,ERRnoaccess));
2633 case SMB_SET_FILE_UNIX_LINK:
2636 /* Set a symbolic link. */
2637 /* Don't allow this if follow links is false. */
2639 if (!lp_symlinks(SNUM(conn)))
2640 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2642 /* Disallow if already exists. */
2643 if (VALID_STAT(sbuf))
2644 return(ERROR_DOS(ERRDOS,ERRbadpath));
2646 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2648 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2649 return(UNIXERROR(ERRDOS,ERRnoaccess));
2651 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2652 fname, link_dest ));
2654 if (conn->vfs_ops.symlink(conn,link_dest,fname) != 0)
2655 return(UNIXERROR(ERRDOS,ERRnoaccess));
2657 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2661 case SMB_SET_FILE_UNIX_HLINK:
2665 /* Set a hard link. */
2667 /* Disallow if already exists. */
2668 if (VALID_STAT(sbuf))
2669 return(ERROR_DOS(ERRDOS,ERRbadpath));
2671 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2673 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2674 return(UNIXERROR(ERRDOS,ERRnoaccess));
2676 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2677 fname, link_dest ));
2679 if (conn->vfs_ops.link(conn,link_dest,fname) != 0)
2680 return(UNIXERROR(ERRDOS,ERRnoaccess));
2682 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2687 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2690 /* get some defaults (no modifications) if any info is zero or -1. */
2691 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2692 tvs.actime = sbuf.st_atime;
2694 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2695 tvs.modtime = sbuf.st_mtime;
2697 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2698 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2699 DEBUG(6,("size: %.0f ", (double)size));
2701 if (S_ISDIR(sbuf.st_mode))
2706 DEBUG(6,("dosmode: %x\n" , dosmode));
2708 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2709 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2710 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2711 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2714 * Only do this test if we are not explicitly
2715 * changing the size of a file.
2718 size = sbuf.st_size;
2722 * Try and set the times, size and mode of this file -
2723 * if they are different from the current values
2725 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2728 * This was a setfileinfo on an open file.
2729 * NT does this a lot. It's actually pointless
2730 * setting the time here, as it will be overwritten
2731 * on the next write, so we save the request
2732 * away and will set it on file close. JRA.
2735 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2736 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
2737 fsp->pending_modtime = tvs.modtime;
2742 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2744 if(file_utime(conn, fname, &tvs)!=0)
2745 return(UNIXERROR(ERRDOS,ERRnoaccess));
2749 /* check the mode isn't different, before changing it */
2750 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
2752 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
2754 if(file_chmod(conn, fname, dosmode, NULL)) {
2755 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2756 return(UNIXERROR(ERRDOS,ERRnoaccess));
2760 if(size != sbuf.st_size) {
2764 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2765 fname, (double)size ));
2768 files_struct *new_fsp = NULL;
2769 int access_mode = 0;
2772 if(global_oplock_break) {
2773 /* Queue this file modify as we are the process of an oplock break. */
2775 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2776 DEBUGADD(2,( "in oplock break state.\n"));
2778 push_oplock_pending_smb_message(inbuf, length);
2782 new_fsp = open_file_shared(conn, fname, &sbuf,
2783 SET_OPEN_MODE(DOS_OPEN_RDWR),
2784 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2785 0, 0, &access_mode, &action);
2787 if (new_fsp == NULL)
2788 return(UNIXERROR(ERRDOS,ERRbadpath));
2789 ret = vfs_set_filelen(new_fsp, size);
2790 close_file(new_fsp,True);
2792 ret = vfs_set_filelen(fsp, size);
2796 return (UNIXERROR(ERRHRD,ERRdiskfull));
2800 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2805 /****************************************************************************
2806 Reply to a TRANS2_MKDIR (make directory with extended attributes).
2807 ****************************************************************************/
2809 static int call_trans2mkdir(connection_struct *conn,
2810 char *inbuf, char *outbuf, int length, int bufsize,
2811 char **pparams, int total_params, char **ppdata, int total_data)
2813 char *params = *pparams;
2816 SMB_STRUCT_STAT sbuf;
2817 BOOL bad_path = False;
2819 if (!CAN_WRITE(conn))
2820 return ERROR_DOS(ERRSRV,ERRaccess);
2822 if (total_params < 4)
2823 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2825 srvstr_pull(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE);
2827 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
2829 unix_convert(directory,conn,0,&bad_path,&sbuf);
2830 if (check_name(directory,conn))
2831 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2834 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
2835 set_bad_path_error(errno, bad_path);
2836 return(UNIXERROR(ERRDOS,ERRnoaccess));
2839 /* Realloc the parameter and data sizes */
2840 params = Realloc(*pparams,2);
2842 return ERROR_DOS(ERRDOS,ERRnomem);
2847 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2852 /****************************************************************************
2853 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
2854 We don't actually do this - we just send a null response.
2855 ****************************************************************************/
2857 static int call_trans2findnotifyfirst(connection_struct *conn,
2858 char *inbuf, char *outbuf, int length, int bufsize,
2859 char **pparams, int total_params, char **ppdata, int total_data)
2861 static uint16 fnf_handle = 257;
2862 char *params = *pparams;
2865 if (total_params < 6)
2866 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2868 info_level = SVAL(params,4);
2869 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
2871 switch (info_level) {
2876 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2879 /* Realloc the parameter and data sizes */
2880 params = Realloc(*pparams,6);
2882 return ERROR_DOS(ERRDOS,ERRnomem);
2885 SSVAL(params,0,fnf_handle);
2886 SSVAL(params,2,0); /* No changes */
2887 SSVAL(params,4,0); /* No EA errors */
2894 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
2899 /****************************************************************************
2900 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
2901 changes). Currently this does nothing.
2902 ****************************************************************************/
2904 static int call_trans2findnotifynext(connection_struct *conn,
2905 char *inbuf, char *outbuf, int length, int bufsize,
2906 char **pparams, int total_params, char **ppdata, int total_data)
2908 char *params = *pparams;
2910 DEBUG(3,("call_trans2findnotifynext\n"));
2912 /* Realloc the parameter and data sizes */
2913 params = Realloc(*pparams,4);
2915 return ERROR_DOS(ERRDOS,ERRnomem);
2918 SSVAL(params,0,0); /* No changes */
2919 SSVAL(params,2,0); /* No EA errors */
2921 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2926 /****************************************************************************
2927 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
2928 ****************************************************************************/
2930 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
2931 char* outbuf, int length, int bufsize,
2932 char **pparams, int total_params, char **ppdata, int total_data)
2934 char *params = *pparams;
2937 int max_referral_level;
2939 DEBUG(10,("call_trans2getdfsreferral\n"));
2941 if (total_params < 2)
2942 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2944 max_referral_level = SVAL(params,0);
2946 if(!lp_host_msdfs())
2947 return ERROR_DOS(ERRDOS,ERRbadfunc);
2949 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
2951 if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
2952 return ERROR_DOS(ERRDOS,ERRbadfile);
2954 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
2955 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
2960 #define LMCAT_SPL 0x53
2961 #define LMFUNC_GETJOBID 0x60
2963 /****************************************************************************
2964 Reply to a TRANS2_IOCTL - used for OS/2 printing.
2965 ****************************************************************************/
2967 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
2968 char* outbuf, int length, int bufsize,
2969 char **pparams, int total_params, char **ppdata, int total_data)
2971 char *pdata = *ppdata;
2972 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
2974 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
2975 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
2976 pdata = Realloc(*ppdata, 32);
2978 return ERROR_DOS(ERRDOS,ERRnomem);
2981 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
2982 CAN ACCEPT THIS IN UNICODE. JRA. */
2984 SSVAL(pdata,0,fsp->print_jobid); /* Job number */
2985 srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
2986 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
2987 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
2990 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
2991 return ERROR_DOS(ERRSRV,ERRerror);
2995 /****************************************************************************
2996 Reply to a SMBfindclose (stop trans2 directory search).
2997 ****************************************************************************/
2999 int reply_findclose(connection_struct *conn,
3000 char *inbuf,char *outbuf,int length,int bufsize)
3003 int dptr_num=SVALS(inbuf,smb_vwv0);
3004 START_PROFILE(SMBfindclose);
3006 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3008 dptr_close(&dptr_num);
3010 outsize = set_message(outbuf,0,0,True);
3012 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3014 END_PROFILE(SMBfindclose);
3018 /****************************************************************************
3019 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3020 ****************************************************************************/
3022 int reply_findnclose(connection_struct *conn,
3023 char *inbuf,char *outbuf,int length,int bufsize)
3027 START_PROFILE(SMBfindnclose);
3029 dptr_num = SVAL(inbuf,smb_vwv0);
3031 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3033 /* We never give out valid handles for a
3034 findnotifyfirst - so any dptr_num is ok here.
3037 outsize = set_message(outbuf,0,0,True);
3039 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3041 END_PROFILE(SMBfindnclose);
3045 /****************************************************************************
3046 Reply to a SMBtranss2 - just ignore it!
3047 ****************************************************************************/
3049 int reply_transs2(connection_struct *conn,
3050 char *inbuf,char *outbuf,int length,int bufsize)
3052 START_PROFILE(SMBtranss2);
3053 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3054 END_PROFILE(SMBtranss2);
3058 /****************************************************************************
3059 Reply to a SMBtrans2.
3060 ****************************************************************************/
3062 int reply_trans2(connection_struct *conn,
3063 char *inbuf,char *outbuf,int length,int bufsize)
3066 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3067 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3069 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3070 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3071 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3072 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3073 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3074 int32 timeout = IVALS(inbuf,smb_timeout);
3076 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3077 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3078 char *params = NULL, *data = NULL;
3079 int num_params, num_params_sofar, num_data, num_data_sofar;
3080 START_PROFILE(SMBtrans2);
3082 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3083 /* Queue this open message as we are the process of an
3086 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3087 DEBUGADD(2,( "in oplock break state.\n"));
3089 push_oplock_pending_smb_message(inbuf, length);
3090 END_PROFILE(SMBtrans2);
3094 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3095 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3096 END_PROFILE(SMBtrans2);
3097 return ERROR_DOS(ERRSRV,ERRaccess);
3100 outsize = set_message(outbuf,0,0,True);
3102 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3103 is so as a sanity check */
3106 * Need to have rc=0 for ioctl to get job id for OS/2.
3107 * Network printing will fail if function is not successful.
3108 * Similar function in reply.c will be used if protocol
3109 * is LANMAN1.0 instead of LM1.2X002.
3110 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3111 * outbuf doesn't have to be set(only job id is used).
3113 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3114 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3115 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3116 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3118 DEBUG(2,("Invalid smb_sucnt in trans2 call(%d)\n",suwcnt));
3119 DEBUG(2,("Transaction is %d\n",tran_call));
3120 END_PROFILE(SMBtrans2);
3121 return ERROR_DOS(ERRSRV,ERRerror);
3125 /* Allocate the space for the maximum needed parameters and data */
3126 if (total_params > 0)
3127 params = (char *)malloc(total_params);
3129 data = (char *)malloc(total_data);
3131 if ((total_params && !params) || (total_data && !data)) {
3132 DEBUG(2,("Out of memory in reply_trans2\n"));
3135 END_PROFILE(SMBtrans2);
3136 return ERROR_DOS(ERRDOS,ERRnomem);
3139 /* Copy the param and data bytes sent with this request into
3140 the params buffer */
3141 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3142 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3144 if (num_params > total_params || num_data > total_data)
3145 exit_server("invalid params in reply_trans2");
3148 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
3150 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
3152 if(num_data_sofar < total_data || num_params_sofar < total_params) {
3153 /* We need to send an interim response then receive the rest
3154 of the parameter/data bytes */
3155 outsize = set_message(outbuf,0,0,True);
3156 if (!send_smb(smbd_server_fd(),outbuf))
3157 exit_server("reply_trans2: send_smb failed.");
3159 while (num_data_sofar < total_data ||
3160 num_params_sofar < total_params) {
3163 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3166 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3167 outsize = set_message(outbuf,0,0,True);
3169 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3171 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3172 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3175 END_PROFILE(SMBtrans2);
3176 return ERROR_DOS(ERRSRV,ERRerror);
3179 /* Revise total_params and total_data in case
3180 they have changed downwards */
3181 total_params = SVAL(inbuf, smb_tpscnt);
3182 total_data = SVAL(inbuf, smb_tdscnt);
3183 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
3184 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
3185 if (num_params_sofar > total_params || num_data_sofar > total_data)
3186 exit_server("data overflow in trans2");
3188 memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)],
3189 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
3190 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
3191 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
3195 if (Protocol >= PROTOCOL_NT1) {
3196 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
3199 /* Now we must call the relevant TRANS2 function */
3201 case TRANSACT2_OPEN:
3202 START_PROFILE_NESTED(Trans2_open);
3203 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
3204 ¶ms, total_params, &data, total_data);
3205 END_PROFILE_NESTED(Trans2_open);
3208 case TRANSACT2_FINDFIRST:
3209 START_PROFILE_NESTED(Trans2_findfirst);
3210 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3211 ¶ms, total_params, &data, total_data);
3212 END_PROFILE_NESTED(Trans2_findfirst);
3215 case TRANSACT2_FINDNEXT:
3216 START_PROFILE_NESTED(Trans2_findnext);
3217 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
3218 ¶ms, total_params, &data, total_data);
3219 END_PROFILE_NESTED(Trans2_findnext);
3222 case TRANSACT2_QFSINFO:
3223 START_PROFILE_NESTED(Trans2_qfsinfo);
3224 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3225 ¶ms, total_params, &data, total_data);
3226 END_PROFILE_NESTED(Trans2_qfsinfo);
3229 case TRANSACT2_SETFSINFO:
3230 START_PROFILE_NESTED(Trans2_setfsinfo);
3231 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
3232 ¶ms, total_params, &data, total_data);
3233 END_PROFILE_NESTED(Trans2_setfsinfo);
3236 case TRANSACT2_QPATHINFO:
3237 case TRANSACT2_QFILEINFO:
3238 START_PROFILE_NESTED(Trans2_qpathinfo);
3239 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3240 ¶ms, total_params, &data, total_data);
3241 END_PROFILE_NESTED(Trans2_qpathinfo);
3243 case TRANSACT2_SETPATHINFO:
3244 case TRANSACT2_SETFILEINFO:
3245 START_PROFILE_NESTED(Trans2_setpathinfo);
3246 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3247 ¶ms, total_params, &data, total_data);
3248 END_PROFILE_NESTED(Trans2_setpathinfo);
3251 case TRANSACT2_FINDNOTIFYFIRST:
3252 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3253 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
3254 ¶ms, total_params, &data, total_data);
3255 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3258 case TRANSACT2_FINDNOTIFYNEXT:
3259 START_PROFILE_NESTED(Trans2_findnotifynext);
3260 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
3261 ¶ms, total_params, &data, total_data);
3262 END_PROFILE_NESTED(Trans2_findnotifynext);
3264 case TRANSACT2_MKDIR:
3265 START_PROFILE_NESTED(Trans2_mkdir);
3266 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3267 ¶ms, total_params, &data, total_data);
3268 END_PROFILE_NESTED(Trans2_mkdir);
3271 case TRANSACT2_GET_DFS_REFERRAL:
3272 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3273 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3274 ¶ms, total_params, &data, total_data);
3275 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3277 case TRANSACT2_IOCTL:
3278 START_PROFILE_NESTED(Trans2_ioctl);
3279 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3280 ¶ms, total_params, &data, total_data);
3281 END_PROFILE_NESTED(Trans2_ioctl);
3284 /* Error in request */
3285 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3288 END_PROFILE(SMBtrans2);
3289 return ERROR_DOS(ERRSRV,ERRerror);
3292 /* As we do not know how many data packets will need to be
3293 returned here the various call_trans2xxxx calls
3294 must send their own. Thus a call_trans2xxx routine only
3295 returns a value other than -1 when it wants to send
3301 END_PROFILE(SMBtrans2);
3302 return outsize; /* If a correct response was needed the
3303 call_trans2xxx calls have already sent
3304 it. If outsize != -1 then it is returning */