syncing with release branch (includes trans2 fixes)
[Samba.git] / source / smbd / trans2.c
blob36e371dc2c8379b97f2f735482219a24d7f1d487
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_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
40 SMB_BIG_UINT ret;
41 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
42 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
43 #else
44 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
45 #endif
46 if (!ret && fsp && fsp->initial_allocation_size)
47 ret = fsp->initial_allocation_size;
48 ret = SMB_ROUNDUP(ret,SMB_ROUNDUP_ALLOCATION_SIZE);
49 return ret;
52 /****************************************************************************
53 Send the required number of replies back.
54 We assume all fields other than the data fields are
55 set correctly for the type of call.
56 HACK ! Always assumes smb_setup field is zero.
57 ****************************************************************************/
59 static int send_trans2_replies(char *outbuf, int bufsize, char *params, int paramsize, char *pdata, int datasize)
61 /* As we are using a protocol > LANMAN1 then the max_send
62 variable must have been set in the sessetupX call.
63 This takes precedence over the max_xmit field in the
64 global struct. These different max_xmit variables should
65 be merged as this is now too confusing */
67 extern int max_send;
68 int data_to_send = datasize;
69 int params_to_send = paramsize;
70 int useable_space;
71 char *pp = params;
72 char *pd = pdata;
73 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
74 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
75 int data_alignment_offset = 0;
77 /* Initially set the wcnt area to be 10 - this is true for all
78 trans2 replies */
79 set_message(outbuf,10,0,True);
81 /* If there genuinely are no parameters or data to send just send
82 the empty packet */
84 if(params_to_send == 0 && data_to_send == 0) {
85 if (!send_smb(smbd_server_fd(),outbuf))
86 exit_server("send_trans2_replies: send_smb failed.");
87 return 0;
90 /* When sending params and data ensure that both are nicely aligned */
91 /* Only do this alignment when there is also data to send - else
92 can cause NT redirector problems. */
94 if (((params_to_send % 4) != 0) && (data_to_send != 0))
95 data_alignment_offset = 4 - (params_to_send % 4);
97 /* Space is bufsize minus Netbios over TCP header minus SMB header */
98 /* The alignment_offset is to align the param bytes on an even byte
99 boundary. NT 4.0 Beta needs this to work correctly. */
101 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
103 /* useable_space can never be more than max_send minus the alignment offset. */
105 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
108 while (params_to_send || data_to_send) {
109 /* Calculate whether we will totally or partially fill this packet */
111 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
113 /* We can never send more than useable_space */
115 * Note that 'useable_space' does not include the alignment offsets,
116 * but we must include the alignment offsets in the calculation of
117 * the length of the data we send over the wire, as the alignment offsets
118 * are sent here. Fix from Marc_Jacobsen@hp.com.
121 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
123 set_message(outbuf, 10, total_sent_thistime, True);
125 /* Set total params and data to be sent */
126 SSVAL(outbuf,smb_tprcnt,paramsize);
127 SSVAL(outbuf,smb_tdrcnt,datasize);
129 /* Calculate how many parameters and data we can fit into
130 this packet. Parameters get precedence */
132 params_sent_thistime = MIN(params_to_send,useable_space);
133 data_sent_thistime = useable_space - params_sent_thistime;
134 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
136 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
138 /* smb_proff is the offset from the start of the SMB header to the
139 parameter bytes, however the first 4 bytes of outbuf are
140 the Netbios over TCP header. Thus use smb_base() to subtract
141 them from the calculation */
143 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
145 if(params_sent_thistime == 0)
146 SSVAL(outbuf,smb_prdisp,0);
147 else
148 /* Absolute displacement of param bytes sent in this packet */
149 SSVAL(outbuf,smb_prdisp,pp - params);
151 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
152 if(data_sent_thistime == 0) {
153 SSVAL(outbuf,smb_droff,0);
154 SSVAL(outbuf,smb_drdisp, 0);
155 } else {
156 /* The offset of the data bytes is the offset of the
157 parameter bytes plus the number of parameters being sent this time */
158 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
159 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
160 SSVAL(outbuf,smb_drdisp, pd - pdata);
163 /* Copy the param bytes into the packet */
165 if(params_sent_thistime)
166 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
168 /* Copy in the data bytes */
170 if(data_sent_thistime)
171 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
172 data_alignment_offset,pd,data_sent_thistime);
174 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
175 params_sent_thistime, data_sent_thistime, useable_space));
176 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
177 params_to_send, data_to_send, paramsize, datasize));
179 /* Send the packet */
180 if (!send_smb(smbd_server_fd(),outbuf))
181 exit_server("send_trans2_replies: send_smb failed.");
183 pp += params_sent_thistime;
184 pd += data_sent_thistime;
186 params_to_send -= params_sent_thistime;
187 data_to_send -= data_sent_thistime;
189 /* Sanity check */
191 if(params_to_send < 0 || data_to_send < 0) {
192 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
193 params_to_send, data_to_send));
194 return -1;
198 return 0;
201 /****************************************************************************
202 Reply to a TRANSACT2_OPEN.
203 ****************************************************************************/
205 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
206 char **pparams, int total_params, char **ppdata, int total_data)
208 char *params = *pparams;
209 int16 open_mode;
210 int16 open_attr;
211 BOOL oplock_request;
212 #if 0
213 BOOL return_additional_info;
214 int16 open_sattr;
215 time_t open_time;
216 #endif
217 int16 open_ofun;
218 int32 open_size;
219 char *pname;
221 pstring fname;
222 mode_t unixmode;
223 SMB_OFF_T size=0;
224 int fmode=0,mtime=0,rmode;
225 SMB_INO_T inode = 0;
226 SMB_STRUCT_STAT sbuf;
227 int smb_action = 0;
228 BOOL bad_path = False;
229 files_struct *fsp;
232 * Ensure we have enough parameters to perform the operation.
235 if (total_params < 29)
236 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
238 open_mode = SVAL(params, 2);
239 open_attr = SVAL(params,6);
240 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
241 #if 0
242 return_additional_info = BITSETW(params,0);
243 open_sattr = SVAL(params, 4);
244 open_time = make_unix_date3(params+8);
245 #endif
246 open_ofun = SVAL(params,12);
247 open_size = IVAL(params,14);
248 pname = &params[28];
250 pstrcpy(fname, pname);
252 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
253 fname,open_mode, open_attr, open_ofun, open_size));
255 if (IS_IPC(conn))
256 return(ERROR_DOS(ERRSRV,ERRaccess));
258 /* XXXX we need to handle passed times, sattr and flags */
260 unix_convert(fname,conn,0,&bad_path,&sbuf);
262 if (!check_name(fname,conn)) {
263 set_bad_path_error(errno, bad_path);
264 return(UNIXERROR(ERRDOS,ERRnoaccess));
267 unixmode = unix_mode(conn,open_attr | aARCH, fname);
269 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode,
270 oplock_request, &rmode,&smb_action);
272 if (!fsp) {
273 set_bad_path_error(errno, bad_path);
274 return(UNIXERROR(ERRDOS,ERRnoaccess));
277 size = get_file_size(sbuf);
278 fmode = dos_mode(conn,fname,&sbuf);
279 mtime = sbuf.st_mtime;
280 inode = sbuf.st_ino;
281 if (fmode & aDIR) {
282 close_file(fsp,False);
283 return(ERROR_DOS(ERRDOS,ERRnoaccess));
286 /* Realloc the size of parameters and data we will return */
287 params = Realloc(*pparams, 28);
288 if( params == NULL )
289 return(ERROR_DOS(ERRDOS,ERRnomem));
290 *pparams = params;
292 memset((char *)params,'\0',28);
293 SSVAL(params,0,fsp->fnum);
294 SSVAL(params,2,fmode);
295 put_dos_date2(params,4, mtime);
296 SIVAL(params,8, (uint32)size);
297 SSVAL(params,12,rmode);
299 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
300 smb_action |= EXTENDED_OPLOCK_GRANTED;
302 SSVAL(params,18,smb_action);
305 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
307 SIVAL(params,20,inode);
309 /* Send the required number of replies */
310 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
312 return -1;
315 /*********************************************************
316 Routine to check if a given string matches exactly.
317 as a special case a mask of "." does NOT match. That
318 is required for correct wildcard semantics
319 Case can be significant or not.
320 **********************************************************/
322 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
324 if (mask[0] == '.' && mask[1] == 0)
325 return False;
326 if (case_sig)
327 return strcmp(str,mask)==0;
328 return strcasecmp(str,mask) == 0;
331 /****************************************************************************
332 Return the filetype for UNIX extensions.
333 ****************************************************************************/
335 static uint32 unix_filetype(mode_t mode)
337 if(S_ISREG(mode))
338 return UNIX_TYPE_FILE;
339 else if(S_ISDIR(mode))
340 return UNIX_TYPE_DIR;
341 #ifdef S_ISLNK
342 else if(S_ISLNK(mode))
343 return UNIX_TYPE_SYMLINK;
344 #endif
345 #ifdef S_ISCHR
346 else if(S_ISCHR(mode))
347 return UNIX_TYPE_CHARDEV;
348 #endif
349 #ifdef S_ISBLK
350 else if(S_ISBLK(mode))
351 return UNIX_TYPE_BLKDEV;
352 #endif
353 #ifdef S_ISFIFO
354 else if(S_ISFIFO(mode))
355 return UNIX_TYPE_FIFO;
356 #endif
357 #ifdef S_ISSOCK
358 else if(S_ISSOCK(mode))
359 return UNIX_TYPE_SOCKET;
360 #endif
362 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
363 return UNIX_TYPE_UNKNOWN;
366 /****************************************************************************
367 Return the major devicenumber for UNIX extensions.
368 ****************************************************************************/
370 static uint32 unix_dev_major(SMB_DEV_T dev)
372 #if defined(HAVE_DEVICE_MAJOR_FN)
373 return (uint32)major(dev);
374 #else
375 return (uint32)(dev >> 8);
376 #endif
379 /****************************************************************************
380 Return the minor devicenumber for UNIX extensions.
381 ****************************************************************************/
383 static uint32 unix_dev_minor(SMB_DEV_T dev)
385 #if defined(HAVE_DEVICE_MINOR_FN)
386 return (uint32)minor(dev);
387 #else
388 return (uint32)(dev & 0xff);
389 #endif
392 /****************************************************************************
393 Map wire perms onto standard UNIX permissions. Obey share restrictions.
394 ****************************************************************************/
396 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
398 mode_t ret = 0;
400 if (perms == SMB_MODE_NO_CHANGE)
401 return pst->st_mode;
403 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
404 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
405 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
406 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
407 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
408 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
409 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
410 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
411 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
412 #ifdef S_ISVTX
413 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
414 #endif
415 #ifdef S_ISGID
416 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
417 #endif
418 #ifdef S_ISUID
419 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
420 #endif
422 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
423 ret &= lp_dir_mask(SNUM(conn));
424 /* Add in force bits */
425 ret |= lp_force_dir_mode(SNUM(conn));
426 } else {
427 /* Apply mode mask */
428 ret &= lp_create_mask(SNUM(conn));
429 /* Add in force bits */
430 ret |= lp_force_create_mode(SNUM(conn));
433 return ret;
436 /****************************************************************************
437 checks for SMB_TIME_NO_CHANGE and if not found
438 calls interpret_long_date
439 ****************************************************************************/
440 time_t interpret_long_unix_date(char *p)
442 DEBUG(1,("interpret_long_unix_date\n"));
443 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
444 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
445 return -1;
446 } else {
447 return interpret_long_date(p);
451 /****************************************************************************
452 Get a level dependent lanman2 dir entry.
453 ****************************************************************************/
455 static BOOL get_lanman2_dir_entry(connection_struct *conn,
456 char *path_mask,int dirtype,int info_level,
457 int requires_resume_key,
458 BOOL dont_descend,char **ppdata,
459 char *base_data, int space_remaining,
460 BOOL *out_of_space, BOOL *got_exact_match,
461 int *last_name_off)
463 char *dname;
464 BOOL found = False;
465 SMB_STRUCT_STAT sbuf;
466 pstring mask;
467 pstring pathreal;
468 pstring fname;
469 char *p, *pdata = *ppdata;
470 uint32 reskey=0;
471 int prev_dirpos=0;
472 int mode=0;
473 SMB_OFF_T size = 0;
474 SMB_BIG_UINT allocation_size = 0;
475 uint32 len;
476 time_t mdate=0, adate=0, cdate=0;
477 char *nameptr;
478 BOOL was_8_3;
479 int nt_extmode; /* Used for NT connections instead of mode */
480 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
482 *fname = 0;
483 *out_of_space = False;
484 *got_exact_match = False;
486 if (!conn->dirptr)
487 return(False);
489 p = strrchr(path_mask,'/');
490 if(p != NULL) {
491 if(p[1] == '\0')
492 pstrcpy(mask,"*.*");
493 else
494 pstrcpy(mask, p+1);
495 } else
496 pstrcpy(mask, path_mask);
498 while (!found) {
499 BOOL got_match;
501 /* Needed if we run out of space */
502 prev_dirpos = TellDir(conn->dirptr);
503 dname = ReadDirName(conn->dirptr);
506 * Due to bugs in NT client redirectors we are not using
507 * resume keys any more - set them to zero.
508 * Check out the related comments in findfirst/findnext.
509 * JRA.
512 reskey = 0;
514 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
515 (long)conn->dirptr,TellDir(conn->dirptr)));
517 if (!dname)
518 return(False);
520 pstrcpy(fname,dname);
522 if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
523 got_match = mask_match(fname, mask, case_sensitive);
525 if(!got_match && !mangle_is_8_3(fname, False)) {
528 * It turns out that NT matches wildcards against
529 * both long *and* short names. This may explain some
530 * of the wildcard wierdness from old DOS clients
531 * that some people have been seeing.... JRA.
534 pstring newname;
535 pstrcpy( newname, fname);
536 mangle_map( newname, True, False, SNUM(conn));
537 if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
538 got_match = mask_match(newname, mask, case_sensitive);
541 if(got_match) {
542 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
543 if (dont_descend && !isdots)
544 continue;
546 pstrcpy(pathreal,conn->dirpath);
547 if(needslash)
548 pstrcat(pathreal,"/");
549 pstrcat(pathreal,dname);
551 if (INFO_LEVEL_IS_UNIX(info_level)) {
552 if (vfs_lstat(conn,pathreal,&sbuf) != 0) {
553 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
554 pathreal,strerror(errno)));
555 continue;
557 } else if (vfs_stat(conn,pathreal,&sbuf) != 0) {
559 /* Needed to show the msdfs symlinks as
560 * directories */
562 if(lp_host_msdfs() &&
563 lp_msdfs_root(SNUM(conn)) &&
564 is_msdfs_link(conn, pathreal, NULL, NULL,
565 &sbuf)) {
567 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
568 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
570 } else {
572 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
573 pathreal,strerror(errno)));
574 continue;
578 mode = dos_mode(conn,pathreal,&sbuf);
580 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
581 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
582 continue;
585 size = get_file_size(sbuf);
586 allocation_size = get_allocation_size(NULL,&sbuf);
587 mdate = sbuf.st_mtime;
588 adate = sbuf.st_atime;
589 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
591 if (lp_dos_filetime_resolution(SNUM(conn))) {
592 cdate &= ~1;
593 mdate &= ~1;
594 adate &= ~1;
597 if(mode & aDIR)
598 size = 0;
600 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
602 found = True;
606 mangle_map(fname,False,True,SNUM(conn));
608 p = pdata;
609 nameptr = p;
611 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
613 switch (info_level) {
614 case 1:
615 if(requires_resume_key) {
616 SIVAL(p,0,reskey);
617 p += 4;
619 put_dos_date2(p,l1_fdateCreation,cdate);
620 put_dos_date2(p,l1_fdateLastAccess,adate);
621 put_dos_date2(p,l1_fdateLastWrite,mdate);
622 SIVAL(p,l1_cbFile,(uint32)size);
623 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
624 SSVAL(p,l1_attrFile,mode);
625 SCVAL(p,l1_cchName,strlen(fname));
626 pstrcpy(p + l1_achName, fname);
627 nameptr = p + l1_achName;
628 p += l1_achName + strlen(fname) + 1;
629 break;
631 case 2:
632 if(requires_resume_key) {
633 SIVAL(p,0,reskey);
634 p += 4;
636 put_dos_date2(p,l2_fdateCreation,cdate);
637 put_dos_date2(p,l2_fdateLastAccess,adate);
638 put_dos_date2(p,l2_fdateLastWrite,mdate);
639 SIVAL(p,l2_cbFile,(uint32)size);
640 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
641 SSVAL(p,l2_attrFile,mode);
642 SIVAL(p,l2_cbList,0); /* No extended attributes */
643 SCVAL(p,l2_cchName,strlen(fname));
644 pstrcpy(p + l2_achName, fname);
645 nameptr = p + l2_achName;
646 p += l2_achName + strlen(fname) + 1;
647 break;
649 case 3:
650 SIVAL(p,0,reskey);
651 put_dos_date2(p,4,cdate);
652 put_dos_date2(p,8,adate);
653 put_dos_date2(p,12,mdate);
654 SIVAL(p,16,(uint32)size);
655 SIVAL(p,20,(uint32)allocation_size);
656 SSVAL(p,24,mode);
657 SIVAL(p,26,4);
658 SCVAL(p,30,strlen(fname));
659 pstrcpy(p+31, fname);
660 nameptr = p+31;
661 p += 31 + strlen(fname) + 1;
662 break;
664 case 4:
665 if(requires_resume_key) {
666 SIVAL(p,0,reskey);
667 p += 4;
669 SIVAL(p,0,33+strlen(fname)+1);
670 put_dos_date2(p,4,cdate);
671 put_dos_date2(p,8,adate);
672 put_dos_date2(p,12,mdate);
673 SIVAL(p,16,(uint32)size);
674 SIVAL(p,20,(uint32)allocation_size);
675 SSVAL(p,24,mode);
676 SCVAL(p,32,strlen(fname));
677 pstrcpy(p + 33, fname);
678 nameptr = p+33;
679 p += 33 + strlen(fname) + 1;
680 break;
682 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
683 was_8_3 = mangle_is_8_3(fname, True);
684 len = 94+strlen(fname);
685 len = (len + 3) & ~3;
686 SIVAL(p,0,len); p += 4;
687 SIVAL(p,0,reskey); p += 4;
688 put_long_date(p,cdate); p += 8;
689 put_long_date(p,adate); p += 8;
690 put_long_date(p,mdate); p += 8;
691 put_long_date(p,mdate); p += 8;
692 SOFF_T(p,0,size);
693 SOFF_T(p,8,allocation_size);
694 p += 16;
695 SIVAL(p,0,nt_extmode); p += 4;
696 SIVAL(p,0,strlen(fname)); p += 4;
697 SIVAL(p,0,0); p += 4;
698 /* Clear the short name buffer. This is
699 * IMPORTANT as not doing so will trigger
700 * a Win2k client bug. JRA.
702 memset(p,'\0',26);
703 if (!was_8_3) {
704 fstring tmpname;
705 fstrcpy(tmpname,fname);
706 mangle_map(tmpname,True,True,SNUM(conn));
707 strupper(tmpname);
708 fstrcpy(p+2,tmpname);
709 SSVAL(p, 0, strlen(tmpname));
710 } else {
711 SSVAL(p,0,0);
712 *(p+2) = 0;
714 p += 2 + 24;
715 /* nameptr = p; */
716 pstrcpy(p,fname); p += strlen(p);
717 p = pdata + len;
718 break;
720 case SMB_FIND_FILE_DIRECTORY_INFO:
721 len = 64+strlen(fname);
722 len = (len + 3) & ~3;
723 SIVAL(p,0,len); p += 4;
724 SIVAL(p,0,reskey); p += 4;
725 put_long_date(p,cdate); p += 8;
726 put_long_date(p,adate); p += 8;
727 put_long_date(p,mdate); p += 8;
728 put_long_date(p,mdate); p += 8;
729 SOFF_T(p,0,size);
730 SOFF_T(p,8,allocation_size);
731 p += 16;
732 SIVAL(p,0,nt_extmode); p += 4;
733 SIVAL(p,0,strlen(fname)); p += 4;
734 pstrcpy(p,fname);
735 p = pdata + len;
736 break;
738 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
739 len = 68+strlen(fname);
740 len = (len + 3) & ~3;
741 SIVAL(p,0,len); p += 4;
742 SIVAL(p,0,reskey); p += 4;
743 put_long_date(p,cdate); p += 8;
744 put_long_date(p,adate); p += 8;
745 put_long_date(p,mdate); p += 8;
746 put_long_date(p,mdate); p += 8;
747 SOFF_T(p,0,size);
748 SOFF_T(p,8,allocation_size);
749 p += 16;
750 SIVAL(p,0,nt_extmode); p += 4;
751 SIVAL(p,0,strlen(fname)); p += 4;
752 SIVAL(p,0,0); p += 4;
753 pstrcpy(p,fname);
754 p = pdata + len;
755 break;
757 case SMB_FIND_FILE_NAMES_INFO:
758 len = 12+strlen(fname);
759 len = (len + 3) & ~3;
760 SIVAL(p,0,len); p += 4;
761 SIVAL(p,0,reskey); p += 4;
762 SIVAL(p,0,strlen(fname)); p += 4;
763 pstrcpy(p,fname);
764 p = pdata + len;
765 break;
767 /* CIFS UNIX Extension. */
769 case SMB_FIND_FILE_UNIX:
770 len = 108+strlen(fname)+1; /* (length of SMB_QUERY_FILE_UNIX_BASIC = 100)+4+4+strlen(fname)*/
771 /* +1 to be sure to transmit the termination of fname */
772 len = (len + 3) & ~3;
774 SIVAL(p,0,len); p+= 4; /* Offset from this structure to the beginning of the next one */
775 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
777 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
778 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
779 p+= 8;
781 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
782 p+= 8;
784 put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */
785 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
786 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
787 p+= 24;
789 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
790 SIVAL(p,4,0);
791 p+= 8;
793 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
794 SIVAL(p,4,0);
795 p+= 8;
797 SIVAL(p,0,unix_filetype(sbuf.st_mode));
798 p+= 4;
800 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
801 SIVAL(p,4,0);
802 p+= 8;
804 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
805 SIVAL(p,4,0);
806 p+= 8;
808 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
809 p+= 8;
811 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
812 SIVAL(p,4,0);
813 p+= 8;
815 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
816 SIVAL(p,4,0);
817 p+= 8;
819 /* End of SMB_QUERY_FILE_UNIX_BASIC */
820 pstrcpy(p,fname);
821 p=pdata+len;
823 break;
825 default:
826 return(False);
830 if (PTR_DIFF(p,pdata) > space_remaining) {
831 /* Move the dirptr back to prev_dirpos */
832 SeekDir(conn->dirptr, prev_dirpos);
833 *out_of_space = True;
834 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
835 return False; /* Not finished - just out of space */
838 /* Setup the last_filename pointer, as an offset from base_data */
839 *last_name_off = PTR_DIFF(nameptr,base_data);
840 /* Advance the data pointer to the next slot */
841 *ppdata = p;
843 return(found);
846 /****************************************************************************
847 Reply to a TRANS2_FINDFIRST.
848 ****************************************************************************/
850 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
851 char **pparams, int total_params, char **ppdata, int total_data)
853 /* We must be careful here that we don't return more than the
854 allowed number of data bytes. If this means returning fewer than
855 maxentries then so be it. We assume that the redirector has
856 enough room for the fixed number of parameter bytes it has
857 requested. */
858 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
859 char *params = *pparams;
860 char *pdata = *ppdata;
861 int dirtype;
862 int maxentries;
863 BOOL close_after_first;
864 BOOL close_if_end;
865 BOOL requires_resume_key;
866 int info_level;
867 pstring directory;
868 pstring mask;
869 char *p, *wcard;
870 int last_name_off=0;
871 int dptr_num = -1;
872 int numentries = 0;
873 int i;
874 BOOL finished = False;
875 BOOL dont_descend = False;
876 BOOL out_of_space = False;
877 int space_remaining;
878 BOOL bad_path = False;
879 SMB_STRUCT_STAT sbuf;
881 if (total_params < 12)
882 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
884 *directory = *mask = 0;
886 dirtype = SVAL(params,0);
887 maxentries = SVAL(params,2);
888 close_after_first = BITSETW(params+4,0);
889 close_if_end = BITSETW(params+4,1);
890 requires_resume_key = BITSETW(params+4,2);
891 info_level = SVAL(params,6);
893 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
894 close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
895 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
896 info_level, max_data_bytes));
898 switch (info_level) {
899 case 1:
900 case 2:
901 case 3:
902 case 4:
903 case SMB_FIND_FILE_DIRECTORY_INFO:
904 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
905 case SMB_FIND_FILE_NAMES_INFO:
906 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
907 break;
908 case SMB_FIND_FILE_UNIX:
909 if (!lp_unix_extensions())
910 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
911 break;
912 default:
913 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
916 pstrcpy(directory, params + 12); /* Complete directory path with wildcard mask appended */
918 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
920 DEBUG(5,("path=%s\n",directory));
922 unix_convert(directory,conn,0,&bad_path,&sbuf);
923 if(!check_name(directory,conn)) {
924 set_bad_path_error(errno, bad_path);
926 #if 0
927 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
928 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && (get_remote_arch() == RA_WINNT)) {
929 unix_ERR_class = ERRDOS;
930 unix_ERR_code = ERRbaddirectory;
932 #endif
934 return(UNIXERROR(ERRDOS,ERRbadpath));
937 p = strrchr(directory,'/');
938 if(p == NULL) {
939 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
940 if((directory[0] == '.') && (directory[1] == '\0'))
941 pstrcpy(mask,"*");
942 else
943 pstrcpy(mask,directory);
944 pstrcpy(directory,"./");
945 } else {
946 pstrcpy(mask,p+1);
947 *p = 0;
950 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
952 pdata = Realloc(*ppdata, max_data_bytes + 1024);
953 if( pdata == NULL )
954 return(ERROR_DOS(ERRDOS,ERRnomem));
955 *ppdata = pdata;
956 memset((char *)pdata,'\0',max_data_bytes + 1024);
958 /* Realloc the params space */
959 params = Realloc(*pparams, 10);
960 if( params == NULL )
961 return ERROR_DOS(ERRDOS,ERRnomem);
962 *pparams = params;
964 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
965 if (dptr_num < 0)
966 return(UNIXERROR(ERRDOS,ERRbadfile));
968 /* Save the wildcard match and attribs we are using on this directory -
969 needed as lanman2 assumes these are being saved between calls */
971 if(!(wcard = strdup(mask))) {
972 dptr_close(&dptr_num);
973 return ERROR_DOS(ERRDOS,ERRnomem);
976 dptr_set_wcard(dptr_num, wcard);
977 dptr_set_attr(dptr_num, dirtype);
979 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
981 /* We don't need to check for VOL here as this is returned by
982 a different TRANS2 call. */
984 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
986 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
987 dont_descend = True;
989 p = pdata;
990 space_remaining = max_data_bytes;
991 out_of_space = False;
993 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
994 BOOL got_exact_match = False;
996 /* this is a heuristic to avoid seeking the dirptr except when
997 absolutely necessary. It allows for a filename of about 40 chars */
999 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1000 out_of_space = True;
1001 finished = False;
1002 } else {
1003 finished = !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
1004 requires_resume_key,dont_descend,
1005 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1006 &last_name_off);
1009 if (finished && out_of_space)
1010 finished = False;
1012 if (!finished && !out_of_space)
1013 numentries++;
1016 * As an optimisation if we know we aren't looking
1017 * for a wildcard name (ie. the name matches the wildcard exactly)
1018 * then we can finish on any (first) match.
1019 * This speeds up large directory searches. JRA.
1022 if(got_exact_match)
1023 finished = True;
1025 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1028 /* Check if we can close the dirptr */
1030 if(close_after_first || (finished && close_if_end)) {
1031 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1032 dptr_close(&dptr_num);
1036 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1037 * from observation of NT.
1040 if(numentries == 0) {
1041 dptr_close(&dptr_num);
1042 return ERROR_DOS(ERRDOS,ERRbadfile);
1045 /* At this point pdata points to numentries directory entries. */
1047 /* Set up the return parameter block */
1048 SSVAL(params,0,dptr_num);
1049 SSVAL(params,2,numentries);
1050 SSVAL(params,4,finished);
1051 SSVAL(params,6,0); /* Never an EA error */
1052 SSVAL(params,8,last_name_off);
1054 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1056 if ((! *directory) && dptr_path(dptr_num))
1057 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1059 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1060 smb_fn_name(CVAL(inbuf,smb_com)),
1061 mask, directory, dirtype, numentries ) );
1064 * Force a name mangle here to ensure that the
1065 * mask as an 8.3 name is top of the mangled cache.
1066 * The reasons for this are subtle. Don't remove
1067 * this code unless you know what you are doing
1068 * (see PR#13758). JRA.
1071 if(!mangle_is_8_3_wildcards( mask, False))
1072 mangle_map(mask, True, True, SNUM(conn));
1074 return(-1);
1077 /****************************************************************************
1078 Reply to a TRANS2_FINDNEXT.
1079 ****************************************************************************/
1081 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1082 char **pparams, int total_params, char **ppdata, int total_data)
1084 /* We must be careful here that we don't return more than the
1085 allowed number of data bytes. If this means returning fewer than
1086 maxentries then so be it. We assume that the redirector has
1087 enough room for the fixed number of parameter bytes it has
1088 requested. */
1089 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1090 char *params = *pparams;
1091 char *pdata = *ppdata;
1092 int dptr_num;
1093 int maxentries;
1094 uint16 info_level;
1095 uint32 resume_key;
1096 BOOL close_after_request;
1097 BOOL close_if_end;
1098 BOOL requires_resume_key;
1099 BOOL continue_bit;
1100 pstring resume_name;
1101 pstring mask;
1102 pstring directory;
1103 char *p;
1104 uint16 dirtype;
1105 int numentries = 0;
1106 int i, last_name_off=0;
1107 BOOL finished = False;
1108 BOOL dont_descend = False;
1109 BOOL out_of_space = False;
1110 int space_remaining;
1112 if (total_params < 12)
1113 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1115 dptr_num = SVAL(params,0);
1116 maxentries = SVAL(params,2);
1117 info_level = SVAL(params,4);
1118 resume_key = IVAL(params,6);
1119 close_after_request = BITSETW(params+10,0);
1120 close_if_end = BITSETW(params+10,1);
1121 requires_resume_key = BITSETW(params+10,2);
1122 continue_bit = BITSETW(params+10,3);
1124 *mask = *directory = *resume_name = 0;
1126 pstrcpy( resume_name, params+12);
1128 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1129 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1130 resume_key = %d resume name = %s continue=%d level = %d\n",
1131 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1132 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1134 switch (info_level) {
1135 case 1:
1136 case 2:
1137 case 3:
1138 case 4:
1139 case SMB_FIND_FILE_DIRECTORY_INFO:
1140 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1141 case SMB_FIND_FILE_NAMES_INFO:
1142 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1143 break;
1144 case SMB_FIND_FILE_UNIX:
1145 if (!lp_unix_extensions())
1146 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1147 break;
1148 default:
1149 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1152 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1153 if(pdata == NULL)
1154 return ERROR_DOS(ERRDOS,ERRnomem);
1156 *ppdata = pdata;
1157 memset((char *)pdata,'\0',max_data_bytes + 1024);
1159 /* Realloc the params space */
1160 params = Realloc(*pparams, 6*SIZEOFWORD);
1161 if( params == NULL )
1162 return ERROR_DOS(ERRDOS,ERRnomem);
1163 *pparams = params;
1165 /* Check that the dptr is valid */
1166 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1167 return ERROR_DOS(ERRDOS,ERRnofiles);
1169 string_set(&conn->dirpath,dptr_path(dptr_num));
1171 /* Get the wildcard mask from the dptr */
1172 if((p = dptr_wcard(dptr_num))== NULL) {
1173 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1174 return ERROR_DOS(ERRDOS,ERRnofiles);
1176 pstrcpy(mask, p);
1177 pstrcpy(directory,conn->dirpath);
1179 /* Get the attr mask from the dptr */
1180 dirtype = dptr_attr(dptr_num);
1182 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1183 dptr_num, mask, dirtype, (long)conn->dirptr, TellDir(conn->dirptr)));
1185 /* We don't need to check for VOL here as this is returned by
1186 a different TRANS2 call. */
1188 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1189 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1190 dont_descend = True;
1192 p = pdata;
1193 space_remaining = max_data_bytes;
1194 out_of_space = False;
1197 * Seek to the correct position. We no longer use the resume key but
1198 * depend on the last file name instead.
1201 if(requires_resume_key && *resume_name && !continue_bit) {
1204 * Fix for NT redirector problem triggered by resume key indexes
1205 * changing between directory scans. We now return a resume key of 0
1206 * and instead look for the filename to continue from (also given
1207 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1208 * findfirst/findnext (as is usual) then the directory pointer
1209 * should already be at the correct place. Check this by scanning
1210 * backwards looking for an exact (ie. case sensitive) filename match.
1211 * If we get to the beginning of the directory and haven't found it then scan
1212 * forwards again looking for a match. JRA.
1215 int current_pos, start_pos;
1216 char *dname = NULL;
1217 void *dirptr = conn->dirptr;
1218 start_pos = TellDir(dirptr);
1220 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1221 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1223 SeekDir(dirptr, current_pos);
1224 dname = ReadDirName(dirptr);
1227 * Remember, name_map_mangle is called by
1228 * get_lanman2_dir_entry(), so the resume name
1229 * could be mangled. Ensure we do the same
1230 * here.
1233 if(dname != NULL)
1234 mangle_map( dname, False, True, SNUM(conn));
1236 if(dname && strcsequal( resume_name, dname)) {
1237 SeekDir(dirptr, current_pos+1);
1238 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1239 break;
1244 * Scan forward from start if not found going backwards.
1247 if(current_pos < 0) {
1248 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1249 SeekDir(dirptr, start_pos);
1250 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1253 * Remember, name_map_mangle is called by
1254 * get_lanman2_dir_entry(), so the resume name
1255 * could be mangled. Ensure we do the same
1256 * here.
1259 if(dname != NULL)
1260 mangle_map( dname, False, True, SNUM(conn));
1262 if(dname && strcsequal( resume_name, dname)) {
1263 SeekDir(dirptr, current_pos+1);
1264 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1265 break;
1267 } /* end for */
1268 } /* end if current_pos */
1269 } /* end if requires_resume_key && !continue_bit */
1271 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1272 BOOL got_exact_match = False;
1274 /* this is a heuristic to avoid seeking the dirptr except when
1275 absolutely necessary. It allows for a filename of about 40 chars */
1277 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1278 out_of_space = True;
1279 finished = False;
1280 } else {
1281 finished = !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
1282 requires_resume_key,dont_descend,
1283 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1284 &last_name_off);
1287 if (finished && out_of_space)
1288 finished = False;
1290 if (!finished && !out_of_space)
1291 numentries++;
1294 * As an optimisation if we know we aren't looking
1295 * for a wildcard name (ie. the name matches the wildcard exactly)
1296 * then we can finish on any (first) match.
1297 * This speeds up large directory searches. JRA.
1300 if(got_exact_match)
1301 finished = True;
1303 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1306 /* Check if we can close the dirptr */
1307 if(close_after_request || (finished && close_if_end)) {
1308 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1309 dptr_close(&dptr_num); /* This frees up the saved mask */
1313 /* Set up the return parameter block */
1314 SSVAL(params,0,numentries);
1315 SSVAL(params,2,finished);
1316 SSVAL(params,4,0); /* Never an EA error */
1317 SSVAL(params,6,last_name_off);
1319 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1321 if ((! *directory) && dptr_path(dptr_num))
1322 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1324 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1325 smb_fn_name(CVAL(inbuf,smb_com)),
1326 mask, directory, dirtype, numentries ) );
1328 return(-1);
1331 /****************************************************************************
1332 Reply to a TRANS2_QFSINFO (query filesystem info).
1333 ****************************************************************************/
1335 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1336 char **pparams, int total_params, char **ppdata, int total_data)
1338 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1339 char *pdata = *ppdata;
1340 char *params = *pparams;
1341 uint16 info_level;
1342 int data_len;
1343 SMB_STRUCT_STAT st;
1344 char *vname = volume_label(SNUM(conn));
1345 int snum = SNUM(conn);
1346 char *fstype = lp_fstype(SNUM(conn));
1348 if (total_params < 2)
1349 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1351 info_level = SVAL(params,0);
1352 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1354 if(vfs_stat(conn,".",&st)!=0) {
1355 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1356 return ERROR_DOS(ERRSRV,ERRinvdevice);
1359 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1360 if ( pdata == NULL )
1361 return ERROR_DOS(ERRDOS,ERRnomem);
1363 *ppdata = pdata;
1364 memset((char *)pdata,'\0',max_data_bytes + 1024);
1366 switch (info_level) {
1367 case 1:
1369 SMB_BIG_UINT dfree,dsize,bsize;
1370 data_len = 18;
1371 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1372 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1373 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1374 SIVAL(pdata,l1_cUnit,dsize);
1375 SIVAL(pdata,l1_cUnitAvail,dfree);
1376 SSVAL(pdata,l1_cbSector,512);
1377 DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1378 (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1379 (unsigned int)dfree, 512));
1380 break;
1383 case 2:
1385 /* Return volume name */
1386 int volname_len = MIN(strlen(vname),11);
1387 data_len = l2_vol_szVolLabel + volname_len + 1;
1389 * Add volume serial number - hash of a combination of
1390 * the called hostname and the service name.
1392 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1393 SCVAL(pdata,l2_vol_cch,volname_len);
1394 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
1395 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1396 (unsigned)st.st_ctime, volname_len,
1397 pdata+l2_vol_szVolLabel));
1398 break;
1401 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1402 case SMB_FS_ATTRIBUTE_INFORMATION:
1404 int fstype_len;
1405 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1406 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */
1407 #if 0 /* Old code. JRA. */
1408 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
1409 SIVAL(pdata,0,0x700FF);
1410 #endif /* Old code. */
1412 SIVAL(pdata,4,255); /* Max filename component length */
1413 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1414 and will think we can't do long filenames */
1415 fstype_len = dos_PutUniCode(pdata+12,unix_to_dos_static(fstype),sizeof(pstring), False);
1416 SIVAL(pdata,8,fstype_len);
1417 data_len = 12 + fstype_len;
1418 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1419 break;
1422 case SMB_QUERY_FS_LABEL_INFO:
1423 case SMB_FS_LABEL_INFORMATION:
1424 data_len = 4 + strlen(vname);
1425 SIVAL(pdata,0,strlen(vname));
1426 pstrcpy(pdata+4,vname);
1427 break;
1429 case SMB_QUERY_FS_VOLUME_INFO:
1430 case SMB_FS_VOLUME_INFORMATION:
1432 * Add volume serial number - hash of a combination of
1433 * the called hostname and the service name.
1435 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1436 (str_checksum(local_machine)<<16));
1438 /* NT4 always serves this up as unicode but expects it to be
1439 * delivered as ascii! (tridge && JRA)
1441 if ((get_remote_arch() != RA_WIN2K) && (global_client_caps & CAP_NT_SMBS)) {
1442 data_len = 18 + strlen(vname);
1443 SIVAL(pdata,12,strlen(vname));
1444 pstrcpy(pdata+18,vname);
1445 } else {
1446 int vnamelen;
1448 vnamelen = dos_PutUniCode(pdata+18, vname, sizeof(pstring), False);
1449 data_len = 18 + vnamelen;
1450 SIVAL(pdata,12,vnamelen);
1451 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1454 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n",
1455 (int)strlen(vname),vname));
1456 break;
1458 case SMB_QUERY_FS_SIZE_INFO:
1459 case SMB_FS_SIZE_INFORMATION:
1461 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1462 data_len = 24;
1463 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1464 block_size = lp_block_size(snum);
1465 if (bsize < block_size) {
1466 SMB_BIG_UINT factor = block_size/bsize;
1467 bsize = block_size;
1468 dsize /= factor;
1469 dfree /= factor;
1471 if (bsize > block_size) {
1472 SMB_BIG_UINT factor = bsize/block_size;
1473 bsize = block_size;
1474 dsize *= factor;
1475 dfree *= factor;
1477 bytes_per_sector = 512;
1478 sectors_per_unit = bsize/bytes_per_sector;
1479 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1480 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1481 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1482 SBIG_UINT(pdata,0,dsize);
1483 SBIG_UINT(pdata,8,dfree);
1484 SIVAL(pdata,16,sectors_per_unit);
1485 SIVAL(pdata,20,bytes_per_sector);
1486 break;
1489 case SMB_FS_FULL_SIZE_INFORMATION:
1491 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1492 data_len = 32;
1493 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1494 block_size = lp_block_size(snum);
1495 if (bsize < block_size) {
1496 SMB_BIG_UINT factor = block_size/bsize;
1497 bsize = block_size;
1498 dsize /= factor;
1499 dfree /= factor;
1501 if (bsize > block_size) {
1502 SMB_BIG_UINT factor = bsize/block_size;
1503 bsize = block_size;
1504 dsize *= factor;
1505 dfree *= factor;
1507 bytes_per_sector = 512;
1508 sectors_per_unit = bsize/bytes_per_sector;
1509 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1510 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1511 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1512 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1513 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1514 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1515 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1516 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1517 break;
1520 case SMB_QUERY_FS_DEVICE_INFO:
1521 case SMB_FS_DEVICE_INFORMATION:
1522 data_len = 8;
1523 SIVAL(pdata,0,0); /* dev type */
1524 SIVAL(pdata,4,0); /* characteristics */
1525 break;
1527 case SMB_FS_OBJECTID_INFORMATION:
1528 data_len = 64;
1529 break;
1532 * Query the version and capabilities of the CIFS UNIX extensions
1533 * in use.
1536 case SMB_QUERY_CIFS_UNIX_INFO:
1538 if (!lp_unix_extensions())
1539 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1541 data_len = 12;
1542 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
1543 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
1544 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
1545 break;
1547 case SMB_MAC_QUERY_FS_INFO:
1549 * Thursby MAC extension... ONLY on NTFS filesystems
1550 * once we do streams then we don't need this
1552 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1553 data_len = 88;
1554 SIVAL(pdata,84,0x100); /* Don't support mac... */
1555 break;
1557 /* drop through */
1558 default:
1559 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1562 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1564 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1566 return -1;
1569 /****************************************************************************
1570 Reply to a TRANS2_SETFSINFO (set filesystem info).
1571 ****************************************************************************/
1573 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1574 char **pparams, int total_params, char **ppdata, int total_data)
1576 /* Just say yes we did it - there is nothing that
1577 can be set here so it doesn't matter. */
1578 int outsize;
1579 DEBUG(3,("call_trans2setfsinfo\n"));
1581 if (!CAN_WRITE(conn))
1582 return(ERROR_DOS(ERRSRV,ERRaccess));
1584 outsize = set_message(outbuf,10,0,True);
1586 return outsize;
1589 /****************************************************************************
1590 Utility function to set bad path error.
1591 ****************************************************************************/
1593 NTSTATUS set_bad_path_error(int err, BOOL bad_path)
1595 if((err == ENOENT) && bad_path) {
1596 unix_ERR_class = ERRDOS;
1597 unix_ERR_code = ERRbadpath;
1598 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1600 return NT_STATUS_OK;
1603 /****************************************************************************
1604 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1605 file name or file id).
1606 ****************************************************************************/
1608 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1609 char **pparams, int total_params, char **ppdata, int total_data)
1611 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1612 char *params = *pparams;
1613 char *pdata = *ppdata;
1614 uint16 tran_call = SVAL(inbuf, smb_setup0);
1615 uint16 info_level;
1616 int mode=0;
1617 SMB_OFF_T size=0;
1618 SMB_BIG_UINT allocation_size = 0;
1619 unsigned int data_size;
1620 SMB_STRUCT_STAT sbuf;
1621 pstring fname1;
1622 char *fname;
1623 pstring dos_fname;
1624 char *fullpathname;
1625 char *p;
1626 int l;
1627 SMB_OFF_T pos = 0;
1628 BOOL bad_path = False;
1629 BOOL delete_pending = False;
1630 time_t c_time;
1631 files_struct *fsp = NULL;
1633 if (!params)
1634 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1636 if (tran_call == TRANSACT2_QFILEINFO) {
1637 if (total_params < 4)
1638 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1640 fsp = file_fsp(params,0);
1641 info_level = SVAL(params,2);
1643 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1645 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1647 * This is actually a QFILEINFO on a directory
1648 * handle (returned from an NT SMB). NT5.0 seems
1649 * to do this call. JRA.
1651 fname = fsp->fsp_name;
1652 unix_convert(fname,conn,0,&bad_path,&sbuf);
1653 if (!check_name(fname,conn)) {
1654 DEBUG(3,("call_trans2qfilepathinfo: check_name of %s failed (%s)\n",fname,strerror(errno)));
1655 set_bad_path_error(errno, bad_path);
1656 return(UNIXERROR(ERRDOS,ERRbadpath));
1659 if (INFO_LEVEL_IS_UNIX(info_level)) {
1660 /* Always do lstat for UNIX calls. */
1661 if (vfs_lstat(conn,fname,&sbuf)) {
1662 DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
1663 set_bad_path_error(errno, bad_path);
1664 return(UNIXERROR(ERRDOS,ERRbadpath));
1666 } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
1667 DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
1668 set_bad_path_error(errno, bad_path);
1669 return(UNIXERROR(ERRDOS,ERRbadpath));
1672 delete_pending = fsp->directory_delete_on_close;
1674 } else {
1676 * Original code - this is an open file.
1678 CHECK_FSP(fsp,conn);
1680 fname = fsp->fsp_name;
1681 if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) {
1682 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1683 return(UNIXERROR(ERRDOS,ERRbadfid));
1686 if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1687 return(UNIXERROR(ERRDOS,ERRnoaccess));
1689 delete_pending = fsp->delete_on_close;
1691 } else {
1692 /* qpathinfo */
1693 if (total_params < 6)
1694 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1696 info_level = SVAL(params,0);
1698 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1700 fname = &fname1[0];
1701 pstrcpy(fname,&params[6]);
1703 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1705 unix_convert(fname,conn,0,&bad_path,&sbuf);
1706 if (!check_name(fname,conn)) {
1707 DEBUG(3,("call_trans2qfilepathinfo: check_name of %s failed (%s)\n",fname,strerror(errno)));
1708 set_bad_path_error(errno, bad_path);
1709 return(UNIXERROR(ERRDOS,ERRbadpath));
1711 if (INFO_LEVEL_IS_UNIX(info_level)) {
1712 /* Always do lstat for UNIX calls. */
1713 if (vfs_lstat(conn,fname,&sbuf)) {
1714 DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
1715 set_bad_path_error(errno, bad_path);
1716 return(UNIXERROR(ERRDOS,ERRbadpath));
1718 } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
1719 DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
1720 set_bad_path_error(errno, bad_path);
1721 return(UNIXERROR(ERRDOS,ERRbadpath));
1726 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
1727 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1729 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1730 fname,info_level,tran_call,total_data));
1732 p = strrchr(fname,'/');
1733 if (!p)
1734 p = fname;
1735 else
1736 p++;
1737 l = strlen(p);
1738 mode = dos_mode(conn,fname,&sbuf);
1739 fullpathname = fname;
1740 size = get_file_size(sbuf);
1741 allocation_size = get_allocation_size(fsp,&sbuf);
1742 if (mode & aDIR)
1743 size = 0;
1745 /* from now on we only want the part after the / */
1746 fname = p;
1748 params = Realloc(*pparams,2);
1749 if ( params == NULL )
1750 return ERROR_DOS(ERRDOS,ERRnomem);
1751 *pparams = params;
1752 memset((char *)params,'\0',2);
1753 data_size = max_data_bytes + 1024;
1754 pdata = Realloc(*ppdata, data_size);
1755 if ( pdata == NULL )
1756 return ERROR_DOS(ERRDOS,ERRnomem);
1757 *ppdata = pdata;
1759 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1760 /* uggh, EAs for OS2 */
1761 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1762 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1765 memset((char *)pdata,'\0',data_size);
1767 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1769 if (lp_dos_filetime_resolution(SNUM(conn))) {
1770 c_time &= ~1;
1771 sbuf.st_atime &= ~1;
1772 sbuf.st_mtime &= ~1;
1773 sbuf.st_mtime &= ~1;
1776 /* NT expects the name to be in an exact form */
1777 if (strequal(fname,"."))
1778 pstrcpy(dos_fname, "\\");
1779 else {
1780 snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname);
1781 string_replace( dos_fname, '/','\\');
1784 switch (info_level) {
1785 case SMB_INFO_STANDARD:
1786 case SMB_INFO_QUERY_EA_SIZE:
1787 data_size = (info_level==1?22:26);
1788 put_dos_date2(pdata,l1_fdateCreation,c_time);
1789 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1790 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1791 SIVAL(pdata,l1_cbFile,(uint32)size);
1792 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
1793 SSVAL(pdata,l1_attrFile,mode);
1794 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1795 break;
1797 case SMB_INFO_QUERY_EAS_FROM_LIST:
1798 data_size = 24;
1799 put_dos_date2(pdata,0,c_time);
1800 put_dos_date2(pdata,4,sbuf.st_atime);
1801 put_dos_date2(pdata,8,sbuf.st_mtime);
1802 SIVAL(pdata,12,(uint32)size);
1803 SIVAL(pdata,16,(uint32)allocation_size);
1804 SIVAL(pdata,20,mode);
1805 break;
1807 case SMB_INFO_QUERY_ALL_EAS:
1808 data_size = 4;
1809 SIVAL(pdata,0,data_size);
1810 break;
1812 case 6:
1813 return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */
1815 case SMB_FILE_BASIC_INFORMATION:
1816 case SMB_QUERY_FILE_BASIC_INFO:
1818 if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1819 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1820 else {
1821 data_size = 40;
1822 SIVAL(pdata,36,0);
1824 put_long_date(pdata,c_time);
1825 put_long_date(pdata+8,sbuf.st_atime);
1826 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1827 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1828 SIVAL(pdata,32,mode);
1830 DEBUG(5,("SMB_QFBI - "));
1833 time_t create_time = c_time;
1834 DEBUG(5,("create: %s ", ctime(&create_time)));
1837 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1838 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1839 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1840 DEBUG(5,("mode: %x\n", mode));
1842 break;
1844 case SMB_FILE_STANDARD_INFORMATION:
1845 case SMB_QUERY_FILE_STANDARD_INFO:
1847 data_size = 24;
1848 /* Fake up allocation size. */
1849 SOFF_T(pdata,0,allocation_size);
1850 SOFF_T(pdata,8,size);
1851 SIVAL(pdata,16,sbuf.st_nlink);
1852 SCVAL(pdata,20,0);
1853 SCVAL(pdata,21,(mode&aDIR)?1:0);
1854 break;
1856 case SMB_FILE_EA_INFORMATION:
1857 case SMB_QUERY_FILE_EA_INFO:
1858 data_size = 4;
1859 SIVAL(pdata,0,0);
1860 break;
1862 /* Get the 8.3 name - used if NT SMB was negotiated. */
1864 case SMB_QUERY_FILE_ALT_NAME_INFO:
1866 pstring short_name;
1867 pstrcpy(short_name,p);
1868 /* Mangle if not already 8.3 */
1869 if(!mangle_is_8_3(short_name, True)) {
1870 mangle_map(short_name,True,True,SNUM(conn));
1872 strupper(short_name);
1873 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1874 l = dos_PutUniCode(pdata + 4, short_name, sizeof(pstring), False);
1875 data_size = 4 + l;
1876 SIVAL(pdata,0,l);
1877 break;
1880 case SMB_QUERY_FILE_NAME_INFO:
1882 * The first part of this code is essential
1883 * to get security descriptors to work on mapped
1884 * drives. Don't ask how I discovered this unless
1885 * you like hearing about me suffering.... :-). JRA.
1888 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1889 l = dos_PutUniCode(pdata + 4, dos_fname,sizeof(pstring), False);
1890 data_size = 4 + l;
1891 SIVAL(pdata,0,l);
1892 break;
1894 case SMB_FILE_ALLOCATION_INFORMATION:
1895 case SMB_QUERY_FILE_ALLOCATION_INFO:
1896 data_size = 8;
1897 SOFF_T(pdata,0,allocation_size);
1898 break;
1900 case SMB_QUERY_FILE_END_OF_FILEINFO:
1901 case SMB_FILE_END_OF_FILE_INFORMATION:
1902 data_size = 8;
1903 SOFF_T(pdata,0,size);
1904 break;
1906 case SMB_QUERY_FILE_ALL_INFO:
1907 put_long_date(pdata,c_time);
1908 put_long_date(pdata+8,sbuf.st_atime);
1909 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1910 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1911 SIVAL(pdata,32,mode);
1912 pdata += 40;
1913 SOFF_T(pdata,0,allocation_size);
1914 SOFF_T(pdata,8,size);
1915 SIVAL(pdata,16,sbuf.st_nlink);
1916 SCVAL(pdata,20,delete_pending);
1917 SCVAL(pdata,21,(mode&aDIR)?1:0);
1918 pdata += 24;
1919 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);
1920 pdata += 8; /* index number */
1921 pdata += 4; /* EA info */
1922 if (mode & aRONLY)
1923 SIVAL(pdata,0,0xA9);
1924 else
1925 SIVAL(pdata,0,0xd01BF);
1926 pdata += 4;
1927 SOFF_T(pdata,0,pos); /* current offset */
1928 pdata += 8;
1929 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1930 pdata += 4;
1931 pdata += 4; /* alignment */
1932 SIVAL(pdata,0,l);
1933 pstrcpy(pdata+4,dos_fname);
1934 pdata += 4 + l;
1935 data_size = PTR_DIFF(pdata,(*ppdata));
1936 break;
1938 case SMB_FILE_INTERNAL_INFORMATION:
1939 /* This should be an index number - looks like dev/ino to me :-) */
1940 SIVAL(pdata,0,sbuf.st_dev);
1941 SIVAL(pdata,4,sbuf.st_ino);
1942 data_size = 8;
1943 break;
1945 case SMB_FILE_ACCESS_INFORMATION:
1946 SIVAL(pdata,0,0x12019F); /* ??? */
1947 data_size = 4;
1948 break;
1950 case SMB_FILE_NAME_INFORMATION:
1951 /* Pathname with leading '\'. */
1953 size_t byte_len;
1955 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1956 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
1957 SIVAL(pdata,0,byte_len);
1958 data_size = 4 + byte_len;
1959 break;
1962 case SMB_FILE_DISPOSITION_INFORMATION:
1963 data_size = 1;
1964 SCVAL(pdata,0,delete_pending);
1965 break;
1967 case SMB_FILE_POSITION_INFORMATION:
1968 data_size = 8;
1969 SOFF_T(pdata,0,pos);
1970 break;
1972 case SMB_FILE_MODE_INFORMATION:
1973 SIVAL(pdata,0,mode);
1974 data_size = 4;
1975 break;
1977 case SMB_FILE_ALIGNMENT_INFORMATION:
1978 SIVAL(pdata,0,0); /* No alignment needed. */
1979 data_size = 4;
1980 break;
1982 #if 0
1983 /* Not yet finished... JRA */
1984 case 1018:
1986 size_t byte_len;
1988 put_long_date(pdata,c_time);
1989 put_long_date(pdata+8,sbuf.st_atime);
1990 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1991 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1992 SIVAL(pdata,32,mode);
1993 SIVAL(pdata,36,0); /* ??? */
1994 SIVAL(pdata,40,0x20); /* ??? */
1995 SIVAL(pdata,44,0); /* ??? */
1996 SOFF_T(pdata,48,size);
1997 SIVAL(pdata,56,0x1); /* ??? */
1998 SIVAL(pdata,60,0); /* ??? */
1999 SIVAL(pdata,64,0); /* ??? */
2000 SIVAL(pdata,68,length); /* Following string length in bytes. */
2001 dos_PutUniCode(pdata+72,,False);
2002 break;
2004 #endif
2006 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2007 /* Last component of pathname. */
2009 size_t byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2010 SIVAL(pdata,0,byte_len);
2011 data_size = 4 + byte_len;
2012 break;
2015 #if 0
2017 * NT4 server just returns "invalid query" to this - if we try to answer
2018 * it then NTws gets a BSOD! (tridge).
2019 * W2K seems to want this. JRA.
2021 case SMB_QUERY_FILE_STREAM_INFO:
2022 #endif
2023 case SMB_FILE_STREAM_INFORMATION:
2024 if (mode & aDIR) {
2025 data_size = 0;
2026 } else {
2027 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 14, False);
2028 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
2029 SIVAL(pdata,0,0); /* Next stream (none). */
2030 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2031 SOFF_T(pdata,8,size);
2032 SOFF_T(pdata,16,allocation_size);
2033 data_size = 24 + byte_len;
2035 break;
2037 case SMB_FILE_COMPRESSION_INFORMATION:
2038 SOFF_T(pdata,0,size);
2039 SIVAL(pdata,8,0); /* ??? */
2040 SIVAL(pdata,12,0); /* ??? */
2041 data_size = 16;
2042 break;
2044 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2045 put_long_date(pdata,c_time);
2046 put_long_date(pdata+8,sbuf.st_atime);
2047 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2048 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2049 SOFF_T(pdata,32,allocation_size); /* Allocation size. */
2050 SOFF_T(pdata,40,size);
2051 SIVAL(pdata,48,mode);
2052 SIVAL(pdata,52,0); /* ??? */
2053 data_size = 56;
2054 break;
2056 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2057 SIVAL(pdata,0,mode);
2058 SIVAL(pdata,4,0);
2059 data_size = 8;
2060 break;
2063 * CIFS UNIX Extensions.
2066 case SMB_QUERY_FILE_UNIX_BASIC:
2068 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2070 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2071 pdata += 8;
2073 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2074 pdata += 8;
2076 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2077 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2078 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2079 pdata += 24;
2081 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2082 SIVAL(pdata,4,0);
2083 pdata += 8;
2085 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2086 SIVAL(pdata,4,0);
2087 pdata += 8;
2089 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2090 pdata += 4;
2092 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2093 SIVAL(pdata,4,0);
2094 pdata += 8;
2096 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2097 SIVAL(pdata,4,0);
2098 pdata += 8;
2100 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2101 pdata += 8;
2103 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2104 SIVAL(pdata,4,0);
2105 pdata += 8;
2107 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2108 SIVAL(pdata,4,0);
2109 pdata += 8+1;
2110 data_size = PTR_DIFF(pdata,(*ppdata));
2113 int i;
2114 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2116 for (i=0; i<100; i++)
2117 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2118 DEBUG(4,("\n"));
2121 break;
2123 case SMB_QUERY_FILE_UNIX_LINK:
2125 pstring buffer;
2126 int len;
2128 #ifdef S_ISLNK
2129 if(!S_ISLNK(sbuf.st_mode))
2130 return(UNIXERROR(ERRSRV,ERRbadlink));
2131 #else
2132 return(UNIXERROR(ERRDOS,ERRbadlink));
2133 #endif
2134 len = conn->vfs_ops.readlink(conn,dos_to_unix_static(fullpathname), buffer, sizeof(pstring)-1); /* read link */
2135 if (len == -1)
2136 return(UNIXERROR(ERRDOS,ERRnoaccess));
2137 buffer[len] = 0;
2138 unix_to_dos(buffer);
2139 pstrcpy(pdata,buffer); /* write '\0' terminated string */
2140 pdata += strlen(buffer)+1;
2141 data_size = PTR_DIFF(pdata,(*ppdata));
2143 break;
2146 default:
2147 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2150 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
2152 return(-1);
2155 /****************************************************************************
2156 Deal with the internal needs of setting the delete on close flag. Note that
2157 as the tdb locking is recursive, it is safe to call this from within
2158 open_file_shared. JRA.
2159 ****************************************************************************/
2161 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2164 * Only allow delete on close for writable shares.
2167 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2168 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2169 fsp->fsp_name ));
2170 return NT_STATUS_ACCESS_DENIED;
2173 * Only allow delete on close for files/directories opened with delete intent.
2176 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2177 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2178 fsp->fsp_name ));
2179 return NT_STATUS_ACCESS_DENIED;
2182 if(fsp->is_directory) {
2183 fsp->directory_delete_on_close = delete_on_close;
2184 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2185 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2186 } else {
2187 fsp->delete_on_close = delete_on_close;
2188 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2189 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2192 return NT_STATUS_OK;
2195 /****************************************************************************
2196 Sets the delete on close flag over all share modes on this file.
2197 Modify the share mode entry for all files open
2198 on this device and inode to tell other smbds we have
2199 changed the delete on close flag. This will be noticed
2200 in the close code, the last closer will delete the file
2201 if flag is set.
2202 ****************************************************************************/
2204 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2206 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2207 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2209 if (fsp->is_directory || fsp->is_stat)
2210 return NT_STATUS_OK;
2212 if (lock_share_entry_fsp(fsp) == False)
2213 return NT_STATUS_ACCESS_DENIED;
2215 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2216 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2217 fsp->fsp_name ));
2218 unlock_share_entry_fsp(fsp);
2219 return NT_STATUS_ACCESS_DENIED;
2222 unlock_share_entry_fsp(fsp);
2223 return NT_STATUS_OK;
2226 /****************************************************************************
2227 Returns true if this pathname is within the share, and thus safe.
2228 ****************************************************************************/
2230 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2232 #ifdef PATH_MAX
2233 char resolved_name[PATH_MAX+1];
2234 #else
2235 pstring resolved_name;
2236 #endif
2237 fstring last_component;
2238 pstring link_dest;
2239 pstring link_test;
2240 char *p;
2241 BOOL bad_path = False;
2242 SMB_STRUCT_STAT sbuf;
2244 pstrcpy(link_dest, link_dest_in);
2245 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2247 /* Store the UNIX converted path. */
2248 pstrcpy(link_dest_out, link_dest);
2250 p = strrchr(link_dest, '/');
2251 if (p) {
2252 fstrcpy(last_component, p+1);
2253 *p = '\0';
2254 } else {
2255 fstrcpy(last_component, link_dest);
2256 pstrcpy(link_dest, "./");
2259 if (conn->vfs_ops.realpath(conn,dos_to_unix_static(link_dest),resolved_name) == NULL)
2260 return -1;
2262 pstrcpy(link_dest, unix_to_dos_static(resolved_name));
2263 pstrcat(link_dest, "/");
2264 pstrcat(link_dest, last_component);
2266 if (*link_dest != '/') {
2267 /* Relative path. */
2268 pstrcpy(link_test, conn->connectpath);
2269 pstrcat(link_test, "/");
2270 pstrcat(link_test, link_dest);
2271 } else {
2272 pstrcpy(link_test, link_dest);
2276 * Check if the link is within the share.
2279 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2280 errno = EACCES;
2281 return -1;
2283 return 0;
2286 /****************************************************************************
2287 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2288 ****************************************************************************/
2290 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2291 char **pparams, int total_params, char **ppdata, int total_data)
2293 char *params = *pparams;
2294 char *pdata = *ppdata;
2295 uint16 tran_call = SVAL(inbuf, smb_setup0);
2296 uint16 info_level;
2297 int dosmode = 0;
2298 SMB_OFF_T size=0;
2299 struct utimbuf tvs;
2300 SMB_STRUCT_STAT sbuf;
2301 pstring fname1;
2302 char *fname = NULL;
2303 int fd = -1;
2304 BOOL bad_path = False;
2305 files_struct *fsp = NULL;
2306 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2307 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2308 mode_t unixmode = 0;
2310 if (tran_call == TRANSACT2_SETFILEINFO) {
2312 if (total_params < 4)
2313 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2315 fsp = file_fsp(params,0);
2316 info_level = SVAL(params,2);
2318 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2320 * This is actually a SETFILEINFO on a directory
2321 * handle (returned from an NT SMB). NT5.0 seems
2322 * to do this call. JRA.
2324 fname = fsp->fsp_name;
2325 unix_convert(fname,conn,0,&bad_path,&sbuf);
2326 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2327 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2328 set_bad_path_error(errno, bad_path);
2329 return(UNIXERROR(ERRDOS,ERRbadpath));
2331 } else if (fsp && fsp->print_file) {
2333 * Doing a DELETE_ON_CLOSE should cancel a print job.
2335 if (((info_level == SMB_SET_FILE_DISPOSITION_INFO)||(info_level == SMB_FILE_DISPOSITION_INFORMATION)) &&
2336 CVAL(pdata,0)) {
2337 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2339 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n",
2340 fsp->fsp_name ));
2342 SSVAL(params,0,0);
2343 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2344 return(-1);
2345 } else
2346 return(UNIXERROR(ERRDOS,ERRbadpath));
2347 } else {
2349 * Original code - this is an open file.
2351 CHECK_FSP(fsp,conn);
2353 fname = fsp->fsp_name;
2354 fd = fsp->fd;
2356 if (vfs_fstat(fsp,fd,&sbuf) != 0) {
2357 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2358 return(UNIXERROR(ERRDOS,ERRbadfid));
2361 } else {
2362 /* set path info */
2363 if (total_params < 6)
2364 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2366 info_level = SVAL(params,0);
2367 fname = fname1;
2368 pstrcpy(fname,&params[6]);
2369 unix_convert(fname,conn,0,&bad_path,&sbuf);
2370 if(!check_name(fname, conn)) {
2371 set_bad_path_error(errno, bad_path);
2372 return(UNIXERROR(ERRDOS,ERRbadpath));
2376 * For CIFS UNIX extensions the target name may not exist.
2379 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2381 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
2382 set_bad_path_error(errno, bad_path);
2383 return(UNIXERROR(ERRDOS,ERRbadpath));
2387 if (!CAN_WRITE(conn))
2388 return ERROR_DOS(ERRSRV,ERRaccess);
2390 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2391 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2393 if (VALID_STAT(sbuf))
2394 unixmode = sbuf.st_mode;
2396 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
2397 tran_call,fname,info_level,total_data));
2399 /* Realloc the parameter and data sizes */
2400 params = Realloc(*pparams,2);
2401 if(params == NULL)
2402 return ERROR_DOS(ERRDOS,ERRnomem);
2403 *pparams = params;
2405 SSVAL(params,0,0);
2407 if (fsp) {
2408 /* the pending modtime overrides the current modtime */
2409 sbuf.st_mtime = fsp->pending_modtime;
2412 size = get_file_size(sbuf);
2413 tvs.modtime = sbuf.st_mtime;
2414 tvs.actime = sbuf.st_atime;
2415 dosmode = dos_mode(conn,fname,&sbuf);
2416 unixmode = sbuf.st_mode;
2418 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2419 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2421 switch (info_level) {
2422 case SMB_INFO_STANDARD:
2424 if (total_data < l1_cbFile+4)
2425 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2427 /* access time */
2428 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2430 /* write time */
2431 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2433 dosmode = SVAL(pdata,l1_attrFile);
2434 size = IVAL(pdata,l1_cbFile);
2435 break;
2438 case SMB_INFO_SET_EA:
2439 return(ERROR_DOS(ERRDOS,ERReasnotsupported));
2441 /* XXXX um, i don't think this is right.
2442 it's also not in the cifs6.txt spec.
2444 case SMB_INFO_QUERY_EAS_FROM_LIST:
2445 if (total_data < 28)
2446 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2448 tvs.actime = make_unix_date2(pdata+8);
2449 tvs.modtime = make_unix_date2(pdata+12);
2450 size = IVAL(pdata,16);
2451 dosmode = IVAL(pdata,24);
2452 break;
2454 /* XXXX nor this. not in cifs6.txt, either. */
2455 case SMB_INFO_QUERY_ALL_EAS:
2456 if (total_data < 28)
2457 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2459 tvs.actime = make_unix_date2(pdata+8);
2460 tvs.modtime = make_unix_date2(pdata+12);
2461 size = IVAL(pdata,16);
2462 dosmode = IVAL(pdata,24);
2463 break;
2465 case SMB_SET_FILE_BASIC_INFO:
2466 case SMB_FILE_BASIC_INFORMATION:
2468 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2469 time_t write_time;
2470 time_t changed_time;
2472 if (total_data < 36)
2473 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2475 /* Ignore create time at offset pdata. */
2477 /* access time */
2478 tvs.actime = interpret_long_date(pdata+8);
2480 write_time = interpret_long_date(pdata+16);
2481 changed_time = interpret_long_date(pdata+24);
2483 tvs.modtime = MIN(write_time, changed_time);
2485 if (write_time > tvs.modtime && write_time != 0xffffffff) {
2486 tvs.modtime = write_time;
2489 /* Prefer a defined time to an undefined one. */
2490 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2491 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2492 ? changed_time
2493 : write_time);
2495 /* attributes */
2496 dosmode = IVAL(pdata,32);
2497 break;
2500 case SMB_FILE_ALLOCATION_INFORMATION:
2501 case SMB_SET_FILE_ALLOCATION_INFO:
2503 int ret = -1;
2504 SMB_BIG_UINT allocation_size;
2506 if (total_data < 8)
2507 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2509 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
2510 #ifdef LARGE_SMB_OFF_T
2511 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
2512 #else /* LARGE_SMB_OFF_T */
2513 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2514 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2515 #endif /* LARGE_SMB_OFF_T */
2516 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2517 fname, (double)allocation_size ));
2519 if (allocation_size)
2520 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
2522 if(allocation_size != get_file_size(sbuf)) {
2523 SMB_STRUCT_STAT new_sbuf;
2525 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2526 fname, (double)allocation_size ));
2528 if (fd == -1) {
2529 files_struct *new_fsp = NULL;
2530 int access_mode = 0;
2531 int action = 0;
2533 if(global_oplock_break) {
2534 /* Queue this file modify as we are the process of an oplock break. */
2536 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2537 DEBUGADD(2,( "in oplock break state.\n"));
2539 push_oplock_pending_smb_message(inbuf, length);
2540 return -1;
2543 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2544 SET_OPEN_MODE(DOS_OPEN_RDWR),
2545 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2546 0, 0, &access_mode, &action);
2548 if (new_fsp == NULL)
2549 return(UNIXERROR(ERRDOS,ERRbadpath));
2550 ret = vfs_allocate_file_space(new_fsp, allocation_size);
2551 if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2552 DEBUG(3,("fstat of fnum %d failed (%s)\n",new_fsp->fnum, strerror(errno)));
2553 ret = -1;
2555 close_file(new_fsp,True);
2556 } else {
2557 ret = vfs_allocate_file_space(fsp, allocation_size);
2558 if (vfs_fstat(fsp,fd,&new_sbuf) != 0) {
2559 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2560 ret = -1;
2563 if (ret == -1)
2564 return ERROR_NT(NT_STATUS_DISK_FULL);
2566 /* Allocate can trucate size... */
2567 size = get_file_size(new_sbuf);
2570 break;
2573 case SMB_FILE_END_OF_FILE_INFORMATION:
2574 case SMB_SET_FILE_END_OF_FILE_INFO:
2576 if (total_data < 8)
2577 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2579 size = IVAL(pdata,0);
2580 #ifdef LARGE_SMB_OFF_T
2581 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2582 #else /* LARGE_SMB_OFF_T */
2583 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2584 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2585 #endif /* LARGE_SMB_OFF_T */
2586 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2587 break;
2590 case SMB_FILE_DISPOSITION_INFORMATION:
2591 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2593 BOOL delete_on_close;
2594 NTSTATUS status;
2596 if (total_data < 1)
2597 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2599 delete_on_close = (CVAL(pdata,0) ? True : False);
2601 if (tran_call != TRANSACT2_SETFILEINFO)
2602 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
2604 if (fsp == NULL)
2605 return(UNIXERROR(ERRDOS,ERRbadfid));
2607 status = set_delete_on_close_internal(fsp, delete_on_close);
2608 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2609 return ERROR_NT(status);
2611 /* The set is across all open files on this dev/inode pair. */
2612 status =set_delete_on_close_over_all(fsp, delete_on_close);
2613 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2614 return ERROR_NT(status);
2616 break;
2620 * CIFS UNIX extensions.
2623 case SMB_SET_FILE_UNIX_BASIC:
2625 uint32 raw_unixmode;
2627 if (total_data < 100)
2628 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2630 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
2631 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
2632 size=IVAL(pdata,0); /* first 8 Bytes are size */
2633 #ifdef LARGE_SMB_OFF_T
2634 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2635 #else /* LARGE_SMB_OFF_T */
2636 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2637 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2638 #endif /* LARGE_SMB_OFF_T */
2640 pdata+=24; /* ctime & st_blocks are not changed */
2641 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
2642 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
2643 pdata+=16;
2644 set_owner = (uid_t)IVAL(pdata,0);
2645 pdata += 8;
2646 set_grp = (gid_t)IVAL(pdata,0);
2647 pdata += 8;
2648 raw_unixmode = IVAL(pdata,28);
2649 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2650 dosmode = 0; /* Ensure dos mode change doesn't override this. */
2652 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2653 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2654 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2656 if (!VALID_STAT(sbuf)) {
2659 * The only valid use of this is to create character and block
2660 * devices, and named pipes. This is deprecated (IMHO) and
2661 * a new info level should be used for mknod. JRA.
2664 #if !defined(HAVE_MAKEDEV_FN)
2665 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2666 #else /* HAVE_MAKEDEV_FN */
2667 uint32 file_type = IVAL(pdata,0);
2668 uint32 dev_major = IVAL(pdata,4);
2669 uint32 dev_minor = IVAL(pdata,12);
2671 uid_t myuid = geteuid();
2672 gid_t mygid = getegid();
2673 SMB_DEV_T dev;
2675 if (tran_call == TRANSACT2_SETFILEINFO)
2676 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2678 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2679 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2681 dev = makedev(dev_major, dev_minor);
2683 /* We can only create as the owner/group we are. */
2685 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2686 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2687 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2688 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2690 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2691 file_type != UNIX_TYPE_FIFO)
2692 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2694 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2695 0%o for file %s\n", (double)dev, unixmode, fname ));
2697 /* Ok - do the mknod. */
2698 if (conn->vfs_ops.mknod(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
2699 return(UNIXERROR(ERRDOS,ERRnoaccess));
2701 SSVAL(params,0,0);
2702 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2703 return(-1);
2704 #endif /* HAVE_MAKEDEV_FN */
2709 * Deal with the UNIX specific mode set.
2712 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
2713 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2714 (unsigned int)unixmode, fname ));
2715 if (vfs_chmod(conn,fname,unixmode) != 0)
2716 return(UNIXERROR(ERRDOS,ERRnoaccess));
2720 * Deal with the UNIX specific uid set.
2723 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
2724 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2725 (unsigned int)set_owner, fname ));
2726 if (vfs_chown(conn,fname,set_owner, (gid_t)-1) != 0)
2727 return(UNIXERROR(ERRDOS,ERRnoaccess));
2731 * Deal with the UNIX specific gid set.
2734 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
2735 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2736 (unsigned int)set_owner, fname ));
2737 if (vfs_chown(conn,fname,(uid_t)-1, set_grp) != 0)
2738 return(UNIXERROR(ERRDOS,ERRnoaccess));
2740 break;
2743 case SMB_SET_FILE_UNIX_LINK:
2745 pstring link_dest;
2746 /* Set a symbolic link. */
2747 /* Don't allow this if follow links is false. */
2749 if (!lp_symlinks(SNUM(conn)))
2750 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2752 /* Disallow if already exists. */
2753 if (VALID_STAT(sbuf))
2754 return(ERROR_DOS(ERRDOS,ERRbadpath));
2756 pstrcpy(link_dest, pdata);
2758 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2759 return(UNIXERROR(ERRDOS,ERRnoaccess));
2760 dos_to_unix(link_dest);
2761 dos_to_unix(fname);
2763 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2764 fname, link_dest ));
2766 if (conn->vfs_ops.symlink(conn,link_dest,fname) != 0)
2767 return(UNIXERROR(ERRDOS,ERRnoaccess));
2768 SSVAL(params,0,0);
2769 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2770 return(-1);
2773 case SMB_SET_FILE_UNIX_HLINK:
2775 pstring link_dest;
2777 /* Set a hard link. */
2779 /* Disallow if already exists. */
2780 if (VALID_STAT(sbuf))
2781 return(ERROR_DOS(ERRDOS,ERRbadpath));
2783 pstrcpy(link_dest, pdata);
2785 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2786 return(UNIXERROR(ERRDOS,ERRnoaccess));
2788 dos_to_unix(link_dest);
2789 dos_to_unix(fname);
2791 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2792 fname, link_dest ));
2794 if (conn->vfs_ops.link(conn,link_dest,fname) != 0)
2795 return(UNIXERROR(ERRDOS,ERRnoaccess));
2796 SSVAL(params,0,0);
2797 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2798 return(-1);
2801 default:
2802 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2805 /* get some defaults (no modifications) if any info is zero or -1. */
2806 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2807 tvs.actime = sbuf.st_atime;
2809 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2810 tvs.modtime = sbuf.st_mtime;
2812 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2813 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2814 DEBUG(6,("size: %.0f ", (double)size));
2815 if (S_ISDIR(sbuf.st_mode))
2816 dosmode |= aDIR;
2817 else
2818 dosmode &= ~aDIR;
2820 DEBUG(6,("dosmode: %x\n" , dosmode));
2822 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2823 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2824 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2825 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2827 * Only do this test if we are not explicitly
2828 * changing the size of a file.
2830 if (!size)
2831 size = get_file_size(sbuf);
2835 * Try and set the times, size and mode of this file -
2836 * if they are different from the current values
2839 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2840 if(fsp != NULL) {
2842 * This was a setfileinfo on an open file.
2843 * NT does this a lot. It's actually pointless
2844 * setting the time here, as it will be overwritten
2845 * on the next write, so we save the request
2846 * away and will set it on file close. JRA.
2849 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2850 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n",
2851 ctime(&tvs.modtime) ));
2852 fsp->pending_modtime = tvs.modtime;
2855 } else {
2857 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2859 if(file_utime(conn, fname, &tvs)!=0)
2860 return(UNIXERROR(ERRDOS,ERRnoaccess));
2864 /* check the mode isn't different, before changing it */
2865 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
2867 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n",
2868 fname, dosmode ));
2870 if(file_chmod(conn, fname, dosmode, NULL)) {
2871 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2872 return(UNIXERROR(ERRDOS,ERRnoaccess));
2876 if(size != get_file_size(sbuf)) {
2878 int ret;
2880 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2881 fname, (double)size ));
2883 if (fd == -1) {
2884 files_struct *new_fsp = NULL;
2885 int access_mode = 0;
2886 int action = 0;
2888 if(global_oplock_break) {
2889 /* Queue this file modify as we are the process of an oplock break. */
2891 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2892 DEBUGADD(2,( "in oplock break state.\n"));
2894 push_oplock_pending_smb_message(inbuf, length);
2895 return -1;
2898 new_fsp = open_file_shared(conn, fname, &sbuf,
2899 SET_OPEN_MODE(DOS_OPEN_RDWR),
2900 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2901 0, 0, &access_mode, &action);
2903 if (new_fsp == NULL)
2904 return(UNIXERROR(ERRDOS,ERRbadpath));
2905 ret = vfs_set_filelen(new_fsp, size);
2906 close_file(new_fsp,True);
2907 } else {
2908 ret = vfs_set_filelen(fsp, size);
2911 if (ret == -1)
2912 return (UNIXERROR(ERRHRD,ERRdiskfull));
2915 SSVAL(params,0,0);
2916 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2917 return(-1);
2920 /****************************************************************************
2921 Reply to a TRANS2_MKDIR (make directory with extended attributes).
2922 ****************************************************************************/
2924 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2925 char **pparams, int total_params, char **ppdata, int total_data)
2927 char *params = *pparams;
2928 pstring directory;
2929 int ret = -1;
2930 SMB_STRUCT_STAT sbuf;
2931 BOOL bad_path = False;
2933 if (!CAN_WRITE(conn))
2934 return ERROR_DOS(ERRSRV,ERRaccess);
2936 if (total_params < 4)
2937 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2939 pstrcpy(directory, &params[4]);
2941 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
2943 unix_convert(directory,conn,0,&bad_path,&sbuf);
2944 if (check_name(directory,conn))
2945 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2947 if(ret < 0) {
2948 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
2949 set_bad_path_error(errno, bad_path);
2950 return(UNIXERROR(ERRDOS,ERRnoaccess));
2953 /* Realloc the parameter and data sizes */
2954 params = Realloc(*pparams,2);
2955 if(params == NULL)
2956 return ERROR_DOS(ERRDOS,ERRnomem);
2957 *pparams = params;
2959 SSVAL(params,0,0);
2961 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2963 return(-1);
2966 /****************************************************************************
2967 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
2968 We don't actually do this - we just send a null response.
2969 ****************************************************************************/
2971 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2972 char **pparams, int total_params, char **ppdata, int total_data)
2974 static uint16 fnf_handle = 257;
2975 char *params = *pparams;
2976 uint16 info_level;
2978 if (total_params < 6)
2979 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2981 info_level = SVAL(params,4);
2982 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
2984 switch (info_level) {
2985 case 1:
2986 case 2:
2987 break;
2988 default:
2989 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2992 /* Realloc the parameter and data sizes */
2993 params = Realloc(*pparams,6);
2994 if(params == NULL)
2995 return ERROR_DOS(ERRDOS,ERRnomem);
2996 *pparams = params;
2998 SSVAL(params,0,fnf_handle);
2999 SSVAL(params,2,0); /* No changes */
3000 SSVAL(params,4,0); /* No EA errors */
3002 fnf_handle++;
3004 if(fnf_handle == 0)
3005 fnf_handle = 257;
3007 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3009 return(-1);
3012 /****************************************************************************
3013 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3014 changes). Currently this does nothing.
3015 ****************************************************************************/
3017 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3018 char **pparams, int total_params, char **ppdata, int total_data)
3020 char *params = *pparams;
3022 DEBUG(3,("call_trans2findnotifynext\n"));
3024 /* Realloc the parameter and data sizes */
3025 params = Realloc(*pparams,4);
3026 if(params == NULL)
3027 return ERROR_DOS(ERRDOS,ERRnomem);
3028 *pparams = params;
3030 SSVAL(params,0,0); /* No changes */
3031 SSVAL(params,2,0); /* No EA errors */
3033 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3035 return(-1);
3038 /****************************************************************************
3039 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3040 ****************************************************************************/
3042 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
3043 char **pparams, int total_params, char **ppdata, int total_data)
3045 char *params = *pparams;
3046 enum remote_arch_types ra_type = get_remote_arch();
3047 BOOL NT_arch = ((ra_type == RA_WINNT) || (ra_type == RA_WIN2K) || (ra_type == RA_WINXP) || (ra_type == RA_WIN2K3));
3048 pstring pathname;
3049 int reply_size = 0;
3050 int max_referral_level;
3052 DEBUG(10,("call_trans2getdfsreferral\n"));
3054 if (total_params < 2)
3055 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3057 max_referral_level = SVAL(params,0);
3059 if(!lp_host_msdfs())
3060 return ERROR_DOS(ERRDOS,ERRbadfunc);
3062 /* if pathname is in UNICODE, convert to DOS */
3063 /* NT always sends in UNICODE, may not set UNICODE flag */
3064 if(NT_arch || (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS)) {
3065 unistr_to_dos(pathname, &params[2], sizeof(pathname));
3066 DEBUG(10,("UNICODE referral for %s\n",pathname));
3067 } else
3068 pstrcpy(pathname,&params[2]);
3070 if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
3071 return ERROR_DOS(ERRDOS,ERRbadfile);
3073 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_UNICODE_STRINGS | FLAGS2_DFS_PATHNAMES);
3074 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3076 return(-1);
3079 #define LMCAT_SPL 0x53
3080 #define LMFUNC_GETJOBID 0x60
3082 /****************************************************************************
3083 reply to a TRANS2_IOCTL - used for OS/2 printing.
3084 ****************************************************************************/
3086 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
3087 char **pparams, int total_params, char **ppdata, int total_data)
3089 char *pdata = *ppdata;
3090 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3092 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3093 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3094 pdata = Realloc(*ppdata, 32);
3095 if(pdata == NULL)
3096 return ERROR_DOS(ERRDOS,ERRnomem);
3097 *ppdata = pdata;
3099 SSVAL(pdata,0,fsp->print_jobid); /* Job number */
3100 StrnCpy(pdata+2, global_myname, 15); /* Our NetBIOS name */
3101 StrnCpy(pdata+18, lp_servicename(SNUM(conn)), 13); /* Service name */
3102 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3103 return(-1);
3104 } else {
3105 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3106 return ERROR_DOS(ERRSRV,ERRerror);
3110 /****************************************************************************
3111 Reply to a SMBfindclose (stop trans2 directory search).
3112 ****************************************************************************/
3114 int reply_findclose(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3116 int outsize = 0;
3117 int dptr_num=SVALS(inbuf,smb_vwv0);
3118 START_PROFILE(SMBfindclose);
3120 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3122 dptr_close(&dptr_num);
3124 outsize = set_message(outbuf,0,0,True);
3126 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3128 END_PROFILE(SMBfindclose);
3129 return(outsize);
3132 /****************************************************************************
3133 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3134 ****************************************************************************/
3136 int reply_findnclose(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3138 int outsize = 0;
3139 int dptr_num= -1;
3140 START_PROFILE(SMBfindnclose);
3142 dptr_num = SVAL(inbuf,smb_vwv0);
3144 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3146 /* We never give out valid handles for a
3147 findnotifyfirst - so any dptr_num is ok here.
3148 Just ignore it. */
3150 outsize = set_message(outbuf,0,0,True);
3152 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3154 END_PROFILE(SMBfindnclose);
3155 return(outsize);
3158 /****************************************************************************
3159 Reply to a SMBtranss2 - just ignore it!
3160 ****************************************************************************/
3162 int reply_transs2(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3164 START_PROFILE(SMBtranss2);
3165 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3166 END_PROFILE(SMBtranss2);
3167 return(-1);
3170 /****************************************************************************
3171 Reply to a SMBtrans2.
3172 ****************************************************************************/
3174 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3176 int outsize = 0;
3177 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3178 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3179 #if 0
3180 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3181 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3182 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3183 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3184 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3185 int32 timeout = IVALS(inbuf,smb_timeout);
3186 #endif
3187 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3188 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3189 char *params = NULL, *data = NULL;
3190 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
3191 START_PROFILE(SMBtrans2);
3193 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3194 /* Queue this open message as we are the process of an
3195 * oplock break. */
3197 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3198 DEBUGADD(2,( "in oplock break state.\n"));
3200 push_oplock_pending_smb_message(inbuf, length);
3201 END_PROFILE(SMBtrans2);
3202 return -1;
3205 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3206 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3207 END_PROFILE(SMBtrans2);
3208 return ERROR_DOS(ERRSRV,ERRaccess);
3211 outsize = set_message(outbuf,0,0,True);
3213 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3214 is so as a sanity check */
3215 if (suwcnt != 1) {
3217 * Need to have rc=0 for ioctl to get job id for OS/2.
3218 * Network printing will fail if function is not successful.
3219 * Similar function in reply.c will be used if protocol
3220 * is LANMAN1.0 instead of LM1.2X002.
3221 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3222 * outbuf doesn't have to be set(only job id is used).
3224 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3225 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3226 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3227 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3228 } else {
3229 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
3230 DEBUG(2,("Transaction is %d\n",tran_call));
3231 END_PROFILE(SMBtrans2);
3232 ERROR_DOS(ERRDOS,ERRinvalidparam);
3236 /* Allocate the space for the maximum needed parameters and data */
3237 if (total_params > 0)
3238 params = (char *)malloc(total_params);
3239 if (total_data > 0)
3240 data = (char *)malloc(total_data);
3242 if ((total_params && !params) || (total_data && !data)) {
3243 DEBUG(2,("Out of memory in reply_trans2\n"));
3244 SAFE_FREE(params);
3245 SAFE_FREE(data);
3246 END_PROFILE(SMBtrans2);
3247 return ERROR_DOS(ERRDOS,ERRnomem);
3250 /* Copy the param and data bytes sent with this request into
3251 the params buffer */
3252 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3253 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3255 if (num_params > total_params || num_data > total_data)
3256 exit_server("invalid params in reply_trans2");
3258 if(params) {
3259 unsigned int psoff = SVAL(inbuf, smb_psoff);
3260 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
3261 goto bad_param;
3262 if (smb_base(inbuf) + psoff + num_params > inbuf + length)
3263 goto bad_param;
3264 memcpy( params, smb_base(inbuf) + psoff, num_params);
3266 if(data) {
3267 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
3268 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
3269 goto bad_param;
3270 if (smb_base(inbuf) + dsoff + num_data > inbuf + length)
3271 goto bad_param;
3272 memcpy( data, smb_base(inbuf) + dsoff, num_data);
3275 if(num_data_sofar < total_data || num_params_sofar < total_params) {
3276 /* We need to send an interim response then receive the rest
3277 of the parameter/data bytes */
3278 outsize = set_message(outbuf,0,0,True);
3279 if (!send_smb(smbd_server_fd(),outbuf))
3280 exit_server("reply_trans2: send_smb failed.");
3282 while (num_data_sofar < total_data ||
3283 num_params_sofar < total_params) {
3284 BOOL ret;
3285 unsigned int param_disp;
3286 unsigned int param_off;
3287 unsigned int data_disp;
3288 unsigned int data_off;
3290 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3292 if ((ret &&
3293 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3294 outsize = set_message(outbuf,0,0,True);
3295 if(ret)
3296 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3297 else
3298 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3299 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3300 goto bad_param;
3303 /* Revise total_params and total_data in case
3304 they have changed downwards */
3305 if (SVAL(inbuf, smb_tpscnt) < total_params)
3306 total_params = SVAL(inbuf, smb_tpscnt);
3307 if (SVAL(inbuf, smb_tdscnt) < total_data)
3308 total_data = SVAL(inbuf, smb_tdscnt);
3310 num_params = SVAL(inbuf,smb_spscnt);
3311 param_off = SVAL(inbuf, smb_spsoff);
3312 param_disp = SVAL(inbuf, smb_spsdisp);
3313 num_params_sofar += num_params;
3315 num_data = SVAL(inbuf, smb_sdscnt);
3316 data_off = SVAL(inbuf, smb_sdsoff);
3317 data_disp = SVAL(inbuf, smb_sdsdisp);
3318 num_data_sofar += num_data;
3320 if (num_params_sofar > total_params || num_data_sofar > total_data)
3321 goto bad_param;
3323 if (num_params) {
3324 if (param_disp + num_params >= total_params)
3325 goto bad_param;
3326 if ((param_disp + num_params < param_disp) ||
3327 (param_disp + num_params < num_params))
3328 goto bad_param;
3329 if (smb_base(inbuf) + param_off + num_params >= inbuf + bufsize)
3330 goto bad_param;
3331 if (params + param_disp < params)
3332 goto bad_param;
3334 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
3336 if (num_data) {
3337 if (data_disp + num_data >= total_data)
3338 goto bad_param;
3339 if ((data_disp + num_data < data_disp) ||
3340 (data_disp + num_data < num_data))
3341 goto bad_param;
3342 if (smb_base(inbuf) + data_off + num_data >= inbuf + bufsize)
3343 goto bad_param;
3344 if (data + data_disp < data)
3345 goto bad_param;
3347 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
3352 if (Protocol >= PROTOCOL_NT1)
3353 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_IS_LONG_NAME);
3355 /* Now we must call the relevant TRANS2 function */
3356 switch(tran_call) {
3357 case TRANSACT2_OPEN:
3358 START_PROFILE_NESTED(Trans2_open);
3359 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
3360 &params, total_params, &data, total_data);
3361 END_PROFILE_NESTED(Trans2_open);
3362 break;
3364 case TRANSACT2_FINDFIRST:
3365 START_PROFILE_NESTED(Trans2_findfirst);
3366 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3367 &params, total_params, &data, total_data);
3368 END_PROFILE_NESTED(Trans2_findfirst);
3369 break;
3371 case TRANSACT2_FINDNEXT:
3372 START_PROFILE_NESTED(Trans2_findnext);
3373 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
3374 &params, total_params, &data, total_data);
3375 END_PROFILE_NESTED(Trans2_findnext);
3376 break;
3378 case TRANSACT2_QFSINFO:
3379 START_PROFILE_NESTED(Trans2_qfsinfo);
3380 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3381 &params, total_params, &data, total_data);
3382 END_PROFILE_NESTED(Trans2_qfsinfo);
3383 break;
3385 case TRANSACT2_SETFSINFO:
3386 START_PROFILE_NESTED(Trans2_setfsinfo);
3387 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
3388 &params, total_params, &data, total_data);
3389 END_PROFILE_NESTED(Trans2_setfsinfo);
3390 break;
3392 case TRANSACT2_QPATHINFO:
3393 case TRANSACT2_QFILEINFO:
3394 START_PROFILE_NESTED(Trans2_qpathinfo);
3395 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3396 &params, total_params, &data, total_data);
3397 END_PROFILE_NESTED(Trans2_qpathinfo);
3398 break;
3399 case TRANSACT2_SETPATHINFO:
3400 case TRANSACT2_SETFILEINFO:
3401 START_PROFILE_NESTED(Trans2_setpathinfo);
3402 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3403 &params, total_params, &data, total_data);
3404 END_PROFILE_NESTED(Trans2_setpathinfo);
3405 break;
3407 case TRANSACT2_FINDNOTIFYFIRST:
3408 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3409 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
3410 &params, total_params, &data, total_data);
3411 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3412 break;
3414 case TRANSACT2_FINDNOTIFYNEXT:
3415 START_PROFILE_NESTED(Trans2_findnotifynext);
3416 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
3417 &params, total_params, &data, total_data);
3418 END_PROFILE_NESTED(Trans2_findnotifynext);
3419 break;
3420 case TRANSACT2_MKDIR:
3421 START_PROFILE_NESTED(Trans2_mkdir);
3422 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3423 &params, total_params, &data, total_data);
3424 END_PROFILE_NESTED(Trans2_mkdir);
3425 break;
3427 case TRANSACT2_GET_DFS_REFERRAL:
3428 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3429 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3430 &params, total_params, &data, total_data);
3431 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3432 break;
3433 case TRANSACT2_IOCTL:
3434 START_PROFILE_NESTED(Trans2_ioctl);
3435 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3436 &params, total_params, &data, total_data);
3437 END_PROFILE_NESTED(Trans2_ioctl);
3438 break;
3439 default:
3440 /* Error in request */
3441 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3442 SAFE_FREE(params);
3443 SAFE_FREE(data);
3444 END_PROFILE(SMBtrans2);
3445 return ERROR_DOS(ERRSRV,ERRerror);
3448 /* As we do not know how many data packets will need to be
3449 returned here the various call_trans2xxxx calls
3450 must send their own. Thus a call_trans2xxx routine only
3451 returns a value other than -1 when it wants to send
3452 an error packet.
3455 SAFE_FREE(params);
3456 SAFE_FREE(data);
3457 END_PROFILE(SMBtrans2);
3458 return outsize; /* If a correct response was needed the
3459 call_trans2xxx calls have already sent
3460 it. If outsize != -1 then it is returning */
3462 bad_param:
3464 SAFE_FREE(params);
3465 SAFE_FREE(data);
3466 END_PROFILE(SMBtrans2);
3467 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);