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);
2250 return (UNIXERROR(ERRDOS,ERRbadpath));
2253 * Original code - this is an open file.
2255 CHECK_FSP(fsp,conn);
2257 pstrcpy(fname, fsp->fsp_name);
2260 if (vfs_fstat(fsp,fd,&sbuf) != 0) {
2261 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2262 return(UNIXERROR(ERRDOS,ERRbadfid));
2267 if (total_params < 6)
2268 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2270 info_level = SVAL(params,0);
2271 srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE);
2272 unix_convert(fname,conn,0,&bad_path,&sbuf);
2273 if(!check_name(fname, conn)) {
2274 set_bad_path_error(errno, bad_path);
2275 return(UNIXERROR(ERRDOS,ERRbadpath));
2279 * For CIFS UNIX extensions the target name may not exist.
2282 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2283 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
2284 set_bad_path_error(errno, bad_path);
2285 return(UNIXERROR(ERRDOS,ERRbadpath));
2289 if (!CAN_WRITE(conn))
2290 return ERROR_DOS(ERRSRV,ERRaccess);
2292 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2293 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2295 if (VALID_STAT(sbuf))
2296 unixmode = sbuf.st_mode;
2298 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
2299 tran_call,fname,info_level,total_data));
2301 /* Realloc the parameter and data sizes */
2302 params = Realloc(*pparams,2);
2304 return ERROR_DOS(ERRDOS,ERRnomem);
2310 /* the pending modtime overrides the current modtime */
2311 sbuf.st_mtime = fsp->pending_modtime;
2314 size = sbuf.st_size;
2315 tvs.modtime = sbuf.st_mtime;
2316 tvs.actime = sbuf.st_atime;
2317 dosmode = dos_mode(conn,fname,&sbuf);
2318 unixmode = sbuf.st_mode;
2320 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2321 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2323 switch (info_level) {
2324 case SMB_INFO_STANDARD:
2325 case SMB_INFO_QUERY_EA_SIZE:
2327 if (total_data < l1_cbFile+4)
2328 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2331 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2334 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2336 dosmode = SVAL(pdata,l1_attrFile);
2337 size = IVAL(pdata,l1_cbFile);
2342 /* XXXX um, i don't think this is right.
2343 it's also not in the cifs6.txt spec.
2345 case SMB_INFO_QUERY_EAS_FROM_LIST:
2346 if (total_data < 28)
2347 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2349 tvs.actime = make_unix_date2(pdata+8);
2350 tvs.modtime = make_unix_date2(pdata+12);
2351 size = IVAL(pdata,16);
2352 dosmode = IVAL(pdata,24);
2355 /* XXXX nor this. not in cifs6.txt, either. */
2356 case SMB_INFO_QUERY_ALL_EAS:
2357 if (total_data < 28)
2358 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2360 tvs.actime = make_unix_date2(pdata+8);
2361 tvs.modtime = make_unix_date2(pdata+12);
2362 size = IVAL(pdata,16);
2363 dosmode = IVAL(pdata,24);
2366 case SMB_SET_FILE_BASIC_INFO:
2367 case SMB_FILE_BASIC_INFORMATION:
2369 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2371 time_t changed_time;
2373 if (total_data < 36)
2374 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2376 /* Ignore create time at offset pdata. */
2379 tvs.actime = interpret_long_date(pdata+8);
2381 write_time = interpret_long_date(pdata+16);
2382 changed_time = interpret_long_date(pdata+24);
2384 tvs.modtime = MIN(write_time, changed_time);
2386 if (write_time > tvs.modtime && write_time != 0xffffffff) {
2387 tvs.modtime = write_time;
2389 /* Prefer a defined time to an undefined one. */
2390 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2391 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2392 ? changed_time : write_time);
2395 dosmode = IVAL(pdata,32);
2399 case SMB_FILE_ALLOCATION_INFORMATION:
2400 case SMB_SET_FILE_ALLOCATION_INFO:
2403 SMB_OFF_T allocation_size = IVAL(pdata,0);
2406 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2408 #ifdef LARGE_SMB_OFF_T
2409 allocation_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2410 #else /* LARGE_SMB_OFF_T */
2411 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2412 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2413 #endif /* LARGE_SMB_OFF_T */
2414 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2415 fname, (double)allocation_size ));
2417 if(allocation_size != sbuf.st_size) {
2418 SMB_STRUCT_STAT new_sbuf;
2420 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2421 fname, (double)allocation_size ));
2424 files_struct *new_fsp = NULL;
2425 int access_mode = 0;
2428 if(global_oplock_break) {
2429 /* Queue this file modify as we are the process of an oplock break. */
2431 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2432 DEBUGADD(2,( "in oplock break state.\n"));
2434 push_oplock_pending_smb_message(inbuf, length);
2438 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2439 SET_OPEN_MODE(DOS_OPEN_RDWR),
2440 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2441 0, 0, &access_mode, &action);
2443 if (new_fsp == NULL)
2444 return(UNIXERROR(ERRDOS,ERRbadpath));
2445 ret = vfs_allocate_file_space(new_fsp, allocation_size);
2446 if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2447 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2448 new_fsp->fnum, strerror(errno)));
2451 close_file(new_fsp,True);
2453 ret = vfs_allocate_file_space(fsp, allocation_size);
2454 if (vfs_fstat(fsp,fd,&new_sbuf) != 0) {
2455 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2456 fsp->fnum, strerror(errno)));
2461 return ERROR_NT(NT_STATUS_DISK_FULL);
2463 /* Allocate can trucate size... */
2464 size = new_sbuf.st_size;
2470 case SMB_FILE_END_OF_FILE_INFORMATION:
2471 case SMB_SET_FILE_END_OF_FILE_INFO:
2474 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2476 size = IVAL(pdata,0);
2477 #ifdef LARGE_SMB_OFF_T
2478 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2479 #else /* LARGE_SMB_OFF_T */
2480 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2481 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2482 #endif /* LARGE_SMB_OFF_T */
2483 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2487 case SMB_FILE_DISPOSITION_INFORMATION:
2488 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2490 BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
2494 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2496 if (tran_call != TRANSACT2_SETFILEINFO)
2497 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2500 return(UNIXERROR(ERRDOS,ERRbadfid));
2502 status = set_delete_on_close_internal(fsp, delete_on_close);
2504 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2505 return ERROR_NT(status);
2511 * CIFS UNIX extensions.
2514 case SMB_SET_FILE_UNIX_BASIC:
2516 uint32 raw_unixmode;
2518 if (total_data < 100)
2519 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2521 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
2522 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
2523 size=IVAL(pdata,0); /* first 8 Bytes are size */
2524 #ifdef LARGE_SMB_OFF_T
2525 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2526 #else /* LARGE_SMB_OFF_T */
2527 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2528 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2529 #endif /* LARGE_SMB_OFF_T */
2531 pdata+=24; /* ctime & st_blocks are not changed */
2532 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
2533 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
2535 set_owner = (uid_t)IVAL(pdata,0);
2537 set_grp = (gid_t)IVAL(pdata,0);
2539 raw_unixmode = IVAL(pdata,28);
2540 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2541 dosmode = 0; /* Ensure dos mode change doesn't override this. */
2543 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2544 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2545 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2547 if (!VALID_STAT(sbuf)) {
2550 * The only valid use of this is to create character and block
2551 * devices, and named pipes. This is deprecated (IMHO) and
2552 * a new info level should be used for mknod. JRA.
2555 #if !defined(HAVE_MAKEDEV_FN)
2556 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2557 #else /* HAVE_MAKEDEV_FN */
2558 uint32 file_type = IVAL(pdata,0);
2559 uint32 dev_major = IVAL(pdata,4);
2560 uint32 dev_minor = IVAL(pdata,12);
2562 uid_t myuid = geteuid();
2563 gid_t mygid = getegid();
2566 if (tran_call == TRANSACT2_SETFILEINFO)
2567 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2569 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2570 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2572 dev = makedev(dev_major, dev_minor);
2574 /* We can only create as the owner/group we are. */
2576 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2577 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2578 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2579 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2581 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2582 file_type != UNIX_TYPE_FIFO)
2583 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2585 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2586 0%o for file %s\n", (double)dev, unixmode, fname ));
2588 /* Ok - do the mknod. */
2589 if (conn->vfs_ops.mknod(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
2590 return(UNIXERROR(ERRDOS,ERRnoaccess));
2593 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2595 #endif /* HAVE_MAKEDEV_FN */
2600 * Deal with the UNIX specific mode set.
2603 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
2604 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2605 (unsigned int)unixmode, fname ));
2606 if (vfs_chmod(conn,fname,unixmode) != 0)
2607 return(UNIXERROR(ERRDOS,ERRnoaccess));
2611 * Deal with the UNIX specific uid set.
2614 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
2615 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2616 (unsigned int)set_owner, fname ));
2617 if (vfs_chown(conn,fname,set_owner, (gid_t)-1) != 0)
2618 return(UNIXERROR(ERRDOS,ERRnoaccess));
2622 * Deal with the UNIX specific gid set.
2625 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
2626 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2627 (unsigned int)set_owner, fname ));
2628 if (vfs_chown(conn,fname,(uid_t)-1, set_grp) != 0)
2629 return(UNIXERROR(ERRDOS,ERRnoaccess));
2634 case SMB_SET_FILE_UNIX_LINK:
2637 /* Set a symbolic link. */
2638 /* Don't allow this if follow links is false. */
2640 if (!lp_symlinks(SNUM(conn)))
2641 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2643 /* Disallow if already exists. */
2644 if (VALID_STAT(sbuf))
2645 return(ERROR_DOS(ERRDOS,ERRbadpath));
2647 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2649 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2650 return(UNIXERROR(ERRDOS,ERRnoaccess));
2652 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2653 fname, link_dest ));
2655 if (conn->vfs_ops.symlink(conn,link_dest,fname) != 0)
2656 return(UNIXERROR(ERRDOS,ERRnoaccess));
2658 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2662 case SMB_SET_FILE_UNIX_HLINK:
2666 /* Set a hard link. */
2668 /* Disallow if already exists. */
2669 if (VALID_STAT(sbuf))
2670 return(ERROR_DOS(ERRDOS,ERRbadpath));
2672 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2674 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2675 return(UNIXERROR(ERRDOS,ERRnoaccess));
2677 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2678 fname, link_dest ));
2680 if (conn->vfs_ops.link(conn,link_dest,fname) != 0)
2681 return(UNIXERROR(ERRDOS,ERRnoaccess));
2683 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2688 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2691 /* get some defaults (no modifications) if any info is zero or -1. */
2692 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2693 tvs.actime = sbuf.st_atime;
2695 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2696 tvs.modtime = sbuf.st_mtime;
2698 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2699 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2700 DEBUG(6,("size: %.0f ", (double)size));
2702 if (S_ISDIR(sbuf.st_mode))
2707 DEBUG(6,("dosmode: %x\n" , dosmode));
2709 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2710 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2711 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2712 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2715 * Only do this test if we are not explicitly
2716 * changing the size of a file.
2719 size = sbuf.st_size;
2723 * Try and set the times, size and mode of this file -
2724 * if they are different from the current values
2726 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2729 * This was a setfileinfo on an open file.
2730 * NT does this a lot. It's actually pointless
2731 * setting the time here, as it will be overwritten
2732 * on the next write, so we save the request
2733 * away and will set it on file close. JRA.
2736 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2737 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
2738 fsp->pending_modtime = tvs.modtime;
2743 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2745 if(file_utime(conn, fname, &tvs)!=0)
2746 return(UNIXERROR(ERRDOS,ERRnoaccess));
2750 /* check the mode isn't different, before changing it */
2751 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
2753 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
2755 if(file_chmod(conn, fname, dosmode, NULL)) {
2756 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2757 return(UNIXERROR(ERRDOS,ERRnoaccess));
2761 if(size != sbuf.st_size) {
2765 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2766 fname, (double)size ));
2769 files_struct *new_fsp = NULL;
2770 int access_mode = 0;
2773 if(global_oplock_break) {
2774 /* Queue this file modify as we are the process of an oplock break. */
2776 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2777 DEBUGADD(2,( "in oplock break state.\n"));
2779 push_oplock_pending_smb_message(inbuf, length);
2783 new_fsp = open_file_shared(conn, fname, &sbuf,
2784 SET_OPEN_MODE(DOS_OPEN_RDWR),
2785 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2786 0, 0, &access_mode, &action);
2788 if (new_fsp == NULL)
2789 return(UNIXERROR(ERRDOS,ERRbadpath));
2790 ret = vfs_set_filelen(new_fsp, size);
2791 close_file(new_fsp,True);
2793 ret = vfs_set_filelen(fsp, size);
2797 return (UNIXERROR(ERRHRD,ERRdiskfull));
2801 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2806 /****************************************************************************
2807 Reply to a TRANS2_MKDIR (make directory with extended attributes).
2808 ****************************************************************************/
2810 static int call_trans2mkdir(connection_struct *conn,
2811 char *inbuf, char *outbuf, int length, int bufsize,
2812 char **pparams, int total_params, char **ppdata, int total_data)
2814 char *params = *pparams;
2817 SMB_STRUCT_STAT sbuf;
2818 BOOL bad_path = False;
2820 if (!CAN_WRITE(conn))
2821 return ERROR_DOS(ERRSRV,ERRaccess);
2823 if (total_params < 4)
2824 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2826 srvstr_pull(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE);
2828 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
2830 unix_convert(directory,conn,0,&bad_path,&sbuf);
2831 if (check_name(directory,conn))
2832 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2835 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
2836 set_bad_path_error(errno, bad_path);
2837 return(UNIXERROR(ERRDOS,ERRnoaccess));
2840 /* Realloc the parameter and data sizes */
2841 params = Realloc(*pparams,2);
2843 return ERROR_DOS(ERRDOS,ERRnomem);
2848 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2853 /****************************************************************************
2854 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
2855 We don't actually do this - we just send a null response.
2856 ****************************************************************************/
2858 static int call_trans2findnotifyfirst(connection_struct *conn,
2859 char *inbuf, char *outbuf, int length, int bufsize,
2860 char **pparams, int total_params, char **ppdata, int total_data)
2862 static uint16 fnf_handle = 257;
2863 char *params = *pparams;
2866 if (total_params < 6)
2867 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2869 info_level = SVAL(params,4);
2870 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
2872 switch (info_level) {
2877 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2880 /* Realloc the parameter and data sizes */
2881 params = Realloc(*pparams,6);
2883 return ERROR_DOS(ERRDOS,ERRnomem);
2886 SSVAL(params,0,fnf_handle);
2887 SSVAL(params,2,0); /* No changes */
2888 SSVAL(params,4,0); /* No EA errors */
2895 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
2900 /****************************************************************************
2901 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
2902 changes). Currently this does nothing.
2903 ****************************************************************************/
2905 static int call_trans2findnotifynext(connection_struct *conn,
2906 char *inbuf, char *outbuf, int length, int bufsize,
2907 char **pparams, int total_params, char **ppdata, int total_data)
2909 char *params = *pparams;
2911 DEBUG(3,("call_trans2findnotifynext\n"));
2913 /* Realloc the parameter and data sizes */
2914 params = Realloc(*pparams,4);
2916 return ERROR_DOS(ERRDOS,ERRnomem);
2919 SSVAL(params,0,0); /* No changes */
2920 SSVAL(params,2,0); /* No EA errors */
2922 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2927 /****************************************************************************
2928 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
2929 ****************************************************************************/
2931 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
2932 char* outbuf, int length, int bufsize,
2933 char **pparams, int total_params, char **ppdata, int total_data)
2935 char *params = *pparams;
2938 int max_referral_level;
2940 DEBUG(10,("call_trans2getdfsreferral\n"));
2942 if (total_params < 2)
2943 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2945 max_referral_level = SVAL(params,0);
2947 if(!lp_host_msdfs())
2948 return ERROR_DOS(ERRDOS,ERRbadfunc);
2950 srvstr_pull(inbuf, pathname, ¶ms[2], sizeof(pathname), -1, STR_TERMINATE);
2952 if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
2953 return ERROR_DOS(ERRDOS,ERRbadfile);
2955 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
2956 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
2961 #define LMCAT_SPL 0x53
2962 #define LMFUNC_GETJOBID 0x60
2964 /****************************************************************************
2965 Reply to a TRANS2_IOCTL - used for OS/2 printing.
2966 ****************************************************************************/
2968 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
2969 char* outbuf, int length, int bufsize,
2970 char **pparams, int total_params, char **ppdata, int total_data)
2972 char *pdata = *ppdata;
2973 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
2975 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
2976 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
2979 pdata = Realloc(*ppdata, 32);
2981 return ERROR_DOS(ERRDOS,ERRnomem);
2984 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
2985 CAN ACCEPT THIS IN UNICODE. JRA. */
2987 rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid); /* Job number */
2988 SSVAL(pdata,0,rap_jobid); /* Job number */
2989 srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
2990 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
2991 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
2994 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
2995 return ERROR_DOS(ERRSRV,ERRerror);
2999 /****************************************************************************
3000 Reply to a SMBfindclose (stop trans2 directory search).
3001 ****************************************************************************/
3003 int reply_findclose(connection_struct *conn,
3004 char *inbuf,char *outbuf,int length,int bufsize)
3007 int dptr_num=SVALS(inbuf,smb_vwv0);
3008 START_PROFILE(SMBfindclose);
3010 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3012 dptr_close(&dptr_num);
3014 outsize = set_message(outbuf,0,0,True);
3016 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3018 END_PROFILE(SMBfindclose);
3022 /****************************************************************************
3023 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3024 ****************************************************************************/
3026 int reply_findnclose(connection_struct *conn,
3027 char *inbuf,char *outbuf,int length,int bufsize)
3031 START_PROFILE(SMBfindnclose);
3033 dptr_num = SVAL(inbuf,smb_vwv0);
3035 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3037 /* We never give out valid handles for a
3038 findnotifyfirst - so any dptr_num is ok here.
3041 outsize = set_message(outbuf,0,0,True);
3043 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3045 END_PROFILE(SMBfindnclose);
3049 /****************************************************************************
3050 Reply to a SMBtranss2 - just ignore it!
3051 ****************************************************************************/
3053 int reply_transs2(connection_struct *conn,
3054 char *inbuf,char *outbuf,int length,int bufsize)
3056 START_PROFILE(SMBtranss2);
3057 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3058 END_PROFILE(SMBtranss2);
3062 /****************************************************************************
3063 Reply to a SMBtrans2.
3064 ****************************************************************************/
3066 int reply_trans2(connection_struct *conn,
3067 char *inbuf,char *outbuf,int length,int bufsize)
3070 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3071 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3073 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3074 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3075 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3076 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3077 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3078 int32 timeout = IVALS(inbuf,smb_timeout);
3080 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3081 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3082 char *params = NULL, *data = NULL;
3083 int num_params, num_params_sofar, num_data, num_data_sofar;
3084 START_PROFILE(SMBtrans2);
3086 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3087 /* Queue this open message as we are the process of an
3090 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3091 DEBUGADD(2,( "in oplock break state.\n"));
3093 push_oplock_pending_smb_message(inbuf, length);
3094 END_PROFILE(SMBtrans2);
3098 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3099 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3100 END_PROFILE(SMBtrans2);
3101 return ERROR_DOS(ERRSRV,ERRaccess);
3104 outsize = set_message(outbuf,0,0,True);
3106 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3107 is so as a sanity check */
3110 * Need to have rc=0 for ioctl to get job id for OS/2.
3111 * Network printing will fail if function is not successful.
3112 * Similar function in reply.c will be used if protocol
3113 * is LANMAN1.0 instead of LM1.2X002.
3114 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3115 * outbuf doesn't have to be set(only job id is used).
3117 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3118 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3119 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3120 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3122 DEBUG(2,("Invalid smb_sucnt in trans2 call(%d)\n",suwcnt));
3123 DEBUG(2,("Transaction is %d\n",tran_call));
3124 END_PROFILE(SMBtrans2);
3125 return ERROR_DOS(ERRSRV,ERRerror);
3129 /* Allocate the space for the maximum needed parameters and data */
3130 if (total_params > 0)
3131 params = (char *)malloc(total_params);
3133 data = (char *)malloc(total_data);
3135 if ((total_params && !params) || (total_data && !data)) {
3136 DEBUG(2,("Out of memory in reply_trans2\n"));
3139 END_PROFILE(SMBtrans2);
3140 return ERROR_DOS(ERRDOS,ERRnomem);
3143 /* Copy the param and data bytes sent with this request into
3144 the params buffer */
3145 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3146 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3148 if (num_params > total_params || num_data > total_data)
3149 exit_server("invalid params in reply_trans2");
3152 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
3154 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
3156 if(num_data_sofar < total_data || num_params_sofar < total_params) {
3157 /* We need to send an interim response then receive the rest
3158 of the parameter/data bytes */
3159 outsize = set_message(outbuf,0,0,True);
3160 if (!send_smb(smbd_server_fd(),outbuf))
3161 exit_server("reply_trans2: send_smb failed.");
3163 while (num_data_sofar < total_data ||
3164 num_params_sofar < total_params) {
3167 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3170 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3171 outsize = set_message(outbuf,0,0,True);
3173 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3175 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3176 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3179 END_PROFILE(SMBtrans2);
3180 return ERROR_DOS(ERRSRV,ERRerror);
3183 /* Revise total_params and total_data in case
3184 they have changed downwards */
3185 total_params = SVAL(inbuf, smb_tpscnt);
3186 total_data = SVAL(inbuf, smb_tdscnt);
3187 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
3188 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
3189 if (num_params_sofar > total_params || num_data_sofar > total_data)
3190 exit_server("data overflow in trans2");
3192 memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)],
3193 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
3194 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
3195 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
3199 if (Protocol >= PROTOCOL_NT1) {
3200 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
3203 /* Now we must call the relevant TRANS2 function */
3205 case TRANSACT2_OPEN:
3206 START_PROFILE_NESTED(Trans2_open);
3207 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
3208 ¶ms, total_params, &data, total_data);
3209 END_PROFILE_NESTED(Trans2_open);
3212 case TRANSACT2_FINDFIRST:
3213 START_PROFILE_NESTED(Trans2_findfirst);
3214 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3215 ¶ms, total_params, &data, total_data);
3216 END_PROFILE_NESTED(Trans2_findfirst);
3219 case TRANSACT2_FINDNEXT:
3220 START_PROFILE_NESTED(Trans2_findnext);
3221 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
3222 ¶ms, total_params, &data, total_data);
3223 END_PROFILE_NESTED(Trans2_findnext);
3226 case TRANSACT2_QFSINFO:
3227 START_PROFILE_NESTED(Trans2_qfsinfo);
3228 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3229 ¶ms, total_params, &data, total_data);
3230 END_PROFILE_NESTED(Trans2_qfsinfo);
3233 case TRANSACT2_SETFSINFO:
3234 START_PROFILE_NESTED(Trans2_setfsinfo);
3235 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
3236 ¶ms, total_params, &data, total_data);
3237 END_PROFILE_NESTED(Trans2_setfsinfo);
3240 case TRANSACT2_QPATHINFO:
3241 case TRANSACT2_QFILEINFO:
3242 START_PROFILE_NESTED(Trans2_qpathinfo);
3243 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3244 ¶ms, total_params, &data, total_data);
3245 END_PROFILE_NESTED(Trans2_qpathinfo);
3247 case TRANSACT2_SETPATHINFO:
3248 case TRANSACT2_SETFILEINFO:
3249 START_PROFILE_NESTED(Trans2_setpathinfo);
3250 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3251 ¶ms, total_params, &data, total_data);
3252 END_PROFILE_NESTED(Trans2_setpathinfo);
3255 case TRANSACT2_FINDNOTIFYFIRST:
3256 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3257 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
3258 ¶ms, total_params, &data, total_data);
3259 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3262 case TRANSACT2_FINDNOTIFYNEXT:
3263 START_PROFILE_NESTED(Trans2_findnotifynext);
3264 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
3265 ¶ms, total_params, &data, total_data);
3266 END_PROFILE_NESTED(Trans2_findnotifynext);
3268 case TRANSACT2_MKDIR:
3269 START_PROFILE_NESTED(Trans2_mkdir);
3270 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3271 ¶ms, total_params, &data, total_data);
3272 END_PROFILE_NESTED(Trans2_mkdir);
3275 case TRANSACT2_GET_DFS_REFERRAL:
3276 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3277 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3278 ¶ms, total_params, &data, total_data);
3279 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3281 case TRANSACT2_IOCTL:
3282 START_PROFILE_NESTED(Trans2_ioctl);
3283 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3284 ¶ms, total_params, &data, total_data);
3285 END_PROFILE_NESTED(Trans2_ioctl);
3288 /* Error in request */
3289 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3292 END_PROFILE(SMBtrans2);
3293 return ERROR_DOS(ERRSRV,ERRerror);
3296 /* As we do not know how many data packets will need to be
3297 returned here the various call_trans2xxxx calls
3298 must send their own. Thus a call_trans2xxx routine only
3299 returns a value other than -1 when it wants to send
3305 END_PROFILE(SMBtrans2);
3306 return outsize; /* If a correct response was needed the
3307 call_trans2xxx calls have already sent
3308 it. If outsize != -1 then it is returning */