add WITH_SENDFILE profiling data (from Pierre Belanger)
[Samba.git] / source / smbd / trans2.c
blob3750fb68b7049e435ec521a59d2b609bf8bdf8f0
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 SMB transaction2 handling
5 Extensively modified by Andrew Tridgell, 1995
6 Copyright (C) Jeremy Allison 1994-2002
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.
23 #include "includes.h"
25 extern int Protocol;
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 #define get_file_size(sbuf) (sbuf.st_size)
35 /* given a stat buffer return the allocated size on disk, taking into
36 account sparse files */
38 SMB_OFF_T get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
40 SMB_OFF_T ret;
41 #if defined(HAVE_STAT_ST_BLKSIZE) && defined(HAVE_STAT_ST_BLOCKS)
42 ret = sbuf->st_blksize * (SMB_OFF_T)sbuf->st_blocks;
43 #elif defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
44 ret = (SMB_OFF_T)STAT_ST_BLOCKSIZE * (SMB_OFF_T)sbuf->st_blocks;
45 #else
46 ret = get_file_size(*sbuf);
47 #endif
48 if (!ret && fsp && fsp->initial_allocation_size)
49 ret = fsp->initial_allocation_size;
50 ret = SMB_ROUNDUP(ret,SMB_ROUNDUP_ALLOCATION_SIZE);
51 return ret;
54 /****************************************************************************
55 Send the required number of replies back.
56 We assume all fields other than the data fields are
57 set correctly for the type of call.
58 HACK ! Always assumes smb_setup field is zero.
59 ****************************************************************************/
61 static int send_trans2_replies(char *outbuf, int bufsize, char *params, int paramsize, char *pdata, int datasize)
63 /* As we are using a protocol > LANMAN1 then the max_send
64 variable must have been set in the sessetupX call.
65 This takes precedence over the max_xmit field in the
66 global struct. These different max_xmit variables should
67 be merged as this is now too confusing */
69 extern int max_send;
70 int data_to_send = datasize;
71 int params_to_send = paramsize;
72 int useable_space;
73 char *pp = params;
74 char *pd = pdata;
75 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
76 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
77 int data_alignment_offset = 0;
79 /* Initially set the wcnt area to be 10 - this is true for all
80 trans2 replies */
81 set_message(outbuf,10,0,True);
83 /* If there genuinely are no parameters or data to send just send
84 the empty packet */
86 if(params_to_send == 0 && data_to_send == 0) {
87 if (!send_smb(smbd_server_fd(),outbuf))
88 exit_server("send_trans2_replies: send_smb failed.");
89 return 0;
92 /* When sending params and data ensure that both are nicely aligned */
93 /* Only do this alignment when there is also data to send - else
94 can cause NT redirector problems. */
96 if (((params_to_send % 4) != 0) && (data_to_send != 0))
97 data_alignment_offset = 4 - (params_to_send % 4);
99 /* Space is bufsize minus Netbios over TCP header minus SMB header */
100 /* The alignment_offset is to align the param bytes on an even byte
101 boundary. NT 4.0 Beta needs this to work correctly. */
103 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
105 /* useable_space can never be more than max_send minus the alignment offset. */
107 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
110 while (params_to_send || data_to_send) {
111 /* Calculate whether we will totally or partially fill this packet */
113 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
115 /* We can never send more than useable_space */
117 * Note that 'useable_space' does not include the alignment offsets,
118 * but we must include the alignment offsets in the calculation of
119 * the length of the data we send over the wire, as the alignment offsets
120 * are sent here. Fix from Marc_Jacobsen@hp.com.
123 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
125 set_message(outbuf, 10, total_sent_thistime, True);
127 /* Set total params and data to be sent */
128 SSVAL(outbuf,smb_tprcnt,paramsize);
129 SSVAL(outbuf,smb_tdrcnt,datasize);
131 /* Calculate how many parameters and data we can fit into
132 this packet. Parameters get precedence */
134 params_sent_thistime = MIN(params_to_send,useable_space);
135 data_sent_thistime = useable_space - params_sent_thistime;
136 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
138 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
140 /* smb_proff is the offset from the start of the SMB header to the
141 parameter bytes, however the first 4 bytes of outbuf are
142 the Netbios over TCP header. Thus use smb_base() to subtract
143 them from the calculation */
145 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
147 if(params_sent_thistime == 0)
148 SSVAL(outbuf,smb_prdisp,0);
149 else
150 /* Absolute displacement of param bytes sent in this packet */
151 SSVAL(outbuf,smb_prdisp,pp - params);
153 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
154 if(data_sent_thistime == 0) {
155 SSVAL(outbuf,smb_droff,0);
156 SSVAL(outbuf,smb_drdisp, 0);
157 } else {
158 /* The offset of the data bytes is the offset of the
159 parameter bytes plus the number of parameters being sent this time */
160 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
161 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
162 SSVAL(outbuf,smb_drdisp, pd - pdata);
165 /* Copy the param bytes into the packet */
167 if(params_sent_thistime)
168 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
170 /* Copy in the data bytes */
172 if(data_sent_thistime)
173 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
174 data_alignment_offset,pd,data_sent_thistime);
176 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
177 params_sent_thistime, data_sent_thistime, useable_space));
178 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
179 params_to_send, data_to_send, paramsize, datasize));
181 /* Send the packet */
182 if (!send_smb(smbd_server_fd(),outbuf))
183 exit_server("send_trans2_replies: send_smb failed.");
185 pp += params_sent_thistime;
186 pd += data_sent_thistime;
188 params_to_send -= params_sent_thistime;
189 data_to_send -= data_sent_thistime;
191 /* Sanity check */
193 if(params_to_send < 0 || data_to_send < 0) {
194 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
195 params_to_send, data_to_send));
196 return -1;
200 return 0;
203 /****************************************************************************
204 Reply to a TRANSACT2_OPEN.
205 ****************************************************************************/
207 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
208 char **pparams, int total_params, char **ppdata, int total_data)
210 char *params = *pparams;
211 int16 open_mode;
212 int16 open_attr;
213 BOOL oplock_request;
214 #if 0
215 BOOL return_additional_info;
216 int16 open_sattr;
217 time_t open_time;
218 #endif
219 int16 open_ofun;
220 int32 open_size;
221 char *pname;
222 int16 namelen;
224 pstring fname;
225 mode_t unixmode;
226 SMB_OFF_T size=0;
227 int fmode=0,mtime=0,rmode;
228 SMB_INO_T inode = 0;
229 SMB_STRUCT_STAT sbuf;
230 int smb_action = 0;
231 BOOL bad_path = False;
232 files_struct *fsp;
235 * Ensure we have enough parameters to perform the operation.
238 if (total_params < 29)
239 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
241 open_mode = SVAL(params, 2);
242 open_attr = SVAL(params,6);
243 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
244 #if 0
245 return_additional_info = BITSETW(params,0);
246 open_sattr = SVAL(params, 4);
247 open_time = make_unix_date3(params+8);
248 #endif
249 open_ofun = SVAL(params,12);
250 open_size = IVAL(params,14);
251 pname = &params[28];
252 namelen = strlen(pname)+1;
254 StrnCpy(fname,pname,namelen);
256 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
257 fname,open_mode, open_attr, open_ofun, open_size));
259 if (IS_IPC(conn))
260 return(ERROR_DOS(ERRSRV,ERRaccess));
262 /* XXXX we need to handle passed times, sattr and flags */
264 unix_convert(fname,conn,0,&bad_path,&sbuf);
266 if (!check_name(fname,conn)) {
267 set_bad_path_error(errno, bad_path);
268 return(UNIXERROR(ERRDOS,ERRnoaccess));
271 unixmode = unix_mode(conn,open_attr | aARCH, fname);
273 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode,
274 oplock_request, &rmode,&smb_action);
276 if (!fsp) {
277 set_bad_path_error(errno, bad_path);
278 return(UNIXERROR(ERRDOS,ERRnoaccess));
281 size = get_file_size(sbuf);
282 fmode = dos_mode(conn,fname,&sbuf);
283 mtime = sbuf.st_mtime;
284 inode = sbuf.st_ino;
285 if (fmode & aDIR) {
286 close_file(fsp,False);
287 return(ERROR_DOS(ERRDOS,ERRnoaccess));
290 /* Realloc the size of parameters and data we will return */
291 params = Realloc(*pparams, 28);
292 if( params == NULL )
293 return(ERROR_DOS(ERRDOS,ERRnomem));
294 *pparams = params;
296 memset((char *)params,'\0',28);
297 SSVAL(params,0,fsp->fnum);
298 SSVAL(params,2,fmode);
299 put_dos_date2(params,4, mtime);
300 SIVAL(params,8, (uint32)size);
301 SSVAL(params,12,rmode);
303 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
304 smb_action |= EXTENDED_OPLOCK_GRANTED;
306 SSVAL(params,18,smb_action);
309 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
311 SIVAL(params,20,inode);
313 /* Send the required number of replies */
314 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
316 return -1;
319 /*********************************************************
320 Routine to check if a given string matches exactly.
321 as a special case a mask of "." does NOT match. That
322 is required for correct wildcard semantics
323 Case can be significant or not.
324 **********************************************************/
326 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
328 if (mask[0] == '.' && mask[1] == 0)
329 return False;
330 if (case_sig)
331 return strcmp(str,mask)==0;
332 return strcasecmp(str,mask) == 0;
335 /****************************************************************************
336 Return the filetype for UNIX extensions.
337 ****************************************************************************/
339 static uint32 unix_filetype(mode_t mode)
341 if(S_ISREG(mode))
342 return UNIX_TYPE_FILE;
343 else if(S_ISDIR(mode))
344 return UNIX_TYPE_DIR;
345 #ifdef S_ISLNK
346 else if(S_ISLNK(mode))
347 return UNIX_TYPE_SYMLINK;
348 #endif
349 #ifdef S_ISCHR
350 else if(S_ISCHR(mode))
351 return UNIX_TYPE_CHARDEV;
352 #endif
353 #ifdef S_ISBLK
354 else if(S_ISBLK(mode))
355 return UNIX_TYPE_BLKDEV;
356 #endif
357 #ifdef S_ISFIFO
358 else if(S_ISFIFO(mode))
359 return UNIX_TYPE_FIFO;
360 #endif
361 #ifdef S_ISSOCK
362 else if(S_ISSOCK(mode))
363 return UNIX_TYPE_SOCKET;
364 #endif
366 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
367 return UNIX_TYPE_UNKNOWN;
370 /****************************************************************************
371 Return the major devicenumber for UNIX extensions.
372 ****************************************************************************/
374 static uint32 unix_dev_major(SMB_DEV_T dev)
376 #if defined(HAVE_DEVICE_MAJOR_FN)
377 return (uint32)major(dev);
378 #else
379 return (uint32)(dev >> 8);
380 #endif
383 /****************************************************************************
384 Return the minor devicenumber for UNIX extensions.
385 ****************************************************************************/
387 static uint32 unix_dev_minor(SMB_DEV_T dev)
389 #if defined(HAVE_DEVICE_MINOR_FN)
390 return (uint32)minor(dev);
391 #else
392 return (uint32)(dev & 0xff);
393 #endif
396 /****************************************************************************
397 Map wire perms onto standard UNIX permissions. Obey share restrictions.
398 ****************************************************************************/
400 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
402 mode_t ret = 0;
404 if (perms == SMB_MODE_NO_CHANGE)
405 return pst->st_mode;
407 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
408 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
409 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
410 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
411 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
412 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
413 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
414 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
415 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
416 #ifdef S_ISVTX
417 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
418 #endif
419 #ifdef S_ISGID
420 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
421 #endif
422 #ifdef S_ISUID
423 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
424 #endif
426 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
427 ret &= lp_dir_mask(SNUM(conn));
428 /* Add in force bits */
429 ret |= lp_force_dir_mode(SNUM(conn));
430 } else {
431 /* Apply mode mask */
432 ret &= lp_create_mask(SNUM(conn));
433 /* Add in force bits */
434 ret |= lp_force_create_mode(SNUM(conn));
437 return ret;
440 /****************************************************************************
441 checks for SMB_TIME_NO_CHANGE and if not found
442 calls interpret_long_date
443 ****************************************************************************/
444 time_t interpret_long_unix_date(char *p)
446 DEBUG(1,("interpret_long_unix_date\n"));
447 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
448 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
449 return -1;
450 } else {
451 return interpret_long_date(p);
455 /****************************************************************************
456 Get a level dependent lanman2 dir entry.
457 ****************************************************************************/
459 static BOOL get_lanman2_dir_entry(connection_struct *conn,
460 char *path_mask,int dirtype,int info_level,
461 int requires_resume_key,
462 BOOL dont_descend,char **ppdata,
463 char *base_data, int space_remaining,
464 BOOL *out_of_space, BOOL *got_exact_match,
465 int *last_name_off)
467 char *dname;
468 BOOL found = False;
469 SMB_STRUCT_STAT sbuf;
470 pstring mask;
471 pstring pathreal;
472 pstring fname;
473 char *p, *pdata = *ppdata;
474 uint32 reskey=0;
475 int prev_dirpos=0;
476 int mode=0;
477 SMB_OFF_T size = 0;
478 SMB_OFF_T allocation_size = 0;
479 uint32 len;
480 time_t mdate=0, adate=0, cdate=0;
481 char *nameptr;
482 BOOL was_8_3;
483 int nt_extmode; /* Used for NT connections instead of mode */
484 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
486 *fname = 0;
487 *out_of_space = False;
488 *got_exact_match = False;
490 if (!conn->dirptr)
491 return(False);
493 p = strrchr(path_mask,'/');
494 if(p != NULL) {
495 if(p[1] == '\0')
496 pstrcpy(mask,"*.*");
497 else
498 pstrcpy(mask, p+1);
499 } else
500 pstrcpy(mask, path_mask);
502 while (!found) {
503 BOOL got_match;
505 /* Needed if we run out of space */
506 prev_dirpos = TellDir(conn->dirptr);
507 dname = ReadDirName(conn->dirptr);
510 * Due to bugs in NT client redirectors we are not using
511 * resume keys any more - set them to zero.
512 * Check out the related comments in findfirst/findnext.
513 * JRA.
516 reskey = 0;
518 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
519 (long)conn->dirptr,TellDir(conn->dirptr)));
521 if (!dname)
522 return(False);
524 pstrcpy(fname,dname);
526 if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
527 got_match = mask_match(fname, mask, case_sensitive);
529 if(!got_match && !mangle_is_8_3(fname, False)) {
532 * It turns out that NT matches wildcards against
533 * both long *and* short names. This may explain some
534 * of the wildcard wierdness from old DOS clients
535 * that some people have been seeing.... JRA.
538 pstring newname;
539 pstrcpy( newname, fname);
540 mangle_map( newname, True, False, SNUM(conn));
541 if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
542 got_match = mask_match(newname, mask, case_sensitive);
545 if(got_match) {
546 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
547 if (dont_descend && !isdots)
548 continue;
550 pstrcpy(pathreal,conn->dirpath);
551 if(needslash)
552 pstrcat(pathreal,"/");
553 pstrcat(pathreal,dname);
555 if (INFO_LEVEL_IS_UNIX(info_level)) {
556 if (vfs_lstat(conn,pathreal,&sbuf) != 0) {
557 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
558 pathreal,strerror(errno)));
559 continue;
561 } else if (vfs_stat(conn,pathreal,&sbuf) != 0) {
563 /* Needed to show the msdfs symlinks as
564 * directories */
566 if(lp_host_msdfs() &&
567 lp_msdfs_root(SNUM(conn)) &&
568 is_msdfs_link(conn, pathreal, NULL, NULL,
569 &sbuf)) {
571 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
572 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
574 } else {
576 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
577 pathreal,strerror(errno)));
578 continue;
582 mode = dos_mode(conn,pathreal,&sbuf);
584 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
585 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
586 continue;
589 size = get_file_size(sbuf);
590 allocation_size = get_allocation_size(NULL,&sbuf);
591 mdate = sbuf.st_mtime;
592 adate = sbuf.st_atime;
593 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
595 if (lp_dos_filetime_resolution(SNUM(conn))) {
596 cdate &= ~1;
597 mdate &= ~1;
598 adate &= ~1;
601 if(mode & aDIR)
602 size = 0;
604 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
606 found = True;
610 mangle_map(fname,False,True,SNUM(conn));
612 p = pdata;
613 nameptr = p;
615 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
617 switch (info_level) {
618 case 1:
619 if(requires_resume_key) {
620 SIVAL(p,0,reskey);
621 p += 4;
623 put_dos_date2(p,l1_fdateCreation,cdate);
624 put_dos_date2(p,l1_fdateLastAccess,adate);
625 put_dos_date2(p,l1_fdateLastWrite,mdate);
626 SIVAL(p,l1_cbFile,(uint32)size);
627 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
628 SSVAL(p,l1_attrFile,mode);
629 SCVAL(p,l1_cchName,strlen(fname));
630 pstrcpy(p + l1_achName, fname);
631 nameptr = p + l1_achName;
632 p += l1_achName + strlen(fname) + 1;
633 break;
635 case 2:
636 if(requires_resume_key) {
637 SIVAL(p,0,reskey);
638 p += 4;
640 put_dos_date2(p,l2_fdateCreation,cdate);
641 put_dos_date2(p,l2_fdateLastAccess,adate);
642 put_dos_date2(p,l2_fdateLastWrite,mdate);
643 SIVAL(p,l2_cbFile,(uint32)size);
644 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
645 SSVAL(p,l2_attrFile,mode);
646 SIVAL(p,l2_cbList,0); /* No extended attributes */
647 SCVAL(p,l2_cchName,strlen(fname));
648 pstrcpy(p + l2_achName, fname);
649 nameptr = p + l2_achName;
650 p += l2_achName + strlen(fname) + 1;
651 break;
653 case 3:
654 SIVAL(p,0,reskey);
655 put_dos_date2(p,4,cdate);
656 put_dos_date2(p,8,adate);
657 put_dos_date2(p,12,mdate);
658 SIVAL(p,16,(uint32)size);
659 SIVAL(p,20,(uint32)allocation_size);
660 SSVAL(p,24,mode);
661 SIVAL(p,26,4);
662 SCVAL(p,30,strlen(fname));
663 pstrcpy(p+31, fname);
664 nameptr = p+31;
665 p += 31 + strlen(fname) + 1;
666 break;
668 case 4:
669 if(requires_resume_key) {
670 SIVAL(p,0,reskey);
671 p += 4;
673 SIVAL(p,0,33+strlen(fname)+1);
674 put_dos_date2(p,4,cdate);
675 put_dos_date2(p,8,adate);
676 put_dos_date2(p,12,mdate);
677 SIVAL(p,16,(uint32)size);
678 SIVAL(p,20,(uint32)allocation_size);
679 SSVAL(p,24,mode);
680 SCVAL(p,32,strlen(fname));
681 pstrcpy(p + 33, fname);
682 nameptr = p+33;
683 p += 33 + strlen(fname) + 1;
684 break;
686 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
687 was_8_3 = mangle_is_8_3(fname, True);
688 len = 94+strlen(fname);
689 len = (len + 3) & ~3;
690 SIVAL(p,0,len); p += 4;
691 SIVAL(p,0,reskey); p += 4;
692 put_long_date(p,cdate); p += 8;
693 put_long_date(p,adate); p += 8;
694 put_long_date(p,mdate); p += 8;
695 put_long_date(p,mdate); p += 8;
696 SOFF_T(p,0,size);
697 SOFF_T(p,8,allocation_size);
698 p += 16;
699 SIVAL(p,0,nt_extmode); p += 4;
700 SIVAL(p,0,strlen(fname)); p += 4;
701 SIVAL(p,0,0); p += 4;
702 /* Clear the short name buffer. This is
703 * IMPORTANT as not doing so will trigger
704 * a Win2k client bug. JRA.
706 memset(p,'\0',26);
707 if (!was_8_3) {
708 fstring tmpname;
709 fstrcpy(tmpname,fname);
710 mangle_map(tmpname,True,True,SNUM(conn));
711 strupper(tmpname);
712 fstrcpy(p+2,tmpname);
713 SSVAL(p, 0, strlen(tmpname));
714 } else {
715 SSVAL(p,0,0);
716 *(p+2) = 0;
718 p += 2 + 24;
719 /* nameptr = p; */
720 pstrcpy(p,fname); p += strlen(p);
721 p = pdata + len;
722 break;
724 case SMB_FIND_FILE_DIRECTORY_INFO:
725 len = 64+strlen(fname);
726 len = (len + 3) & ~3;
727 SIVAL(p,0,len); p += 4;
728 SIVAL(p,0,reskey); p += 4;
729 put_long_date(p,cdate); p += 8;
730 put_long_date(p,adate); p += 8;
731 put_long_date(p,mdate); p += 8;
732 put_long_date(p,mdate); p += 8;
733 SOFF_T(p,0,size);
734 SOFF_T(p,8,allocation_size);
735 p += 16;
736 SIVAL(p,0,nt_extmode); p += 4;
737 SIVAL(p,0,strlen(fname)); p += 4;
738 pstrcpy(p,fname);
739 p = pdata + len;
740 break;
742 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
743 len = 68+strlen(fname);
744 len = (len + 3) & ~3;
745 SIVAL(p,0,len); p += 4;
746 SIVAL(p,0,reskey); p += 4;
747 put_long_date(p,cdate); p += 8;
748 put_long_date(p,adate); p += 8;
749 put_long_date(p,mdate); p += 8;
750 put_long_date(p,mdate); p += 8;
751 SOFF_T(p,0,size);
752 SOFF_T(p,8,allocation_size);
753 p += 16;
754 SIVAL(p,0,nt_extmode); p += 4;
755 SIVAL(p,0,strlen(fname)); p += 4;
756 SIVAL(p,0,0); p += 4;
757 pstrcpy(p,fname);
758 p = pdata + len;
759 break;
761 case SMB_FIND_FILE_NAMES_INFO:
762 len = 12+strlen(fname);
763 len = (len + 3) & ~3;
764 SIVAL(p,0,len); p += 4;
765 SIVAL(p,0,reskey); p += 4;
766 SIVAL(p,0,strlen(fname)); p += 4;
767 pstrcpy(p,fname);
768 p = pdata + len;
769 break;
771 /* CIFS UNIX Extension. */
773 case SMB_FIND_FILE_UNIX:
774 len = 108+strlen(fname)+1; /* (length of SMB_QUERY_FILE_UNIX_BASIC = 100)+4+4+strlen(fname)*/
775 /* +1 to be sure to transmit the termination of fname */
776 len = (len + 3) & ~3;
778 SIVAL(p,0,len); p+= 4; /* Offset from this structure to the beginning of the next one */
779 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
781 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
782 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
783 p+= 8;
785 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
786 p+= 8;
788 put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */
789 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
790 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
791 p+= 24;
793 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
794 SIVAL(p,4,0);
795 p+= 8;
797 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
798 SIVAL(p,4,0);
799 p+= 8;
801 SIVAL(p,0,unix_filetype(sbuf.st_mode));
802 p+= 4;
804 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
805 SIVAL(p,4,0);
806 p+= 8;
808 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
809 SIVAL(p,4,0);
810 p+= 8;
812 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
813 p+= 8;
815 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
816 SIVAL(p,4,0);
817 p+= 8;
819 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
820 SIVAL(p,4,0);
821 p+= 8;
823 /* End of SMB_QUERY_FILE_UNIX_BASIC */
824 pstrcpy(p,fname);
825 p=pdata+len;
827 break;
829 default:
830 return(False);
834 if (PTR_DIFF(p,pdata) > space_remaining) {
835 /* Move the dirptr back to prev_dirpos */
836 SeekDir(conn->dirptr, prev_dirpos);
837 *out_of_space = True;
838 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
839 return False; /* Not finished - just out of space */
842 /* Setup the last_filename pointer, as an offset from base_data */
843 *last_name_off = PTR_DIFF(nameptr,base_data);
844 /* Advance the data pointer to the next slot */
845 *ppdata = p;
847 return(found);
850 /****************************************************************************
851 Reply to a TRANS2_FINDFIRST.
852 ****************************************************************************/
854 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
855 char **pparams, int total_params, char **ppdata, int total_data)
857 /* We must be careful here that we don't return more than the
858 allowed number of data bytes. If this means returning fewer than
859 maxentries then so be it. We assume that the redirector has
860 enough room for the fixed number of parameter bytes it has
861 requested. */
862 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
863 char *params = *pparams;
864 char *pdata = *ppdata;
865 int dirtype;
866 int maxentries;
867 BOOL close_after_first;
868 BOOL close_if_end;
869 BOOL requires_resume_key;
870 int info_level;
871 pstring directory;
872 pstring mask;
873 char *p, *wcard;
874 int last_name_off=0;
875 int dptr_num = -1;
876 int numentries = 0;
877 int i;
878 BOOL finished = False;
879 BOOL dont_descend = False;
880 BOOL out_of_space = False;
881 int space_remaining;
882 BOOL bad_path = False;
883 SMB_STRUCT_STAT sbuf;
885 if (total_params < 12)
886 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
888 *directory = *mask = 0;
890 dirtype = SVAL(params,0);
891 maxentries = SVAL(params,2);
892 close_after_first = BITSETW(params+4,0);
893 close_if_end = BITSETW(params+4,1);
894 requires_resume_key = BITSETW(params+4,2);
895 info_level = SVAL(params,6);
897 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
898 close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
899 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
900 info_level, max_data_bytes));
902 switch (info_level) {
903 case 1:
904 case 2:
905 case 3:
906 case 4:
907 case SMB_FIND_FILE_DIRECTORY_INFO:
908 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
909 case SMB_FIND_FILE_NAMES_INFO:
910 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
911 break;
912 case SMB_FIND_FILE_UNIX:
913 if (!lp_unix_extensions())
914 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
915 break;
916 default:
917 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
920 pstrcpy(directory, params + 12); /* Complete directory path with wildcard mask appended */
922 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
924 DEBUG(5,("path=%s\n",directory));
926 unix_convert(directory,conn,0,&bad_path,&sbuf);
927 if(!check_name(directory,conn)) {
928 set_bad_path_error(errno, bad_path);
930 #if 0
931 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
932 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && (get_remote_arch() == RA_WINNT)) {
933 unix_ERR_class = ERRDOS;
934 unix_ERR_code = ERRbaddirectory;
936 #endif
938 return(UNIXERROR(ERRDOS,ERRbadpath));
941 p = strrchr(directory,'/');
942 if(p == NULL) {
943 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
944 if((directory[0] == '.') && (directory[1] == '\0'))
945 pstrcpy(mask,"*");
946 else
947 pstrcpy(mask,directory);
948 pstrcpy(directory,"./");
949 } else {
950 pstrcpy(mask,p+1);
951 *p = 0;
954 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
956 pdata = Realloc(*ppdata, max_data_bytes + 1024);
957 if( pdata == NULL )
958 return(ERROR_DOS(ERRDOS,ERRnomem));
959 *ppdata = pdata;
960 memset((char *)pdata,'\0',max_data_bytes + 1024);
962 /* Realloc the params space */
963 params = Realloc(*pparams, 10);
964 if( params == NULL )
965 return ERROR_DOS(ERRDOS,ERRnomem);
966 *pparams = params;
968 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
969 if (dptr_num < 0)
970 return(UNIXERROR(ERRDOS,ERRbadfile));
972 /* Save the wildcard match and attribs we are using on this directory -
973 needed as lanman2 assumes these are being saved between calls */
975 if(!(wcard = strdup(mask))) {
976 dptr_close(&dptr_num);
977 return ERROR_DOS(ERRDOS,ERRnomem);
980 dptr_set_wcard(dptr_num, wcard);
981 dptr_set_attr(dptr_num, dirtype);
983 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
985 /* We don't need to check for VOL here as this is returned by
986 a different TRANS2 call. */
988 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
990 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
991 dont_descend = True;
993 p = pdata;
994 space_remaining = max_data_bytes;
995 out_of_space = False;
997 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
998 BOOL got_exact_match = False;
1000 /* this is a heuristic to avoid seeking the dirptr except when
1001 absolutely necessary. It allows for a filename of about 40 chars */
1003 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1004 out_of_space = True;
1005 finished = False;
1006 } else {
1007 finished = !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
1008 requires_resume_key,dont_descend,
1009 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1010 &last_name_off);
1013 if (finished && out_of_space)
1014 finished = False;
1016 if (!finished && !out_of_space)
1017 numentries++;
1020 * As an optimisation if we know we aren't looking
1021 * for a wildcard name (ie. the name matches the wildcard exactly)
1022 * then we can finish on any (first) match.
1023 * This speeds up large directory searches. JRA.
1026 if(got_exact_match)
1027 finished = True;
1029 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1032 /* Check if we can close the dirptr */
1034 if(close_after_first || (finished && close_if_end)) {
1035 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1036 dptr_close(&dptr_num);
1040 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1041 * from observation of NT.
1044 if(numentries == 0) {
1045 dptr_close(&dptr_num);
1046 return ERROR_DOS(ERRDOS,ERRbadfile);
1049 /* At this point pdata points to numentries directory entries. */
1051 /* Set up the return parameter block */
1052 SSVAL(params,0,dptr_num);
1053 SSVAL(params,2,numentries);
1054 SSVAL(params,4,finished);
1055 SSVAL(params,6,0); /* Never an EA error */
1056 SSVAL(params,8,last_name_off);
1058 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1060 if ((! *directory) && dptr_path(dptr_num))
1061 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1063 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1064 smb_fn_name(CVAL(inbuf,smb_com)),
1065 mask, directory, dirtype, numentries ) );
1068 * Force a name mangle here to ensure that the
1069 * mask as an 8.3 name is top of the mangled cache.
1070 * The reasons for this are subtle. Don't remove
1071 * this code unless you know what you are doing
1072 * (see PR#13758). JRA.
1075 if(!mangle_is_8_3_wildcards( mask, False))
1076 mangle_map(mask, True, True, SNUM(conn));
1078 return(-1);
1081 /****************************************************************************
1082 Reply to a TRANS2_FINDNEXT.
1083 ****************************************************************************/
1085 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1086 char **pparams, int total_params, char **ppdata, int total_data)
1088 /* We must be careful here that we don't return more than the
1089 allowed number of data bytes. If this means returning fewer than
1090 maxentries then so be it. We assume that the redirector has
1091 enough room for the fixed number of parameter bytes it has
1092 requested. */
1093 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1094 char *params = *pparams;
1095 char *pdata = *ppdata;
1096 int dptr_num;
1097 int maxentries;
1098 uint16 info_level;
1099 uint32 resume_key;
1100 BOOL close_after_request;
1101 BOOL close_if_end;
1102 BOOL requires_resume_key;
1103 BOOL continue_bit;
1104 pstring resume_name;
1105 pstring mask;
1106 pstring directory;
1107 char *p;
1108 uint16 dirtype;
1109 int numentries = 0;
1110 int i, last_name_off=0;
1111 BOOL finished = False;
1112 BOOL dont_descend = False;
1113 BOOL out_of_space = False;
1114 int space_remaining;
1116 if (total_params < 12)
1117 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1119 dptr_num = SVAL(params,0);
1120 maxentries = SVAL(params,2);
1121 info_level = SVAL(params,4);
1122 resume_key = IVAL(params,6);
1123 close_after_request = BITSETW(params+10,0);
1124 close_if_end = BITSETW(params+10,1);
1125 requires_resume_key = BITSETW(params+10,2);
1126 continue_bit = BITSETW(params+10,3);
1128 *mask = *directory = *resume_name = 0;
1130 pstrcpy( resume_name, params+12);
1132 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1133 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1134 resume_key = %d resume name = %s continue=%d level = %d\n",
1135 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1136 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1138 switch (info_level) {
1139 case 1:
1140 case 2:
1141 case 3:
1142 case 4:
1143 case SMB_FIND_FILE_DIRECTORY_INFO:
1144 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1145 case SMB_FIND_FILE_NAMES_INFO:
1146 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1147 break;
1148 case SMB_FIND_FILE_UNIX:
1149 if (!lp_unix_extensions())
1150 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1151 break;
1152 default:
1153 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1156 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1157 if(pdata == NULL)
1158 return ERROR_DOS(ERRDOS,ERRnomem);
1160 *ppdata = pdata;
1161 memset((char *)pdata,'\0',max_data_bytes + 1024);
1163 /* Realloc the params space */
1164 params = Realloc(*pparams, 6*SIZEOFWORD);
1165 if( params == NULL )
1166 return ERROR_DOS(ERRDOS,ERRnomem);
1167 *pparams = params;
1169 /* Check that the dptr is valid */
1170 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1171 return ERROR_DOS(ERRDOS,ERRnofiles);
1173 string_set(&conn->dirpath,dptr_path(dptr_num));
1175 /* Get the wildcard mask from the dptr */
1176 if((p = dptr_wcard(dptr_num))== NULL) {
1177 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1178 return ERROR_DOS(ERRDOS,ERRnofiles);
1180 pstrcpy(mask, p);
1181 pstrcpy(directory,conn->dirpath);
1183 /* Get the attr mask from the dptr */
1184 dirtype = dptr_attr(dptr_num);
1186 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1187 dptr_num, mask, dirtype, (long)conn->dirptr, TellDir(conn->dirptr)));
1189 /* We don't need to check for VOL here as this is returned by
1190 a different TRANS2 call. */
1192 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1193 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1194 dont_descend = True;
1196 p = pdata;
1197 space_remaining = max_data_bytes;
1198 out_of_space = False;
1201 * Seek to the correct position. We no longer use the resume key but
1202 * depend on the last file name instead.
1205 if(requires_resume_key && *resume_name && !continue_bit) {
1208 * Fix for NT redirector problem triggered by resume key indexes
1209 * changing between directory scans. We now return a resume key of 0
1210 * and instead look for the filename to continue from (also given
1211 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1212 * findfirst/findnext (as is usual) then the directory pointer
1213 * should already be at the correct place. Check this by scanning
1214 * backwards looking for an exact (ie. case sensitive) filename match.
1215 * If we get to the beginning of the directory and haven't found it then scan
1216 * forwards again looking for a match. JRA.
1219 int current_pos, start_pos;
1220 char *dname = NULL;
1221 void *dirptr = conn->dirptr;
1222 start_pos = TellDir(dirptr);
1224 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1225 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1227 SeekDir(dirptr, current_pos);
1228 dname = ReadDirName(dirptr);
1231 * Remember, name_map_mangle is called by
1232 * get_lanman2_dir_entry(), so the resume name
1233 * could be mangled. Ensure we do the same
1234 * here.
1237 if(dname != NULL)
1238 mangle_map( dname, False, True, SNUM(conn));
1240 if(dname && strcsequal( resume_name, dname)) {
1241 SeekDir(dirptr, current_pos+1);
1242 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1243 break;
1248 * Scan forward from start if not found going backwards.
1251 if(current_pos < 0) {
1252 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1253 SeekDir(dirptr, start_pos);
1254 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1257 * Remember, name_map_mangle is called by
1258 * get_lanman2_dir_entry(), so the resume name
1259 * could be mangled. Ensure we do the same
1260 * here.
1263 if(dname != NULL)
1264 mangle_map( dname, False, True, SNUM(conn));
1266 if(dname && strcsequal( resume_name, dname)) {
1267 SeekDir(dirptr, current_pos+1);
1268 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1269 break;
1271 } /* end for */
1272 } /* end if current_pos */
1273 } /* end if requires_resume_key && !continue_bit */
1275 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1276 BOOL got_exact_match = False;
1278 /* this is a heuristic to avoid seeking the dirptr except when
1279 absolutely necessary. It allows for a filename of about 40 chars */
1281 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1282 out_of_space = True;
1283 finished = False;
1284 } else {
1285 finished = !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
1286 requires_resume_key,dont_descend,
1287 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1288 &last_name_off);
1291 if (finished && out_of_space)
1292 finished = False;
1294 if (!finished && !out_of_space)
1295 numentries++;
1298 * As an optimisation if we know we aren't looking
1299 * for a wildcard name (ie. the name matches the wildcard exactly)
1300 * then we can finish on any (first) match.
1301 * This speeds up large directory searches. JRA.
1304 if(got_exact_match)
1305 finished = True;
1307 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1310 /* Check if we can close the dirptr */
1311 if(close_after_request || (finished && close_if_end)) {
1312 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1313 dptr_close(&dptr_num); /* This frees up the saved mask */
1317 /* Set up the return parameter block */
1318 SSVAL(params,0,numentries);
1319 SSVAL(params,2,finished);
1320 SSVAL(params,4,0); /* Never an EA error */
1321 SSVAL(params,6,last_name_off);
1323 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1325 if ((! *directory) && dptr_path(dptr_num))
1326 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1328 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1329 smb_fn_name(CVAL(inbuf,smb_com)),
1330 mask, directory, dirtype, numentries ) );
1332 return(-1);
1335 /****************************************************************************
1336 Reply to a TRANS2_QFSINFO (query filesystem info).
1337 ****************************************************************************/
1339 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1340 char **pparams, int total_params, char **ppdata, int total_data)
1342 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1343 char *pdata = *ppdata;
1344 char *params = *pparams;
1345 uint16 info_level;
1346 int data_len;
1347 SMB_STRUCT_STAT st;
1348 char *vname = volume_label(SNUM(conn));
1349 int snum = SNUM(conn);
1350 char *fstype = lp_fstype(SNUM(conn));
1352 if (total_params < 2)
1353 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1355 info_level = SVAL(params,0);
1356 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1358 if(vfs_stat(conn,".",&st)!=0) {
1359 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1360 return ERROR_DOS(ERRSRV,ERRinvdevice);
1363 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1364 if ( pdata == NULL )
1365 return ERROR_DOS(ERRDOS,ERRnomem);
1367 *ppdata = pdata;
1368 memset((char *)pdata,'\0',max_data_bytes + 1024);
1370 switch (info_level) {
1371 case 1:
1373 SMB_BIG_UINT dfree,dsize,bsize;
1374 data_len = 18;
1375 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1376 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1377 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1378 SIVAL(pdata,l1_cUnit,dsize);
1379 SIVAL(pdata,l1_cUnitAvail,dfree);
1380 SSVAL(pdata,l1_cbSector,512);
1381 DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1382 (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1383 (unsigned int)dfree, 512));
1384 break;
1387 case 2:
1389 /* Return volume name */
1390 int volname_len = MIN(strlen(vname),11);
1391 data_len = l2_vol_szVolLabel + volname_len + 1;
1393 * Add volume serial number - hash of a combination of
1394 * the called hostname and the service name.
1396 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1397 SCVAL(pdata,l2_vol_cch,volname_len);
1398 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
1399 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1400 (unsigned)st.st_ctime, volname_len,
1401 pdata+l2_vol_szVolLabel));
1402 break;
1405 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1406 case SMB_FS_ATTRIBUTE_INFORMATION:
1408 int fstype_len;
1409 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1410 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */
1411 #if 0 /* Old code. JRA. */
1412 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
1413 SIVAL(pdata,0,0x700FF);
1414 #endif /* Old code. */
1416 SIVAL(pdata,4,255); /* Max filename component length */
1417 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1418 and will think we can't do long filenames */
1419 fstype_len = dos_PutUniCode(pdata+12,unix_to_dos_static(fstype),sizeof(pstring), False);
1420 SIVAL(pdata,8,fstype_len);
1421 data_len = 12 + fstype_len;
1422 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1423 break;
1426 case SMB_QUERY_FS_LABEL_INFO:
1427 case SMB_FS_LABEL_INFORMATION:
1428 data_len = 4 + strlen(vname);
1429 SIVAL(pdata,0,strlen(vname));
1430 pstrcpy(pdata+4,vname);
1431 break;
1433 case SMB_QUERY_FS_VOLUME_INFO:
1434 case SMB_FS_VOLUME_INFORMATION:
1436 * Add volume serial number - hash of a combination of
1437 * the called hostname and the service name.
1439 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1440 (str_checksum(local_machine)<<16));
1442 /* NT4 always serves this up as unicode but expects it to be
1443 * delivered as ascii! (tridge && JRA)
1445 if ((get_remote_arch() != RA_WIN2K) && (global_client_caps & CAP_NT_SMBS)) {
1446 data_len = 18 + strlen(vname);
1447 SIVAL(pdata,12,strlen(vname));
1448 pstrcpy(pdata+18,vname);
1449 } else {
1450 int vnamelen;
1452 vnamelen = dos_PutUniCode(pdata+18, vname, sizeof(pstring), False);
1453 data_len = 18 + vnamelen;
1454 SIVAL(pdata,12,vnamelen);
1455 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1458 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n",
1459 (int)strlen(vname),vname));
1460 break;
1462 case SMB_QUERY_FS_SIZE_INFO:
1463 case SMB_FS_SIZE_INFORMATION:
1465 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1466 data_len = 24;
1467 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1468 block_size = lp_block_size(snum);
1469 if (bsize < block_size) {
1470 SMB_BIG_UINT factor = block_size/bsize;
1471 bsize = block_size;
1472 dsize /= factor;
1473 dfree /= factor;
1475 if (bsize > block_size) {
1476 SMB_BIG_UINT factor = bsize/block_size;
1477 bsize = block_size;
1478 dsize *= factor;
1479 dfree *= factor;
1481 bytes_per_sector = 512;
1482 sectors_per_unit = bsize/bytes_per_sector;
1483 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1484 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1485 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1486 SBIG_UINT(pdata,0,dsize);
1487 SBIG_UINT(pdata,8,dfree);
1488 SIVAL(pdata,16,sectors_per_unit);
1489 SIVAL(pdata,20,bytes_per_sector);
1490 break;
1493 case SMB_FS_FULL_SIZE_INFORMATION:
1495 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1496 data_len = 32;
1497 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1498 block_size = lp_block_size(snum);
1499 if (bsize < block_size) {
1500 SMB_BIG_UINT factor = block_size/bsize;
1501 bsize = block_size;
1502 dsize /= factor;
1503 dfree /= factor;
1505 if (bsize > block_size) {
1506 SMB_BIG_UINT factor = bsize/block_size;
1507 bsize = block_size;
1508 dsize *= factor;
1509 dfree *= factor;
1511 bytes_per_sector = 512;
1512 sectors_per_unit = bsize/bytes_per_sector;
1513 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1514 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1515 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1516 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1517 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1518 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1519 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1520 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1521 break;
1524 case SMB_QUERY_FS_DEVICE_INFO:
1525 case SMB_FS_DEVICE_INFORMATION:
1526 data_len = 8;
1527 SIVAL(pdata,0,0); /* dev type */
1528 SIVAL(pdata,4,0); /* characteristics */
1529 break;
1531 case SMB_FS_OBJECTID_INFORMATION:
1532 data_len = 64;
1533 break;
1536 * Query the version and capabilities of the CIFS UNIX extensions
1537 * in use.
1540 case SMB_QUERY_CIFS_UNIX_INFO:
1542 if (!lp_unix_extensions())
1543 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1545 data_len = 12;
1546 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
1547 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
1548 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
1549 break;
1551 case SMB_MAC_QUERY_FS_INFO:
1553 * Thursby MAC extension... ONLY on NTFS filesystems
1554 * once we do streams then we don't need this
1556 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1557 data_len = 88;
1558 SIVAL(pdata,84,0x100); /* Don't support mac... */
1559 break;
1561 /* drop through */
1562 default:
1563 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1566 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1568 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1570 return -1;
1573 /****************************************************************************
1574 Reply to a TRANS2_SETFSINFO (set filesystem info).
1575 ****************************************************************************/
1577 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1578 char **pparams, int total_params, char **ppdata, int total_data)
1580 /* Just say yes we did it - there is nothing that
1581 can be set here so it doesn't matter. */
1582 int outsize;
1583 DEBUG(3,("call_trans2setfsinfo\n"));
1585 if (!CAN_WRITE(conn))
1586 return(ERROR_DOS(ERRSRV,ERRaccess));
1588 outsize = set_message(outbuf,10,0,True);
1590 return outsize;
1593 /****************************************************************************
1594 Utility function to set bad path error.
1595 ****************************************************************************/
1597 NTSTATUS set_bad_path_error(int err, BOOL bad_path)
1599 if((err == ENOENT) && bad_path) {
1600 unix_ERR_class = ERRDOS;
1601 unix_ERR_code = ERRbadpath;
1602 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1604 return NT_STATUS_OK;
1607 /****************************************************************************
1608 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1609 file name or file id).
1610 ****************************************************************************/
1612 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1613 char **pparams, int total_params, char **ppdata, int total_data)
1615 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1616 char *params = *pparams;
1617 char *pdata = *ppdata;
1618 uint16 tran_call = SVAL(inbuf, smb_setup0);
1619 uint16 info_level;
1620 int mode=0;
1621 SMB_OFF_T size=0;
1622 SMB_OFF_T allocation_size = 0;
1623 unsigned int data_size;
1624 SMB_STRUCT_STAT sbuf;
1625 pstring fname1;
1626 char *fname;
1627 pstring dos_fname;
1628 char *fullpathname;
1629 char *p;
1630 int l;
1631 SMB_OFF_T pos = 0;
1632 BOOL bad_path = False;
1633 BOOL delete_pending = False;
1634 time_t c_time;
1635 files_struct *fsp = NULL;
1637 if (!params)
1638 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1640 if (tran_call == TRANSACT2_QFILEINFO) {
1641 if (total_params < 4)
1642 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1644 fsp = file_fsp(params,0);
1645 info_level = SVAL(params,2);
1647 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1649 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1651 * This is actually a QFILEINFO on a directory
1652 * handle (returned from an NT SMB). NT5.0 seems
1653 * to do this call. JRA.
1655 fname = fsp->fsp_name;
1656 unix_convert(fname,conn,0,&bad_path,&sbuf);
1657 if (!check_name(fname,conn)) {
1658 DEBUG(3,("call_trans2qfilepathinfo: check_name of %s failed (%s)\n",fname,strerror(errno)));
1659 set_bad_path_error(errno, bad_path);
1660 return(UNIXERROR(ERRDOS,ERRbadpath));
1663 if (INFO_LEVEL_IS_UNIX(info_level)) {
1664 /* Always do lstat for UNIX calls. */
1665 if (vfs_lstat(conn,fname,&sbuf)) {
1666 DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
1667 set_bad_path_error(errno, bad_path);
1668 return(UNIXERROR(ERRDOS,ERRbadpath));
1670 } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
1671 DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
1672 set_bad_path_error(errno, bad_path);
1673 return(UNIXERROR(ERRDOS,ERRbadpath));
1676 delete_pending = fsp->directory_delete_on_close;
1678 } else {
1680 * Original code - this is an open file.
1682 CHECK_FSP(fsp,conn);
1684 fname = fsp->fsp_name;
1685 if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) {
1686 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1687 return(UNIXERROR(ERRDOS,ERRbadfid));
1690 if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1691 return(UNIXERROR(ERRDOS,ERRnoaccess));
1693 delete_pending = fsp->delete_on_close;
1695 } else {
1696 /* qpathinfo */
1697 if (total_params < 6)
1698 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1700 info_level = SVAL(params,0);
1702 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1704 fname = &fname1[0];
1705 pstrcpy(fname,&params[6]);
1707 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1709 unix_convert(fname,conn,0,&bad_path,&sbuf);
1710 if (!check_name(fname,conn)) {
1711 DEBUG(3,("call_trans2qfilepathinfo: check_name of %s failed (%s)\n",fname,strerror(errno)));
1712 set_bad_path_error(errno, bad_path);
1713 return(UNIXERROR(ERRDOS,ERRbadpath));
1715 if (INFO_LEVEL_IS_UNIX(info_level)) {
1716 /* Always do lstat for UNIX calls. */
1717 if (vfs_lstat(conn,fname,&sbuf)) {
1718 DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
1719 set_bad_path_error(errno, bad_path);
1720 return(UNIXERROR(ERRDOS,ERRbadpath));
1722 } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
1723 DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
1724 set_bad_path_error(errno, bad_path);
1725 return(UNIXERROR(ERRDOS,ERRbadpath));
1730 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
1731 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1733 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1734 fname,info_level,tran_call,total_data));
1736 p = strrchr(fname,'/');
1737 if (!p)
1738 p = fname;
1739 else
1740 p++;
1741 l = strlen(p);
1742 mode = dos_mode(conn,fname,&sbuf);
1743 fullpathname = fname;
1744 size = get_file_size(sbuf);
1745 allocation_size = get_allocation_size(fsp,&sbuf);
1746 if (mode & aDIR)
1747 size = 0;
1749 /* from now on we only want the part after the / */
1750 fname = p;
1752 params = Realloc(*pparams,2);
1753 if ( params == NULL )
1754 return ERROR_DOS(ERRDOS,ERRnomem);
1755 *pparams = params;
1756 memset((char *)params,'\0',2);
1757 data_size = max_data_bytes + 1024;
1758 pdata = Realloc(*ppdata, data_size);
1759 if ( pdata == NULL )
1760 return ERROR_DOS(ERRDOS,ERRnomem);
1761 *ppdata = pdata;
1763 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1764 /* uggh, EAs for OS2 */
1765 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1766 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1769 memset((char *)pdata,'\0',data_size);
1771 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1773 if (lp_dos_filetime_resolution(SNUM(conn))) {
1774 c_time &= ~1;
1775 sbuf.st_atime &= ~1;
1776 sbuf.st_mtime &= ~1;
1777 sbuf.st_mtime &= ~1;
1780 /* NT expects the name to be in an exact form */
1781 if (strequal(fname,"."))
1782 pstrcpy(dos_fname, "\\");
1783 else {
1784 snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname);
1785 string_replace( dos_fname, '/','\\');
1788 switch (info_level) {
1789 case SMB_INFO_STANDARD:
1790 case SMB_INFO_QUERY_EA_SIZE:
1791 data_size = (info_level==1?22:26);
1792 put_dos_date2(pdata,l1_fdateCreation,c_time);
1793 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1794 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1795 SIVAL(pdata,l1_cbFile,(uint32)size);
1796 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
1797 SSVAL(pdata,l1_attrFile,mode);
1798 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1799 break;
1801 case SMB_INFO_QUERY_EAS_FROM_LIST:
1802 data_size = 24;
1803 put_dos_date2(pdata,0,c_time);
1804 put_dos_date2(pdata,4,sbuf.st_atime);
1805 put_dos_date2(pdata,8,sbuf.st_mtime);
1806 SIVAL(pdata,12,(uint32)size);
1807 SIVAL(pdata,16,(uint32)allocation_size);
1808 SIVAL(pdata,20,mode);
1809 break;
1811 case SMB_INFO_QUERY_ALL_EAS:
1812 data_size = 4;
1813 SIVAL(pdata,0,data_size);
1814 break;
1816 case 6:
1817 return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */
1819 case SMB_FILE_BASIC_INFORMATION:
1820 case SMB_QUERY_FILE_BASIC_INFO:
1822 if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1823 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1824 else {
1825 data_size = 40;
1826 SIVAL(pdata,36,0);
1828 put_long_date(pdata,c_time);
1829 put_long_date(pdata+8,sbuf.st_atime);
1830 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1831 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1832 SIVAL(pdata,32,mode);
1834 DEBUG(5,("SMB_QFBI - "));
1837 time_t create_time = c_time;
1838 DEBUG(5,("create: %s ", ctime(&create_time)));
1841 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1842 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1843 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1844 DEBUG(5,("mode: %x\n", mode));
1846 break;
1848 case SMB_FILE_STANDARD_INFORMATION:
1849 case SMB_QUERY_FILE_STANDARD_INFO:
1851 data_size = 24;
1852 /* Fake up allocation size. */
1853 SOFF_T(pdata,0,allocation_size);
1854 SOFF_T(pdata,8,size);
1855 SIVAL(pdata,16,sbuf.st_nlink);
1856 SCVAL(pdata,20,0);
1857 SCVAL(pdata,21,(mode&aDIR)?1:0);
1858 break;
1860 case SMB_FILE_EA_INFORMATION:
1861 case SMB_QUERY_FILE_EA_INFO:
1862 data_size = 4;
1863 SIVAL(pdata,0,0);
1864 break;
1866 /* Get the 8.3 name - used if NT SMB was negotiated. */
1868 case SMB_QUERY_FILE_ALT_NAME_INFO:
1870 pstring short_name;
1871 pstrcpy(short_name,p);
1872 /* Mangle if not already 8.3 */
1873 if(!mangle_is_8_3(short_name, True)) {
1874 mangle_map(short_name,True,True,SNUM(conn));
1876 strupper(short_name);
1877 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1878 l = dos_PutUniCode(pdata + 4, short_name, sizeof(pstring), False);
1879 data_size = 4 + l;
1880 SIVAL(pdata,0,l);
1881 break;
1884 case SMB_QUERY_FILE_NAME_INFO:
1886 * The first part of this code is essential
1887 * to get security descriptors to work on mapped
1888 * drives. Don't ask how I discovered this unless
1889 * you like hearing about me suffering.... :-). JRA.
1892 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1893 l = dos_PutUniCode(pdata + 4, dos_fname,sizeof(pstring), False);
1894 data_size = 4 + l;
1895 SIVAL(pdata,0,l);
1896 break;
1898 case SMB_FILE_ALLOCATION_INFORMATION:
1899 case SMB_QUERY_FILE_ALLOCATION_INFO:
1900 data_size = 8;
1901 SOFF_T(pdata,0,allocation_size);
1902 break;
1904 case SMB_QUERY_FILE_END_OF_FILEINFO:
1905 case SMB_FILE_END_OF_FILE_INFORMATION:
1906 data_size = 8;
1907 SOFF_T(pdata,0,size);
1908 break;
1910 case SMB_QUERY_FILE_ALL_INFO:
1911 put_long_date(pdata,c_time);
1912 put_long_date(pdata+8,sbuf.st_atime);
1913 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1914 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1915 SIVAL(pdata,32,mode);
1916 pdata += 40;
1917 SOFF_T(pdata,0,allocation_size);
1918 SOFF_T(pdata,8,size);
1919 SIVAL(pdata,16,sbuf.st_nlink);
1920 SCVAL(pdata,20,delete_pending);
1921 SCVAL(pdata,21,(mode&aDIR)?1:0);
1922 pdata += 24;
1923 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);
1924 pdata += 8; /* index number */
1925 pdata += 4; /* EA info */
1926 if (mode & aRONLY)
1927 SIVAL(pdata,0,0xA9);
1928 else
1929 SIVAL(pdata,0,0xd01BF);
1930 pdata += 4;
1931 SOFF_T(pdata,0,pos); /* current offset */
1932 pdata += 8;
1933 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1934 pdata += 4;
1935 pdata += 4; /* alignment */
1936 SIVAL(pdata,0,l);
1937 pstrcpy(pdata+4,dos_fname);
1938 pdata += 4 + l;
1939 data_size = PTR_DIFF(pdata,(*ppdata));
1940 break;
1942 case SMB_FILE_INTERNAL_INFORMATION:
1943 /* This should be an index number - looks like dev/ino to me :-) */
1944 SIVAL(pdata,0,sbuf.st_dev);
1945 SIVAL(pdata,4,sbuf.st_ino);
1946 data_size = 8;
1947 break;
1949 case SMB_FILE_ACCESS_INFORMATION:
1950 SIVAL(pdata,0,0x12019F); /* ??? */
1951 data_size = 4;
1952 break;
1954 case SMB_FILE_NAME_INFORMATION:
1955 /* Pathname with leading '\'. */
1957 size_t byte_len;
1959 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1960 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
1961 SIVAL(pdata,0,byte_len);
1962 data_size = 4 + byte_len;
1963 break;
1966 case SMB_FILE_DISPOSITION_INFORMATION:
1967 data_size = 1;
1968 SCVAL(pdata,0,delete_pending);
1969 break;
1971 case SMB_FILE_POSITION_INFORMATION:
1972 data_size = 8;
1973 SOFF_T(pdata,0,pos);
1974 break;
1976 case SMB_FILE_MODE_INFORMATION:
1977 SIVAL(pdata,0,mode);
1978 data_size = 4;
1979 break;
1981 case SMB_FILE_ALIGNMENT_INFORMATION:
1982 SIVAL(pdata,0,0); /* No alignment needed. */
1983 data_size = 4;
1984 break;
1986 #if 0
1987 /* Not yet finished... JRA */
1988 case 1018:
1990 size_t byte_len;
1992 put_long_date(pdata,c_time);
1993 put_long_date(pdata+8,sbuf.st_atime);
1994 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1995 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1996 SIVAL(pdata,32,mode);
1997 SIVAL(pdata,36,0); /* ??? */
1998 SIVAL(pdata,40,0x20); /* ??? */
1999 SIVAL(pdata,44,0); /* ??? */
2000 SOFF_T(pdata,48,size);
2001 SIVAL(pdata,56,0x1); /* ??? */
2002 SIVAL(pdata,60,0); /* ??? */
2003 SIVAL(pdata,64,0); /* ??? */
2004 SIVAL(pdata,68,length); /* Following string length in bytes. */
2005 dos_PutUniCode(pdata+72,,False);
2006 break;
2008 #endif
2010 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2011 /* Last component of pathname. */
2013 size_t byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2014 SIVAL(pdata,0,byte_len);
2015 data_size = 4 + byte_len;
2016 break;
2019 #if 0
2021 * NT4 server just returns "invalid query" to this - if we try to answer
2022 * it then NTws gets a BSOD! (tridge).
2023 * W2K seems to want this. JRA.
2025 case SMB_QUERY_FILE_STREAM_INFO:
2026 #endif
2027 case SMB_FILE_STREAM_INFORMATION:
2028 if (mode & aDIR) {
2029 data_size = 0;
2030 } else {
2031 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 14, False);
2032 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
2033 SIVAL(pdata,0,0); /* Next stream (none). */
2034 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2035 SOFF_T(pdata,8,size);
2036 SOFF_T(pdata,16,allocation_size);
2037 data_size = 24 + byte_len;
2039 break;
2041 case SMB_FILE_COMPRESSION_INFORMATION:
2042 SOFF_T(pdata,0,size);
2043 SIVAL(pdata,8,0); /* ??? */
2044 SIVAL(pdata,12,0); /* ??? */
2045 data_size = 16;
2046 break;
2048 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2049 put_long_date(pdata,c_time);
2050 put_long_date(pdata+8,sbuf.st_atime);
2051 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2052 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2053 SOFF_T(pdata,32,allocation_size); /* Allocation size. */
2054 SOFF_T(pdata,40,size);
2055 SIVAL(pdata,48,mode);
2056 SIVAL(pdata,52,0); /* ??? */
2057 data_size = 56;
2058 break;
2060 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2061 SIVAL(pdata,0,mode);
2062 SIVAL(pdata,4,0);
2063 data_size = 8;
2064 break;
2067 * CIFS UNIX Extensions.
2070 case SMB_QUERY_FILE_UNIX_BASIC:
2072 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2074 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2075 pdata += 8;
2077 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2078 pdata += 8;
2080 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2081 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2082 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2083 pdata += 24;
2085 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2086 SIVAL(pdata,4,0);
2087 pdata += 8;
2089 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2090 SIVAL(pdata,4,0);
2091 pdata += 8;
2093 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2094 pdata += 4;
2096 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2097 SIVAL(pdata,4,0);
2098 pdata += 8;
2100 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2101 SIVAL(pdata,4,0);
2102 pdata += 8;
2104 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2105 pdata += 8;
2107 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2108 SIVAL(pdata,4,0);
2109 pdata += 8;
2111 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2112 SIVAL(pdata,4,0);
2113 pdata += 8+1;
2114 data_size = PTR_DIFF(pdata,(*ppdata));
2117 int i;
2118 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2120 for (i=0; i<100; i++)
2121 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2122 DEBUG(4,("\n"));
2125 break;
2127 case SMB_QUERY_FILE_UNIX_LINK:
2129 pstring buffer;
2130 int len;
2132 #ifdef S_ISLNK
2133 if(!S_ISLNK(sbuf.st_mode))
2134 return(UNIXERROR(ERRSRV,ERRbadlink));
2135 #else
2136 return(UNIXERROR(ERRDOS,ERRbadlink));
2137 #endif
2138 len = conn->vfs_ops.readlink(conn,dos_to_unix_static(fullpathname), buffer, sizeof(pstring)-1); /* read link */
2139 if (len == -1)
2140 return(UNIXERROR(ERRDOS,ERRnoaccess));
2141 buffer[len] = 0;
2142 unix_to_dos(buffer);
2143 pstrcpy(pdata,buffer); /* write '\0' terminated string */
2144 pdata += strlen(buffer)+1;
2145 data_size = PTR_DIFF(pdata,(*ppdata));
2147 break;
2150 default:
2151 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2154 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
2156 return(-1);
2159 /****************************************************************************
2160 Deal with the internal needs of setting the delete on close flag. Note that
2161 as the tdb locking is recursive, it is safe to call this from within
2162 open_file_shared. JRA.
2163 ****************************************************************************/
2165 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2168 * Only allow delete on close for writable shares.
2171 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2172 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2173 fsp->fsp_name ));
2174 return NT_STATUS_ACCESS_DENIED;
2177 * Only allow delete on close for files/directories opened with delete intent.
2180 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2181 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2182 fsp->fsp_name ));
2183 return NT_STATUS_ACCESS_DENIED;
2186 if(fsp->is_directory) {
2187 fsp->directory_delete_on_close = delete_on_close;
2188 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2189 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2190 } else {
2192 files_struct *iterate_fsp;
2195 * Modify the share mode entry for all files open
2196 * on this device and inode to tell other smbds we have
2197 * changed the delete on close flag. This will be noticed
2198 * in the close code, the last closer will delete the file
2199 * if flag is set.
2202 DEBUG(10,("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2203 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2205 if (lock_share_entry_fsp(fsp) == False)
2206 return NT_STATUS_ACCESS_DENIED;
2208 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2209 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2210 fsp->fsp_name ));
2211 unlock_share_entry_fsp(fsp);
2212 return NT_STATUS_ACCESS_DENIED;
2216 * Release the lock.
2219 unlock_share_entry_fsp(fsp);
2222 * Go through all files we have open on the same device and
2223 * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
2224 * Other smbd's that have this file open will look in the share_mode on close.
2225 * take care of this (rare) case in close_file(). See the comment there.
2226 * NB. JRA. We don't really need to do this anymore - all should be taken
2227 * care of in the share_mode changes in the tdb.
2230 for(iterate_fsp = file_find_di_first(fsp->dev, fsp->inode);
2231 iterate_fsp; iterate_fsp = file_find_di_next(iterate_fsp))
2232 fsp->delete_on_close = delete_on_close;
2235 * Set the delete on close flag in the fsp.
2237 fsp->delete_on_close = delete_on_close;
2239 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2240 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2244 return NT_STATUS_OK;
2247 /****************************************************************************
2248 Returns true if this pathname is within the share, and thus safe.
2249 ****************************************************************************/
2251 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2253 #ifdef PATH_MAX
2254 char resolved_name[PATH_MAX+1];
2255 #else
2256 pstring resolved_name;
2257 #endif
2258 fstring last_component;
2259 pstring link_dest;
2260 pstring link_test;
2261 char *p;
2262 BOOL bad_path = False;
2263 SMB_STRUCT_STAT sbuf;
2265 pstrcpy(link_dest, link_dest_in);
2266 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2268 /* Store the UNIX converted path. */
2269 pstrcpy(link_dest_out, link_dest);
2271 p = strrchr(link_dest, '/');
2272 if (p) {
2273 fstrcpy(last_component, p+1);
2274 *p = '\0';
2275 } else {
2276 fstrcpy(last_component, link_dest);
2277 pstrcpy(link_dest, "./");
2280 if (conn->vfs_ops.realpath(conn,dos_to_unix_static(link_dest),resolved_name) == NULL)
2281 return -1;
2283 pstrcpy(link_dest, unix_to_dos_static(resolved_name));
2284 pstrcat(link_dest, "/");
2285 pstrcat(link_dest, last_component);
2287 if (*link_dest != '/') {
2288 /* Relative path. */
2289 pstrcpy(link_test, conn->connectpath);
2290 pstrcat(link_test, "/");
2291 pstrcat(link_test, link_dest);
2292 } else {
2293 pstrcpy(link_test, link_dest);
2297 * Check if the link is within the share.
2300 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2301 errno = EACCES;
2302 return -1;
2304 return 0;
2307 /****************************************************************************
2308 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2309 ****************************************************************************/
2311 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2312 char **pparams, int total_params, char **ppdata, int total_data)
2314 char *params = *pparams;
2315 char *pdata = *ppdata;
2316 uint16 tran_call = SVAL(inbuf, smb_setup0);
2317 uint16 info_level;
2318 int dosmode = 0;
2319 SMB_OFF_T size=0;
2320 struct utimbuf tvs;
2321 SMB_STRUCT_STAT sbuf;
2322 pstring fname1;
2323 char *fname = NULL;
2324 int fd = -1;
2325 BOOL bad_path = False;
2326 files_struct *fsp = NULL;
2327 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2328 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2329 mode_t unixmode = 0;
2331 if (tran_call == TRANSACT2_SETFILEINFO) {
2333 if (total_params < 4)
2334 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2336 fsp = file_fsp(params,0);
2337 info_level = SVAL(params,2);
2339 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2341 * This is actually a SETFILEINFO on a directory
2342 * handle (returned from an NT SMB). NT5.0 seems
2343 * to do this call. JRA.
2345 fname = fsp->fsp_name;
2346 unix_convert(fname,conn,0,&bad_path,&sbuf);
2347 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2348 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2349 set_bad_path_error(errno, bad_path);
2350 return(UNIXERROR(ERRDOS,ERRbadpath));
2352 } else if (fsp && fsp->print_file) {
2354 * Doing a DELETE_ON_CLOSE should cancel a print job.
2356 if (((info_level == SMB_SET_FILE_DISPOSITION_INFO)||(info_level == SMB_FILE_DISPOSITION_INFORMATION)) &&
2357 CVAL(pdata,0)) {
2358 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2360 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n",
2361 fsp->fsp_name ));
2363 SSVAL(params,0,0);
2364 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2365 return(-1);
2366 } else
2367 return(UNIXERROR(ERRDOS,ERRbadpath));
2368 } else {
2370 * Original code - this is an open file.
2372 CHECK_FSP(fsp,conn);
2374 fname = fsp->fsp_name;
2375 fd = fsp->fd;
2377 if (vfs_fstat(fsp,fd,&sbuf) != 0) {
2378 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2379 return(UNIXERROR(ERRDOS,ERRbadfid));
2382 } else {
2383 /* set path info */
2384 if (total_params < 6)
2385 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2387 info_level = SVAL(params,0);
2388 fname = fname1;
2389 pstrcpy(fname,&params[6]);
2390 unix_convert(fname,conn,0,&bad_path,&sbuf);
2391 if(!check_name(fname, conn)) {
2392 set_bad_path_error(errno, bad_path);
2393 return(UNIXERROR(ERRDOS,ERRbadpath));
2397 * For CIFS UNIX extensions the target name may not exist.
2400 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2402 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
2403 set_bad_path_error(errno, bad_path);
2404 return(UNIXERROR(ERRDOS,ERRbadpath));
2408 if (!CAN_WRITE(conn))
2409 return ERROR_DOS(ERRSRV,ERRaccess);
2411 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2412 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2414 if (VALID_STAT(sbuf))
2415 unixmode = sbuf.st_mode;
2417 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
2418 tran_call,fname,info_level,total_data));
2420 /* Realloc the parameter and data sizes */
2421 params = Realloc(*pparams,2);
2422 if(params == NULL)
2423 return ERROR_DOS(ERRDOS,ERRnomem);
2424 *pparams = params;
2426 SSVAL(params,0,0);
2428 if (fsp) {
2429 /* the pending modtime overrides the current modtime */
2430 sbuf.st_mtime = fsp->pending_modtime;
2433 size = get_file_size(sbuf);
2434 tvs.modtime = sbuf.st_mtime;
2435 tvs.actime = sbuf.st_atime;
2436 dosmode = dos_mode(conn,fname,&sbuf);
2437 unixmode = sbuf.st_mode;
2439 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2440 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2442 switch (info_level) {
2443 case SMB_INFO_STANDARD:
2445 if (total_data < l1_cbFile+4)
2446 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2448 /* access time */
2449 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2451 /* write time */
2452 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2454 dosmode = SVAL(pdata,l1_attrFile);
2455 size = IVAL(pdata,l1_cbFile);
2456 break;
2459 case SMB_INFO_SET_EA:
2460 return(ERROR_DOS(ERRDOS,ERReasnotsupported));
2462 /* XXXX um, i don't think this is right.
2463 it's also not in the cifs6.txt spec.
2465 case SMB_INFO_QUERY_EAS_FROM_LIST:
2466 if (total_data < 28)
2467 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2469 tvs.actime = make_unix_date2(pdata+8);
2470 tvs.modtime = make_unix_date2(pdata+12);
2471 size = IVAL(pdata,16);
2472 dosmode = IVAL(pdata,24);
2473 break;
2475 /* XXXX nor this. not in cifs6.txt, either. */
2476 case SMB_INFO_QUERY_ALL_EAS:
2477 if (total_data < 28)
2478 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2480 tvs.actime = make_unix_date2(pdata+8);
2481 tvs.modtime = make_unix_date2(pdata+12);
2482 size = IVAL(pdata,16);
2483 dosmode = IVAL(pdata,24);
2484 break;
2486 case SMB_SET_FILE_BASIC_INFO:
2487 case SMB_FILE_BASIC_INFORMATION:
2489 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2490 time_t write_time;
2491 time_t changed_time;
2493 if (total_data < 36)
2494 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2496 /* Ignore create time at offset pdata. */
2498 /* access time */
2499 tvs.actime = interpret_long_date(pdata+8);
2501 write_time = interpret_long_date(pdata+16);
2502 changed_time = interpret_long_date(pdata+24);
2504 tvs.modtime = MIN(write_time, changed_time);
2506 if (write_time > tvs.modtime && write_time != 0xffffffff) {
2507 tvs.modtime = write_time;
2510 /* Prefer a defined time to an undefined one. */
2511 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2512 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2513 ? changed_time
2514 : write_time);
2516 /* attributes */
2517 dosmode = IVAL(pdata,32);
2518 break;
2521 case SMB_FILE_ALLOCATION_INFORMATION:
2522 case SMB_SET_FILE_ALLOCATION_INFO:
2524 int ret = -1;
2525 SMB_OFF_T allocation_size;
2527 if (total_data < 8)
2528 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2530 allocation_size = IVAL(pdata,0);
2531 #ifdef LARGE_SMB_OFF_T
2532 allocation_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2533 #else /* LARGE_SMB_OFF_T */
2534 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2535 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2536 #endif /* LARGE_SMB_OFF_T */
2537 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2538 fname, (double)allocation_size ));
2540 if (allocation_size)
2541 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
2543 if(allocation_size != get_file_size(sbuf)) {
2544 SMB_STRUCT_STAT new_sbuf;
2546 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2547 fname, (double)allocation_size ));
2549 if (fd == -1) {
2550 files_struct *new_fsp = NULL;
2551 int access_mode = 0;
2552 int action = 0;
2554 if(global_oplock_break) {
2555 /* Queue this file modify as we are the process of an oplock break. */
2557 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2558 DEBUGADD(2,( "in oplock break state.\n"));
2560 push_oplock_pending_smb_message(inbuf, length);
2561 return -1;
2564 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2565 SET_OPEN_MODE(DOS_OPEN_RDWR),
2566 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2567 0, 0, &access_mode, &action);
2569 if (new_fsp == NULL)
2570 return(UNIXERROR(ERRDOS,ERRbadpath));
2571 ret = vfs_allocate_file_space(new_fsp, allocation_size);
2572 if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2573 DEBUG(3,("fstat of fnum %d failed (%s)\n",new_fsp->fnum, strerror(errno)));
2574 ret = -1;
2576 close_file(new_fsp,True);
2577 } else {
2578 ret = vfs_allocate_file_space(fsp, allocation_size);
2579 if (vfs_fstat(fsp,fd,&new_sbuf) != 0) {
2580 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2581 ret = -1;
2584 if (ret == -1)
2585 return ERROR_NT(NT_STATUS_DISK_FULL);
2587 /* Allocate can trucate size... */
2588 size = get_file_size(new_sbuf);
2591 break;
2594 case SMB_FILE_END_OF_FILE_INFORMATION:
2595 case SMB_SET_FILE_END_OF_FILE_INFO:
2597 if (total_data < 8)
2598 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2600 size = IVAL(pdata,0);
2601 #ifdef LARGE_SMB_OFF_T
2602 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2603 #else /* LARGE_SMB_OFF_T */
2604 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2605 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2606 #endif /* LARGE_SMB_OFF_T */
2607 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2608 break;
2611 case SMB_FILE_DISPOSITION_INFORMATION:
2612 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2614 BOOL delete_on_close;
2615 NTSTATUS status;
2617 if (total_data < 1)
2618 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2620 delete_on_close = (CVAL(pdata,0) ? True : False);
2622 if (tran_call != TRANSACT2_SETFILEINFO)
2623 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
2625 if (fsp == NULL)
2626 return(UNIXERROR(ERRDOS,ERRbadfid));
2628 status = set_delete_on_close_internal(fsp, delete_on_close);
2630 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2631 return ERROR_NT(status);
2633 break;
2637 * CIFS UNIX extensions.
2640 case SMB_SET_FILE_UNIX_BASIC:
2642 uint32 raw_unixmode;
2644 if (total_data < 100)
2645 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2647 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
2648 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
2649 size=IVAL(pdata,0); /* first 8 Bytes are size */
2650 #ifdef LARGE_SMB_OFF_T
2651 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2652 #else /* LARGE_SMB_OFF_T */
2653 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2654 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2655 #endif /* LARGE_SMB_OFF_T */
2657 pdata+=24; /* ctime & st_blocks are not changed */
2658 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
2659 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
2660 pdata+=16;
2661 set_owner = (uid_t)IVAL(pdata,0);
2662 pdata += 8;
2663 set_grp = (gid_t)IVAL(pdata,0);
2664 pdata += 8;
2665 raw_unixmode = IVAL(pdata,28);
2666 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2667 dosmode = 0; /* Ensure dos mode change doesn't override this. */
2669 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2670 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2671 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2673 if (!VALID_STAT(sbuf)) {
2676 * The only valid use of this is to create character and block
2677 * devices, and named pipes. This is deprecated (IMHO) and
2678 * a new info level should be used for mknod. JRA.
2681 #if !defined(HAVE_MAKEDEV_FN)
2682 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2683 #else /* HAVE_MAKEDEV_FN */
2684 uint32 file_type = IVAL(pdata,0);
2685 uint32 dev_major = IVAL(pdata,4);
2686 uint32 dev_minor = IVAL(pdata,12);
2688 uid_t myuid = geteuid();
2689 gid_t mygid = getegid();
2690 SMB_DEV_T dev;
2692 if (tran_call == TRANSACT2_SETFILEINFO)
2693 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2695 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2696 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2698 dev = makedev(dev_major, dev_minor);
2700 /* We can only create as the owner/group we are. */
2702 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2703 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2704 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2705 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2707 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2708 file_type != UNIX_TYPE_FIFO)
2709 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2711 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2712 0%o for file %s\n", (double)dev, unixmode, fname ));
2714 /* Ok - do the mknod. */
2715 if (conn->vfs_ops.mknod(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
2716 return(UNIXERROR(ERRDOS,ERRnoaccess));
2718 SSVAL(params,0,0);
2719 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2720 return(-1);
2721 #endif /* HAVE_MAKEDEV_FN */
2726 * Deal with the UNIX specific mode set.
2729 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
2730 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2731 (unsigned int)unixmode, fname ));
2732 if (vfs_chmod(conn,fname,unixmode) != 0)
2733 return(UNIXERROR(ERRDOS,ERRnoaccess));
2737 * Deal with the UNIX specific uid set.
2740 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
2741 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2742 (unsigned int)set_owner, fname ));
2743 if (vfs_chown(conn,fname,set_owner, (gid_t)-1) != 0)
2744 return(UNIXERROR(ERRDOS,ERRnoaccess));
2748 * Deal with the UNIX specific gid set.
2751 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
2752 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2753 (unsigned int)set_owner, fname ));
2754 if (vfs_chown(conn,fname,(uid_t)-1, set_grp) != 0)
2755 return(UNIXERROR(ERRDOS,ERRnoaccess));
2757 break;
2760 case SMB_SET_FILE_UNIX_LINK:
2762 pstring link_dest;
2763 /* Set a symbolic link. */
2764 /* Don't allow this if follow links is false. */
2766 if (!lp_symlinks(SNUM(conn)))
2767 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2769 /* Disallow if already exists. */
2770 if (VALID_STAT(sbuf))
2771 return(ERROR_DOS(ERRDOS,ERRbadpath));
2773 pstrcpy(link_dest, pdata);
2775 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2776 return(UNIXERROR(ERRDOS,ERRnoaccess));
2777 dos_to_unix(link_dest);
2778 dos_to_unix(fname);
2780 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2781 fname, link_dest ));
2783 if (conn->vfs_ops.symlink(conn,link_dest,fname) != 0)
2784 return(UNIXERROR(ERRDOS,ERRnoaccess));
2785 SSVAL(params,0,0);
2786 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2787 return(-1);
2790 case SMB_SET_FILE_UNIX_HLINK:
2792 pstring link_dest;
2794 /* Set a hard link. */
2796 /* Disallow if already exists. */
2797 if (VALID_STAT(sbuf))
2798 return(ERROR_DOS(ERRDOS,ERRbadpath));
2800 pstrcpy(link_dest, pdata);
2802 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2803 return(UNIXERROR(ERRDOS,ERRnoaccess));
2805 dos_to_unix(link_dest);
2806 dos_to_unix(fname);
2808 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2809 fname, link_dest ));
2811 if (conn->vfs_ops.link(conn,link_dest,fname) != 0)
2812 return(UNIXERROR(ERRDOS,ERRnoaccess));
2813 SSVAL(params,0,0);
2814 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2815 return(-1);
2818 default:
2819 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2822 /* get some defaults (no modifications) if any info is zero or -1. */
2823 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2824 tvs.actime = sbuf.st_atime;
2826 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2827 tvs.modtime = sbuf.st_mtime;
2829 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2830 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2831 DEBUG(6,("size: %.0f ", (double)size));
2832 if (S_ISDIR(sbuf.st_mode))
2833 dosmode |= aDIR;
2834 else
2835 dosmode &= ~aDIR;
2837 DEBUG(6,("dosmode: %x\n" , dosmode));
2839 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2840 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2841 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2842 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2844 * Only do this test if we are not explicitly
2845 * changing the size of a file.
2847 if (!size)
2848 size = get_file_size(sbuf);
2852 * Try and set the times, size and mode of this file -
2853 * if they are different from the current values
2856 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2857 if(fsp != NULL) {
2859 * This was a setfileinfo on an open file.
2860 * NT does this a lot. It's actually pointless
2861 * setting the time here, as it will be overwritten
2862 * on the next write, so we save the request
2863 * away and will set it on file close. JRA.
2866 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2867 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n",
2868 ctime(&tvs.modtime) ));
2869 fsp->pending_modtime = tvs.modtime;
2872 } else {
2874 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2876 if(file_utime(conn, fname, &tvs)!=0)
2877 return(UNIXERROR(ERRDOS,ERRnoaccess));
2881 /* check the mode isn't different, before changing it */
2882 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
2884 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n",
2885 fname, dosmode ));
2887 if(file_chmod(conn, fname, dosmode, NULL)) {
2888 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2889 return(UNIXERROR(ERRDOS,ERRnoaccess));
2893 if(size != get_file_size(sbuf)) {
2895 int ret;
2897 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2898 fname, (double)size ));
2900 if (fd == -1) {
2901 files_struct *new_fsp = NULL;
2902 int access_mode = 0;
2903 int action = 0;
2905 if(global_oplock_break) {
2906 /* Queue this file modify as we are the process of an oplock break. */
2908 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2909 DEBUGADD(2,( "in oplock break state.\n"));
2911 push_oplock_pending_smb_message(inbuf, length);
2912 return -1;
2915 new_fsp = open_file_shared(conn, fname, &sbuf,
2916 SET_OPEN_MODE(DOS_OPEN_RDWR),
2917 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2918 0, 0, &access_mode, &action);
2920 if (new_fsp == NULL)
2921 return(UNIXERROR(ERRDOS,ERRbadpath));
2922 ret = vfs_set_filelen(new_fsp, size);
2923 close_file(new_fsp,True);
2924 } else {
2925 ret = vfs_set_filelen(fsp, size);
2928 if (ret == -1)
2929 return (UNIXERROR(ERRHRD,ERRdiskfull));
2932 SSVAL(params,0,0);
2933 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2934 return(-1);
2937 /****************************************************************************
2938 Reply to a TRANS2_MKDIR (make directory with extended attributes).
2939 ****************************************************************************/
2941 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2942 char **pparams, int total_params, char **ppdata, int total_data)
2944 char *params = *pparams;
2945 pstring directory;
2946 int ret = -1;
2947 SMB_STRUCT_STAT sbuf;
2948 BOOL bad_path = False;
2950 if (!CAN_WRITE(conn))
2951 return ERROR_DOS(ERRSRV,ERRaccess);
2953 if (total_params < 4)
2954 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2956 pstrcpy(directory, &params[4]);
2958 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
2960 unix_convert(directory,conn,0,&bad_path,&sbuf);
2961 if (check_name(directory,conn))
2962 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2964 if(ret < 0) {
2965 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
2966 set_bad_path_error(errno, bad_path);
2967 return(UNIXERROR(ERRDOS,ERRnoaccess));
2970 /* Realloc the parameter and data sizes */
2971 params = Realloc(*pparams,2);
2972 if(params == NULL)
2973 return ERROR_DOS(ERRDOS,ERRnomem);
2974 *pparams = params;
2976 SSVAL(params,0,0);
2978 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2980 return(-1);
2983 /****************************************************************************
2984 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
2985 We don't actually do this - we just send a null response.
2986 ****************************************************************************/
2988 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2989 char **pparams, int total_params, char **ppdata, int total_data)
2991 static uint16 fnf_handle = 257;
2992 char *params = *pparams;
2993 uint16 info_level;
2995 if (total_params < 6)
2996 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2998 info_level = SVAL(params,4);
2999 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3001 switch (info_level) {
3002 case 1:
3003 case 2:
3004 break;
3005 default:
3006 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3009 /* Realloc the parameter and data sizes */
3010 params = Realloc(*pparams,6);
3011 if(params == NULL)
3012 return ERROR_DOS(ERRDOS,ERRnomem);
3013 *pparams = params;
3015 SSVAL(params,0,fnf_handle);
3016 SSVAL(params,2,0); /* No changes */
3017 SSVAL(params,4,0); /* No EA errors */
3019 fnf_handle++;
3021 if(fnf_handle == 0)
3022 fnf_handle = 257;
3024 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3026 return(-1);
3029 /****************************************************************************
3030 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3031 changes). Currently this does nothing.
3032 ****************************************************************************/
3034 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3035 char **pparams, int total_params, char **ppdata, int total_data)
3037 char *params = *pparams;
3039 DEBUG(3,("call_trans2findnotifynext\n"));
3041 /* Realloc the parameter and data sizes */
3042 params = Realloc(*pparams,4);
3043 if(params == NULL)
3044 return ERROR_DOS(ERRDOS,ERRnomem);
3045 *pparams = params;
3047 SSVAL(params,0,0); /* No changes */
3048 SSVAL(params,2,0); /* No EA errors */
3050 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3052 return(-1);
3055 /****************************************************************************
3056 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3057 ****************************************************************************/
3059 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
3060 char **pparams, int total_params, char **ppdata, int total_data)
3062 char *params = *pparams;
3063 enum remote_arch_types ra_type = get_remote_arch();
3064 BOOL NT_arch = ((ra_type == RA_WINNT) || (ra_type == RA_WIN2K));
3065 pstring pathname;
3066 int reply_size = 0;
3067 int max_referral_level;
3069 DEBUG(10,("call_trans2getdfsreferral\n"));
3071 if (total_params < 2)
3072 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3074 max_referral_level = SVAL(params,0);
3076 if(!lp_host_msdfs())
3077 return ERROR_DOS(ERRDOS,ERRbadfunc);
3079 /* if pathname is in UNICODE, convert to DOS */
3080 /* NT always sends in UNICODE, may not set UNICODE flag */
3081 if(NT_arch || (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS)) {
3082 unistr_to_dos(pathname, &params[2], sizeof(pathname));
3083 DEBUG(10,("UNICODE referral for %s\n",pathname));
3084 } else
3085 pstrcpy(pathname,&params[2]);
3087 if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
3088 return ERROR_DOS(ERRDOS,ERRbadfile);
3090 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_UNICODE_STRINGS | FLAGS2_DFS_PATHNAMES);
3091 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3093 return(-1);
3096 #define LMCAT_SPL 0x53
3097 #define LMFUNC_GETJOBID 0x60
3099 /****************************************************************************
3100 reply to a TRANS2_IOCTL - used for OS/2 printing.
3101 ****************************************************************************/
3103 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
3104 char **pparams, int total_params, char **ppdata, int total_data)
3106 char *pdata = *ppdata;
3107 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3109 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3110 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3111 pdata = Realloc(*ppdata, 32);
3112 if(pdata == NULL)
3113 return ERROR_DOS(ERRDOS,ERRnomem);
3114 *ppdata = pdata;
3116 SSVAL(pdata,0,fsp->print_jobid); /* Job number */
3117 StrnCpy(pdata+2, global_myname, 15); /* Our NetBIOS name */
3118 StrnCpy(pdata+18, lp_servicename(SNUM(conn)), 13); /* Service name */
3119 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3120 return(-1);
3121 } else {
3122 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3123 return ERROR_DOS(ERRSRV,ERRerror);
3127 /****************************************************************************
3128 Reply to a SMBfindclose (stop trans2 directory search).
3129 ****************************************************************************/
3131 int reply_findclose(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3133 int outsize = 0;
3134 int dptr_num=SVALS(inbuf,smb_vwv0);
3135 START_PROFILE(SMBfindclose);
3137 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3139 dptr_close(&dptr_num);
3141 outsize = set_message(outbuf,0,0,True);
3143 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3145 END_PROFILE(SMBfindclose);
3146 return(outsize);
3149 /****************************************************************************
3150 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3151 ****************************************************************************/
3153 int reply_findnclose(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3155 int outsize = 0;
3156 int dptr_num= -1;
3157 START_PROFILE(SMBfindnclose);
3159 dptr_num = SVAL(inbuf,smb_vwv0);
3161 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3163 /* We never give out valid handles for a
3164 findnotifyfirst - so any dptr_num is ok here.
3165 Just ignore it. */
3167 outsize = set_message(outbuf,0,0,True);
3169 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3171 END_PROFILE(SMBfindnclose);
3172 return(outsize);
3175 /****************************************************************************
3176 Reply to a SMBtranss2 - just ignore it!
3177 ****************************************************************************/
3179 int reply_transs2(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3181 START_PROFILE(SMBtranss2);
3182 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3183 END_PROFILE(SMBtranss2);
3184 return(-1);
3187 /****************************************************************************
3188 Reply to a SMBtrans2.
3189 ****************************************************************************/
3191 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3193 int outsize = 0;
3194 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3195 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3196 #if 0
3197 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3198 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3199 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3200 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3201 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3202 int32 timeout = IVALS(inbuf,smb_timeout);
3203 #endif
3204 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3205 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3206 char *params = NULL, *data = NULL;
3207 int num_params, num_params_sofar, num_data, num_data_sofar;
3208 START_PROFILE(SMBtrans2);
3210 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3211 /* Queue this open message as we are the process of an
3212 * oplock break. */
3214 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3215 DEBUGADD(2,( "in oplock break state.\n"));
3217 push_oplock_pending_smb_message(inbuf, length);
3218 END_PROFILE(SMBtrans2);
3219 return -1;
3222 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3223 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3224 END_PROFILE(SMBtrans2);
3225 return ERROR_DOS(ERRSRV,ERRaccess);
3228 outsize = set_message(outbuf,0,0,True);
3230 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3231 is so as a sanity check */
3232 if (suwcnt != 1) {
3234 * Need to have rc=0 for ioctl to get job id for OS/2.
3235 * Network printing will fail if function is not successful.
3236 * Similar function in reply.c will be used if protocol
3237 * is LANMAN1.0 instead of LM1.2X002.
3238 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3239 * outbuf doesn't have to be set(only job id is used).
3241 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3242 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3243 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3244 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3245 } else {
3246 DEBUG(2,("Invalid smb_sucnt in trans2 call(%d)\n",suwcnt));
3247 DEBUG(2,("Transaction is %d\n",tran_call));
3248 END_PROFILE(SMBtrans2);
3249 return ERROR_DOS(ERRSRV,ERRerror);
3253 /* Allocate the space for the maximum needed parameters and data */
3254 if (total_params > 0)
3255 params = (char *)malloc(total_params);
3256 if (total_data > 0)
3257 data = (char *)malloc(total_data);
3259 if ((total_params && !params) || (total_data && !data)) {
3260 DEBUG(2,("Out of memory in reply_trans2\n"));
3261 SAFE_FREE(params);
3262 SAFE_FREE(data);
3263 END_PROFILE(SMBtrans2);
3264 return ERROR_DOS(ERRDOS,ERRnomem);
3267 /* Copy the param and data bytes sent with this request into
3268 the params buffer */
3269 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3270 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3272 if (num_params > total_params || num_data > total_data)
3273 exit_server("invalid params in reply_trans2");
3275 if(params)
3276 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
3277 if(data)
3278 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
3280 if(num_data_sofar < total_data || num_params_sofar < total_params) {
3281 /* We need to send an interim response then receive the rest
3282 of the parameter/data bytes */
3283 outsize = set_message(outbuf,0,0,True);
3284 if (!send_smb(smbd_server_fd(),outbuf))
3285 exit_server("reply_trans2: send_smb failed.");
3287 while (num_data_sofar < total_data ||
3288 num_params_sofar < total_params) {
3289 BOOL ret;
3291 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3293 if ((ret &&
3294 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3295 outsize = set_message(outbuf,0,0,True);
3296 if(ret)
3297 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3298 else
3299 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3300 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3301 SAFE_FREE(params);
3302 SAFE_FREE(data);
3303 END_PROFILE(SMBtrans2);
3304 return ERROR_DOS(ERRSRV,ERRerror);
3307 /* Revise total_params and total_data in case
3308 they have changed downwards */
3309 total_params = SVAL(inbuf, smb_tpscnt);
3310 total_data = SVAL(inbuf, smb_tdscnt);
3311 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
3312 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
3313 if (num_params_sofar > total_params || num_data_sofar > total_data)
3314 exit_server("data overflow in trans2");
3316 memcpy( &params[ SVAL(inbuf, smb_spsdisp)],
3317 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
3318 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
3319 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
3323 if (Protocol >= PROTOCOL_NT1)
3324 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_IS_LONG_NAME);
3326 /* Now we must call the relevant TRANS2 function */
3327 switch(tran_call) {
3328 case TRANSACT2_OPEN:
3329 START_PROFILE_NESTED(Trans2_open);
3330 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
3331 &params, total_params, &data, total_data);
3332 END_PROFILE_NESTED(Trans2_open);
3333 break;
3335 case TRANSACT2_FINDFIRST:
3336 START_PROFILE_NESTED(Trans2_findfirst);
3337 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3338 &params, total_params, &data, total_data);
3339 END_PROFILE_NESTED(Trans2_findfirst);
3340 break;
3342 case TRANSACT2_FINDNEXT:
3343 START_PROFILE_NESTED(Trans2_findnext);
3344 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
3345 &params, total_params, &data, total_data);
3346 END_PROFILE_NESTED(Trans2_findnext);
3347 break;
3349 case TRANSACT2_QFSINFO:
3350 START_PROFILE_NESTED(Trans2_qfsinfo);
3351 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3352 &params, total_params, &data, total_data);
3353 END_PROFILE_NESTED(Trans2_qfsinfo);
3354 break;
3356 case TRANSACT2_SETFSINFO:
3357 START_PROFILE_NESTED(Trans2_setfsinfo);
3358 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
3359 &params, total_params, &data, total_data);
3360 END_PROFILE_NESTED(Trans2_setfsinfo);
3361 break;
3363 case TRANSACT2_QPATHINFO:
3364 case TRANSACT2_QFILEINFO:
3365 START_PROFILE_NESTED(Trans2_qpathinfo);
3366 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3367 &params, total_params, &data, total_data);
3368 END_PROFILE_NESTED(Trans2_qpathinfo);
3369 break;
3370 case TRANSACT2_SETPATHINFO:
3371 case TRANSACT2_SETFILEINFO:
3372 START_PROFILE_NESTED(Trans2_setpathinfo);
3373 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3374 &params, total_params, &data, total_data);
3375 END_PROFILE_NESTED(Trans2_setpathinfo);
3376 break;
3378 case TRANSACT2_FINDNOTIFYFIRST:
3379 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3380 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
3381 &params, total_params, &data, total_data);
3382 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3383 break;
3385 case TRANSACT2_FINDNOTIFYNEXT:
3386 START_PROFILE_NESTED(Trans2_findnotifynext);
3387 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
3388 &params, total_params, &data, total_data);
3389 END_PROFILE_NESTED(Trans2_findnotifynext);
3390 break;
3391 case TRANSACT2_MKDIR:
3392 START_PROFILE_NESTED(Trans2_mkdir);
3393 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3394 &params, total_params, &data, total_data);
3395 END_PROFILE_NESTED(Trans2_mkdir);
3396 break;
3398 case TRANSACT2_GET_DFS_REFERRAL:
3399 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3400 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3401 &params, total_params, &data, total_data);
3402 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3403 break;
3404 case TRANSACT2_IOCTL:
3405 START_PROFILE_NESTED(Trans2_ioctl);
3406 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3407 &params, total_params, &data, total_data);
3408 END_PROFILE_NESTED(Trans2_ioctl);
3409 break;
3410 default:
3411 /* Error in request */
3412 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3413 SAFE_FREE(params);
3414 SAFE_FREE(data);
3415 END_PROFILE(SMBtrans2);
3416 return ERROR_DOS(ERRSRV,ERRerror);
3419 /* As we do not know how many data packets will need to be
3420 returned here the various call_trans2xxxx calls
3421 must send their own. Thus a call_trans2xxx routine only
3422 returns a value other than -1 when it wants to send
3423 an error packet.
3426 SAFE_FREE(params);
3427 SAFE_FREE(data);
3428 END_PROFILE(SMBtrans2);
3429 return outsize; /* If a correct response was needed the
3430 call_trans2xxx calls have already sent
3431 it. If outsize != -1 then it is returning */