Fix delete on close semantics to match W2K. I (think:-) I understand it now :-).
[Samba.git] / source / smbd / trans2.c
blobfa10331826899769dae8d94783e0b3352814fec0
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;
220 int16 namelen;
222 pstring fname;
223 mode_t unixmode;
224 SMB_OFF_T size=0;
225 int fmode=0,mtime=0,rmode;
226 SMB_INO_T inode = 0;
227 SMB_STRUCT_STAT sbuf;
228 int smb_action = 0;
229 BOOL bad_path = False;
230 files_struct *fsp;
233 * Ensure we have enough parameters to perform the operation.
236 if (total_params < 29)
237 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
239 open_mode = SVAL(params, 2);
240 open_attr = SVAL(params,6);
241 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
242 #if 0
243 return_additional_info = BITSETW(params,0);
244 open_sattr = SVAL(params, 4);
245 open_time = make_unix_date3(params+8);
246 #endif
247 open_ofun = SVAL(params,12);
248 open_size = IVAL(params,14);
249 pname = &params[28];
250 namelen = strlen(pname)+1;
252 StrnCpy(fname,pname,namelen);
254 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
255 fname,open_mode, open_attr, open_ofun, open_size));
257 if (IS_IPC(conn))
258 return(ERROR_DOS(ERRSRV,ERRaccess));
260 /* XXXX we need to handle passed times, sattr and flags */
262 unix_convert(fname,conn,0,&bad_path,&sbuf);
264 if (!check_name(fname,conn)) {
265 set_bad_path_error(errno, bad_path);
266 return(UNIXERROR(ERRDOS,ERRnoaccess));
269 unixmode = unix_mode(conn,open_attr | aARCH, fname);
271 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode,
272 oplock_request, &rmode,&smb_action);
274 if (!fsp) {
275 set_bad_path_error(errno, bad_path);
276 return(UNIXERROR(ERRDOS,ERRnoaccess));
279 size = get_file_size(sbuf);
280 fmode = dos_mode(conn,fname,&sbuf);
281 mtime = sbuf.st_mtime;
282 inode = sbuf.st_ino;
283 if (fmode & aDIR) {
284 close_file(fsp,False);
285 return(ERROR_DOS(ERRDOS,ERRnoaccess));
288 /* Realloc the size of parameters and data we will return */
289 params = Realloc(*pparams, 28);
290 if( params == NULL )
291 return(ERROR_DOS(ERRDOS,ERRnomem));
292 *pparams = params;
294 memset((char *)params,'\0',28);
295 SSVAL(params,0,fsp->fnum);
296 SSVAL(params,2,fmode);
297 put_dos_date2(params,4, mtime);
298 SIVAL(params,8, (uint32)size);
299 SSVAL(params,12,rmode);
301 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
302 smb_action |= EXTENDED_OPLOCK_GRANTED;
304 SSVAL(params,18,smb_action);
307 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
309 SIVAL(params,20,inode);
311 /* Send the required number of replies */
312 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
314 return -1;
317 /*********************************************************
318 Routine to check if a given string matches exactly.
319 as a special case a mask of "." does NOT match. That
320 is required for correct wildcard semantics
321 Case can be significant or not.
322 **********************************************************/
324 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
326 if (mask[0] == '.' && mask[1] == 0)
327 return False;
328 if (case_sig)
329 return strcmp(str,mask)==0;
330 return strcasecmp(str,mask) == 0;
333 /****************************************************************************
334 Return the filetype for UNIX extensions.
335 ****************************************************************************/
337 static uint32 unix_filetype(mode_t mode)
339 if(S_ISREG(mode))
340 return UNIX_TYPE_FILE;
341 else if(S_ISDIR(mode))
342 return UNIX_TYPE_DIR;
343 #ifdef S_ISLNK
344 else if(S_ISLNK(mode))
345 return UNIX_TYPE_SYMLINK;
346 #endif
347 #ifdef S_ISCHR
348 else if(S_ISCHR(mode))
349 return UNIX_TYPE_CHARDEV;
350 #endif
351 #ifdef S_ISBLK
352 else if(S_ISBLK(mode))
353 return UNIX_TYPE_BLKDEV;
354 #endif
355 #ifdef S_ISFIFO
356 else if(S_ISFIFO(mode))
357 return UNIX_TYPE_FIFO;
358 #endif
359 #ifdef S_ISSOCK
360 else if(S_ISSOCK(mode))
361 return UNIX_TYPE_SOCKET;
362 #endif
364 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
365 return UNIX_TYPE_UNKNOWN;
368 /****************************************************************************
369 Return the major devicenumber for UNIX extensions.
370 ****************************************************************************/
372 static uint32 unix_dev_major(SMB_DEV_T dev)
374 #if defined(HAVE_DEVICE_MAJOR_FN)
375 return (uint32)major(dev);
376 #else
377 return (uint32)(dev >> 8);
378 #endif
381 /****************************************************************************
382 Return the minor devicenumber for UNIX extensions.
383 ****************************************************************************/
385 static uint32 unix_dev_minor(SMB_DEV_T dev)
387 #if defined(HAVE_DEVICE_MINOR_FN)
388 return (uint32)minor(dev);
389 #else
390 return (uint32)(dev & 0xff);
391 #endif
394 /****************************************************************************
395 Map wire perms onto standard UNIX permissions. Obey share restrictions.
396 ****************************************************************************/
398 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
400 mode_t ret = 0;
402 if (perms == SMB_MODE_NO_CHANGE)
403 return pst->st_mode;
405 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
406 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
407 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
408 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
409 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
410 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
411 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
412 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
413 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
414 #ifdef S_ISVTX
415 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
416 #endif
417 #ifdef S_ISGID
418 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
419 #endif
420 #ifdef S_ISUID
421 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
422 #endif
424 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
425 ret &= lp_dir_mask(SNUM(conn));
426 /* Add in force bits */
427 ret |= lp_force_dir_mode(SNUM(conn));
428 } else {
429 /* Apply mode mask */
430 ret &= lp_create_mask(SNUM(conn));
431 /* Add in force bits */
432 ret |= lp_force_create_mode(SNUM(conn));
435 return ret;
438 /****************************************************************************
439 checks for SMB_TIME_NO_CHANGE and if not found
440 calls interpret_long_date
441 ****************************************************************************/
442 time_t interpret_long_unix_date(char *p)
444 DEBUG(1,("interpret_long_unix_date\n"));
445 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
446 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
447 return -1;
448 } else {
449 return interpret_long_date(p);
453 /****************************************************************************
454 Get a level dependent lanman2 dir entry.
455 ****************************************************************************/
457 static BOOL get_lanman2_dir_entry(connection_struct *conn,
458 char *path_mask,int dirtype,int info_level,
459 int requires_resume_key,
460 BOOL dont_descend,char **ppdata,
461 char *base_data, int space_remaining,
462 BOOL *out_of_space, BOOL *got_exact_match,
463 int *last_name_off)
465 char *dname;
466 BOOL found = False;
467 SMB_STRUCT_STAT sbuf;
468 pstring mask;
469 pstring pathreal;
470 pstring fname;
471 char *p, *pdata = *ppdata;
472 uint32 reskey=0;
473 int prev_dirpos=0;
474 int mode=0;
475 SMB_OFF_T size = 0;
476 SMB_BIG_UINT allocation_size = 0;
477 uint32 len;
478 time_t mdate=0, adate=0, cdate=0;
479 char *nameptr;
480 BOOL was_8_3;
481 int nt_extmode; /* Used for NT connections instead of mode */
482 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
484 *fname = 0;
485 *out_of_space = False;
486 *got_exact_match = False;
488 if (!conn->dirptr)
489 return(False);
491 p = strrchr(path_mask,'/');
492 if(p != NULL) {
493 if(p[1] == '\0')
494 pstrcpy(mask,"*.*");
495 else
496 pstrcpy(mask, p+1);
497 } else
498 pstrcpy(mask, path_mask);
500 while (!found) {
501 BOOL got_match;
503 /* Needed if we run out of space */
504 prev_dirpos = TellDir(conn->dirptr);
505 dname = ReadDirName(conn->dirptr);
508 * Due to bugs in NT client redirectors we are not using
509 * resume keys any more - set them to zero.
510 * Check out the related comments in findfirst/findnext.
511 * JRA.
514 reskey = 0;
516 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
517 (long)conn->dirptr,TellDir(conn->dirptr)));
519 if (!dname)
520 return(False);
522 pstrcpy(fname,dname);
524 if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
525 got_match = mask_match(fname, mask, case_sensitive);
527 if(!got_match && !mangle_is_8_3(fname, False)) {
530 * It turns out that NT matches wildcards against
531 * both long *and* short names. This may explain some
532 * of the wildcard wierdness from old DOS clients
533 * that some people have been seeing.... JRA.
536 pstring newname;
537 pstrcpy( newname, fname);
538 mangle_map( newname, True, False, SNUM(conn));
539 if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
540 got_match = mask_match(newname, mask, case_sensitive);
543 if(got_match) {
544 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
545 if (dont_descend && !isdots)
546 continue;
548 pstrcpy(pathreal,conn->dirpath);
549 if(needslash)
550 pstrcat(pathreal,"/");
551 pstrcat(pathreal,dname);
553 if (INFO_LEVEL_IS_UNIX(info_level)) {
554 if (vfs_lstat(conn,pathreal,&sbuf) != 0) {
555 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
556 pathreal,strerror(errno)));
557 continue;
559 } else if (vfs_stat(conn,pathreal,&sbuf) != 0) {
561 /* Needed to show the msdfs symlinks as
562 * directories */
564 if(lp_host_msdfs() &&
565 lp_msdfs_root(SNUM(conn)) &&
566 is_msdfs_link(conn, pathreal, NULL, NULL,
567 &sbuf)) {
569 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
570 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
572 } else {
574 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
575 pathreal,strerror(errno)));
576 continue;
580 mode = dos_mode(conn,pathreal,&sbuf);
582 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
583 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
584 continue;
587 size = get_file_size(sbuf);
588 allocation_size = get_allocation_size(NULL,&sbuf);
589 mdate = sbuf.st_mtime;
590 adate = sbuf.st_atime;
591 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
593 if (lp_dos_filetime_resolution(SNUM(conn))) {
594 cdate &= ~1;
595 mdate &= ~1;
596 adate &= ~1;
599 if(mode & aDIR)
600 size = 0;
602 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
604 found = True;
608 mangle_map(fname,False,True,SNUM(conn));
610 p = pdata;
611 nameptr = p;
613 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
615 switch (info_level) {
616 case 1:
617 if(requires_resume_key) {
618 SIVAL(p,0,reskey);
619 p += 4;
621 put_dos_date2(p,l1_fdateCreation,cdate);
622 put_dos_date2(p,l1_fdateLastAccess,adate);
623 put_dos_date2(p,l1_fdateLastWrite,mdate);
624 SIVAL(p,l1_cbFile,(uint32)size);
625 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
626 SSVAL(p,l1_attrFile,mode);
627 SCVAL(p,l1_cchName,strlen(fname));
628 pstrcpy(p + l1_achName, fname);
629 nameptr = p + l1_achName;
630 p += l1_achName + strlen(fname) + 1;
631 break;
633 case 2:
634 if(requires_resume_key) {
635 SIVAL(p,0,reskey);
636 p += 4;
638 put_dos_date2(p,l2_fdateCreation,cdate);
639 put_dos_date2(p,l2_fdateLastAccess,adate);
640 put_dos_date2(p,l2_fdateLastWrite,mdate);
641 SIVAL(p,l2_cbFile,(uint32)size);
642 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
643 SSVAL(p,l2_attrFile,mode);
644 SIVAL(p,l2_cbList,0); /* No extended attributes */
645 SCVAL(p,l2_cchName,strlen(fname));
646 pstrcpy(p + l2_achName, fname);
647 nameptr = p + l2_achName;
648 p += l2_achName + strlen(fname) + 1;
649 break;
651 case 3:
652 SIVAL(p,0,reskey);
653 put_dos_date2(p,4,cdate);
654 put_dos_date2(p,8,adate);
655 put_dos_date2(p,12,mdate);
656 SIVAL(p,16,(uint32)size);
657 SIVAL(p,20,(uint32)allocation_size);
658 SSVAL(p,24,mode);
659 SIVAL(p,26,4);
660 SCVAL(p,30,strlen(fname));
661 pstrcpy(p+31, fname);
662 nameptr = p+31;
663 p += 31 + strlen(fname) + 1;
664 break;
666 case 4:
667 if(requires_resume_key) {
668 SIVAL(p,0,reskey);
669 p += 4;
671 SIVAL(p,0,33+strlen(fname)+1);
672 put_dos_date2(p,4,cdate);
673 put_dos_date2(p,8,adate);
674 put_dos_date2(p,12,mdate);
675 SIVAL(p,16,(uint32)size);
676 SIVAL(p,20,(uint32)allocation_size);
677 SSVAL(p,24,mode);
678 SCVAL(p,32,strlen(fname));
679 pstrcpy(p + 33, fname);
680 nameptr = p+33;
681 p += 33 + strlen(fname) + 1;
682 break;
684 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
685 was_8_3 = mangle_is_8_3(fname, True);
686 len = 94+strlen(fname);
687 len = (len + 3) & ~3;
688 SIVAL(p,0,len); p += 4;
689 SIVAL(p,0,reskey); p += 4;
690 put_long_date(p,cdate); p += 8;
691 put_long_date(p,adate); p += 8;
692 put_long_date(p,mdate); p += 8;
693 put_long_date(p,mdate); p += 8;
694 SOFF_T(p,0,size);
695 SOFF_T(p,8,allocation_size);
696 p += 16;
697 SIVAL(p,0,nt_extmode); p += 4;
698 SIVAL(p,0,strlen(fname)); p += 4;
699 SIVAL(p,0,0); p += 4;
700 /* Clear the short name buffer. This is
701 * IMPORTANT as not doing so will trigger
702 * a Win2k client bug. JRA.
704 memset(p,'\0',26);
705 if (!was_8_3) {
706 fstring tmpname;
707 fstrcpy(tmpname,fname);
708 mangle_map(tmpname,True,True,SNUM(conn));
709 strupper(tmpname);
710 fstrcpy(p+2,tmpname);
711 SSVAL(p, 0, strlen(tmpname));
712 } else {
713 SSVAL(p,0,0);
714 *(p+2) = 0;
716 p += 2 + 24;
717 /* nameptr = p; */
718 pstrcpy(p,fname); p += strlen(p);
719 p = pdata + len;
720 break;
722 case SMB_FIND_FILE_DIRECTORY_INFO:
723 len = 64+strlen(fname);
724 len = (len + 3) & ~3;
725 SIVAL(p,0,len); p += 4;
726 SIVAL(p,0,reskey); p += 4;
727 put_long_date(p,cdate); p += 8;
728 put_long_date(p,adate); p += 8;
729 put_long_date(p,mdate); p += 8;
730 put_long_date(p,mdate); p += 8;
731 SOFF_T(p,0,size);
732 SOFF_T(p,8,allocation_size);
733 p += 16;
734 SIVAL(p,0,nt_extmode); p += 4;
735 SIVAL(p,0,strlen(fname)); p += 4;
736 pstrcpy(p,fname);
737 p = pdata + len;
738 break;
740 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
741 len = 68+strlen(fname);
742 len = (len + 3) & ~3;
743 SIVAL(p,0,len); p += 4;
744 SIVAL(p,0,reskey); p += 4;
745 put_long_date(p,cdate); p += 8;
746 put_long_date(p,adate); p += 8;
747 put_long_date(p,mdate); p += 8;
748 put_long_date(p,mdate); p += 8;
749 SOFF_T(p,0,size);
750 SOFF_T(p,8,allocation_size);
751 p += 16;
752 SIVAL(p,0,nt_extmode); p += 4;
753 SIVAL(p,0,strlen(fname)); p += 4;
754 SIVAL(p,0,0); p += 4;
755 pstrcpy(p,fname);
756 p = pdata + len;
757 break;
759 case SMB_FIND_FILE_NAMES_INFO:
760 len = 12+strlen(fname);
761 len = (len + 3) & ~3;
762 SIVAL(p,0,len); p += 4;
763 SIVAL(p,0,reskey); p += 4;
764 SIVAL(p,0,strlen(fname)); p += 4;
765 pstrcpy(p,fname);
766 p = pdata + len;
767 break;
769 /* CIFS UNIX Extension. */
771 case SMB_FIND_FILE_UNIX:
772 len = 108+strlen(fname)+1; /* (length of SMB_QUERY_FILE_UNIX_BASIC = 100)+4+4+strlen(fname)*/
773 /* +1 to be sure to transmit the termination of fname */
774 len = (len + 3) & ~3;
776 SIVAL(p,0,len); p+= 4; /* Offset from this structure to the beginning of the next one */
777 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
779 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
780 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
781 p+= 8;
783 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
784 p+= 8;
786 put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */
787 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
788 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
789 p+= 24;
791 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
792 SIVAL(p,4,0);
793 p+= 8;
795 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
796 SIVAL(p,4,0);
797 p+= 8;
799 SIVAL(p,0,unix_filetype(sbuf.st_mode));
800 p+= 4;
802 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
803 SIVAL(p,4,0);
804 p+= 8;
806 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
807 SIVAL(p,4,0);
808 p+= 8;
810 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
811 p+= 8;
813 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
814 SIVAL(p,4,0);
815 p+= 8;
817 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
818 SIVAL(p,4,0);
819 p+= 8;
821 /* End of SMB_QUERY_FILE_UNIX_BASIC */
822 pstrcpy(p,fname);
823 p=pdata+len;
825 break;
827 default:
828 return(False);
832 if (PTR_DIFF(p,pdata) > space_remaining) {
833 /* Move the dirptr back to prev_dirpos */
834 SeekDir(conn->dirptr, prev_dirpos);
835 *out_of_space = True;
836 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
837 return False; /* Not finished - just out of space */
840 /* Setup the last_filename pointer, as an offset from base_data */
841 *last_name_off = PTR_DIFF(nameptr,base_data);
842 /* Advance the data pointer to the next slot */
843 *ppdata = p;
845 return(found);
848 /****************************************************************************
849 Reply to a TRANS2_FINDFIRST.
850 ****************************************************************************/
852 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
853 char **pparams, int total_params, char **ppdata, int total_data)
855 /* We must be careful here that we don't return more than the
856 allowed number of data bytes. If this means returning fewer than
857 maxentries then so be it. We assume that the redirector has
858 enough room for the fixed number of parameter bytes it has
859 requested. */
860 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
861 char *params = *pparams;
862 char *pdata = *ppdata;
863 int dirtype;
864 int maxentries;
865 BOOL close_after_first;
866 BOOL close_if_end;
867 BOOL requires_resume_key;
868 int info_level;
869 pstring directory;
870 pstring mask;
871 char *p, *wcard;
872 int last_name_off=0;
873 int dptr_num = -1;
874 int numentries = 0;
875 int i;
876 BOOL finished = False;
877 BOOL dont_descend = False;
878 BOOL out_of_space = False;
879 int space_remaining;
880 BOOL bad_path = False;
881 SMB_STRUCT_STAT sbuf;
883 if (total_params < 12)
884 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
886 *directory = *mask = 0;
888 dirtype = SVAL(params,0);
889 maxentries = SVAL(params,2);
890 close_after_first = BITSETW(params+4,0);
891 close_if_end = BITSETW(params+4,1);
892 requires_resume_key = BITSETW(params+4,2);
893 info_level = SVAL(params,6);
895 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
896 close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
897 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
898 info_level, max_data_bytes));
900 switch (info_level) {
901 case 1:
902 case 2:
903 case 3:
904 case 4:
905 case SMB_FIND_FILE_DIRECTORY_INFO:
906 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
907 case SMB_FIND_FILE_NAMES_INFO:
908 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
909 break;
910 case SMB_FIND_FILE_UNIX:
911 if (!lp_unix_extensions())
912 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
913 break;
914 default:
915 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
918 pstrcpy(directory, params + 12); /* Complete directory path with wildcard mask appended */
920 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
922 DEBUG(5,("path=%s\n",directory));
924 unix_convert(directory,conn,0,&bad_path,&sbuf);
925 if(!check_name(directory,conn)) {
926 set_bad_path_error(errno, bad_path);
928 #if 0
929 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
930 if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && (get_remote_arch() == RA_WINNT)) {
931 unix_ERR_class = ERRDOS;
932 unix_ERR_code = ERRbaddirectory;
934 #endif
936 return(UNIXERROR(ERRDOS,ERRbadpath));
939 p = strrchr(directory,'/');
940 if(p == NULL) {
941 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
942 if((directory[0] == '.') && (directory[1] == '\0'))
943 pstrcpy(mask,"*");
944 else
945 pstrcpy(mask,directory);
946 pstrcpy(directory,"./");
947 } else {
948 pstrcpy(mask,p+1);
949 *p = 0;
952 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
954 pdata = Realloc(*ppdata, max_data_bytes + 1024);
955 if( pdata == NULL )
956 return(ERROR_DOS(ERRDOS,ERRnomem));
957 *ppdata = pdata;
958 memset((char *)pdata,'\0',max_data_bytes + 1024);
960 /* Realloc the params space */
961 params = Realloc(*pparams, 10);
962 if( params == NULL )
963 return ERROR_DOS(ERRDOS,ERRnomem);
964 *pparams = params;
966 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
967 if (dptr_num < 0)
968 return(UNIXERROR(ERRDOS,ERRbadfile));
970 /* Save the wildcard match and attribs we are using on this directory -
971 needed as lanman2 assumes these are being saved between calls */
973 if(!(wcard = strdup(mask))) {
974 dptr_close(&dptr_num);
975 return ERROR_DOS(ERRDOS,ERRnomem);
978 dptr_set_wcard(dptr_num, wcard);
979 dptr_set_attr(dptr_num, dirtype);
981 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
983 /* We don't need to check for VOL here as this is returned by
984 a different TRANS2 call. */
986 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
988 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
989 dont_descend = True;
991 p = pdata;
992 space_remaining = max_data_bytes;
993 out_of_space = False;
995 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
996 BOOL got_exact_match = False;
998 /* this is a heuristic to avoid seeking the dirptr except when
999 absolutely necessary. It allows for a filename of about 40 chars */
1001 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1002 out_of_space = True;
1003 finished = False;
1004 } else {
1005 finished = !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
1006 requires_resume_key,dont_descend,
1007 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1008 &last_name_off);
1011 if (finished && out_of_space)
1012 finished = False;
1014 if (!finished && !out_of_space)
1015 numentries++;
1018 * As an optimisation if we know we aren't looking
1019 * for a wildcard name (ie. the name matches the wildcard exactly)
1020 * then we can finish on any (first) match.
1021 * This speeds up large directory searches. JRA.
1024 if(got_exact_match)
1025 finished = True;
1027 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1030 /* Check if we can close the dirptr */
1032 if(close_after_first || (finished && close_if_end)) {
1033 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1034 dptr_close(&dptr_num);
1038 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1039 * from observation of NT.
1042 if(numentries == 0) {
1043 dptr_close(&dptr_num);
1044 return ERROR_DOS(ERRDOS,ERRbadfile);
1047 /* At this point pdata points to numentries directory entries. */
1049 /* Set up the return parameter block */
1050 SSVAL(params,0,dptr_num);
1051 SSVAL(params,2,numentries);
1052 SSVAL(params,4,finished);
1053 SSVAL(params,6,0); /* Never an EA error */
1054 SSVAL(params,8,last_name_off);
1056 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1058 if ((! *directory) && dptr_path(dptr_num))
1059 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1061 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1062 smb_fn_name(CVAL(inbuf,smb_com)),
1063 mask, directory, dirtype, numentries ) );
1066 * Force a name mangle here to ensure that the
1067 * mask as an 8.3 name is top of the mangled cache.
1068 * The reasons for this are subtle. Don't remove
1069 * this code unless you know what you are doing
1070 * (see PR#13758). JRA.
1073 if(!mangle_is_8_3_wildcards( mask, False))
1074 mangle_map(mask, True, True, SNUM(conn));
1076 return(-1);
1079 /****************************************************************************
1080 Reply to a TRANS2_FINDNEXT.
1081 ****************************************************************************/
1083 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1084 char **pparams, int total_params, char **ppdata, int total_data)
1086 /* We must be careful here that we don't return more than the
1087 allowed number of data bytes. If this means returning fewer than
1088 maxentries then so be it. We assume that the redirector has
1089 enough room for the fixed number of parameter bytes it has
1090 requested. */
1091 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1092 char *params = *pparams;
1093 char *pdata = *ppdata;
1094 int dptr_num;
1095 int maxentries;
1096 uint16 info_level;
1097 uint32 resume_key;
1098 BOOL close_after_request;
1099 BOOL close_if_end;
1100 BOOL requires_resume_key;
1101 BOOL continue_bit;
1102 pstring resume_name;
1103 pstring mask;
1104 pstring directory;
1105 char *p;
1106 uint16 dirtype;
1107 int numentries = 0;
1108 int i, last_name_off=0;
1109 BOOL finished = False;
1110 BOOL dont_descend = False;
1111 BOOL out_of_space = False;
1112 int space_remaining;
1114 if (total_params < 12)
1115 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1117 dptr_num = SVAL(params,0);
1118 maxentries = SVAL(params,2);
1119 info_level = SVAL(params,4);
1120 resume_key = IVAL(params,6);
1121 close_after_request = BITSETW(params+10,0);
1122 close_if_end = BITSETW(params+10,1);
1123 requires_resume_key = BITSETW(params+10,2);
1124 continue_bit = BITSETW(params+10,3);
1126 *mask = *directory = *resume_name = 0;
1128 pstrcpy( resume_name, params+12);
1130 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1131 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1132 resume_key = %d resume name = %s continue=%d level = %d\n",
1133 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1134 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1136 switch (info_level) {
1137 case 1:
1138 case 2:
1139 case 3:
1140 case 4:
1141 case SMB_FIND_FILE_DIRECTORY_INFO:
1142 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1143 case SMB_FIND_FILE_NAMES_INFO:
1144 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1145 break;
1146 case SMB_FIND_FILE_UNIX:
1147 if (!lp_unix_extensions())
1148 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1149 break;
1150 default:
1151 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1154 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1155 if(pdata == NULL)
1156 return ERROR_DOS(ERRDOS,ERRnomem);
1158 *ppdata = pdata;
1159 memset((char *)pdata,'\0',max_data_bytes + 1024);
1161 /* Realloc the params space */
1162 params = Realloc(*pparams, 6*SIZEOFWORD);
1163 if( params == NULL )
1164 return ERROR_DOS(ERRDOS,ERRnomem);
1165 *pparams = params;
1167 /* Check that the dptr is valid */
1168 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1169 return ERROR_DOS(ERRDOS,ERRnofiles);
1171 string_set(&conn->dirpath,dptr_path(dptr_num));
1173 /* Get the wildcard mask from the dptr */
1174 if((p = dptr_wcard(dptr_num))== NULL) {
1175 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1176 return ERROR_DOS(ERRDOS,ERRnofiles);
1178 pstrcpy(mask, p);
1179 pstrcpy(directory,conn->dirpath);
1181 /* Get the attr mask from the dptr */
1182 dirtype = dptr_attr(dptr_num);
1184 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1185 dptr_num, mask, dirtype, (long)conn->dirptr, TellDir(conn->dirptr)));
1187 /* We don't need to check for VOL here as this is returned by
1188 a different TRANS2 call. */
1190 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1191 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1192 dont_descend = True;
1194 p = pdata;
1195 space_remaining = max_data_bytes;
1196 out_of_space = False;
1199 * Seek to the correct position. We no longer use the resume key but
1200 * depend on the last file name instead.
1203 if(requires_resume_key && *resume_name && !continue_bit) {
1206 * Fix for NT redirector problem triggered by resume key indexes
1207 * changing between directory scans. We now return a resume key of 0
1208 * and instead look for the filename to continue from (also given
1209 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1210 * findfirst/findnext (as is usual) then the directory pointer
1211 * should already be at the correct place. Check this by scanning
1212 * backwards looking for an exact (ie. case sensitive) filename match.
1213 * If we get to the beginning of the directory and haven't found it then scan
1214 * forwards again looking for a match. JRA.
1217 int current_pos, start_pos;
1218 char *dname = NULL;
1219 void *dirptr = conn->dirptr;
1220 start_pos = TellDir(dirptr);
1222 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1223 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1225 SeekDir(dirptr, current_pos);
1226 dname = ReadDirName(dirptr);
1229 * Remember, name_map_mangle is called by
1230 * get_lanman2_dir_entry(), so the resume name
1231 * could be mangled. Ensure we do the same
1232 * here.
1235 if(dname != NULL)
1236 mangle_map( dname, False, True, SNUM(conn));
1238 if(dname && strcsequal( resume_name, dname)) {
1239 SeekDir(dirptr, current_pos+1);
1240 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1241 break;
1246 * Scan forward from start if not found going backwards.
1249 if(current_pos < 0) {
1250 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1251 SeekDir(dirptr, start_pos);
1252 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1255 * Remember, name_map_mangle is called by
1256 * get_lanman2_dir_entry(), so the resume name
1257 * could be mangled. Ensure we do the same
1258 * here.
1261 if(dname != NULL)
1262 mangle_map( dname, False, True, SNUM(conn));
1264 if(dname && strcsequal( resume_name, dname)) {
1265 SeekDir(dirptr, current_pos+1);
1266 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1267 break;
1269 } /* end for */
1270 } /* end if current_pos */
1271 } /* end if requires_resume_key && !continue_bit */
1273 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1274 BOOL got_exact_match = False;
1276 /* this is a heuristic to avoid seeking the dirptr except when
1277 absolutely necessary. It allows for a filename of about 40 chars */
1279 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1280 out_of_space = True;
1281 finished = False;
1282 } else {
1283 finished = !get_lanman2_dir_entry(conn,mask,dirtype,info_level,
1284 requires_resume_key,dont_descend,
1285 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1286 &last_name_off);
1289 if (finished && out_of_space)
1290 finished = False;
1292 if (!finished && !out_of_space)
1293 numentries++;
1296 * As an optimisation if we know we aren't looking
1297 * for a wildcard name (ie. the name matches the wildcard exactly)
1298 * then we can finish on any (first) match.
1299 * This speeds up large directory searches. JRA.
1302 if(got_exact_match)
1303 finished = True;
1305 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1308 /* Check if we can close the dirptr */
1309 if(close_after_request || (finished && close_if_end)) {
1310 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1311 dptr_close(&dptr_num); /* This frees up the saved mask */
1315 /* Set up the return parameter block */
1316 SSVAL(params,0,numentries);
1317 SSVAL(params,2,finished);
1318 SSVAL(params,4,0); /* Never an EA error */
1319 SSVAL(params,6,last_name_off);
1321 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1323 if ((! *directory) && dptr_path(dptr_num))
1324 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1326 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1327 smb_fn_name(CVAL(inbuf,smb_com)),
1328 mask, directory, dirtype, numentries ) );
1330 return(-1);
1333 /****************************************************************************
1334 Reply to a TRANS2_QFSINFO (query filesystem info).
1335 ****************************************************************************/
1337 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1338 char **pparams, int total_params, char **ppdata, int total_data)
1340 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1341 char *pdata = *ppdata;
1342 char *params = *pparams;
1343 uint16 info_level;
1344 int data_len;
1345 SMB_STRUCT_STAT st;
1346 char *vname = volume_label(SNUM(conn));
1347 int snum = SNUM(conn);
1348 char *fstype = lp_fstype(SNUM(conn));
1350 if (total_params < 2)
1351 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1353 info_level = SVAL(params,0);
1354 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1356 if(vfs_stat(conn,".",&st)!=0) {
1357 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1358 return ERROR_DOS(ERRSRV,ERRinvdevice);
1361 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1362 if ( pdata == NULL )
1363 return ERROR_DOS(ERRDOS,ERRnomem);
1365 *ppdata = pdata;
1366 memset((char *)pdata,'\0',max_data_bytes + 1024);
1368 switch (info_level) {
1369 case 1:
1371 SMB_BIG_UINT dfree,dsize,bsize;
1372 data_len = 18;
1373 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1374 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1375 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1376 SIVAL(pdata,l1_cUnit,dsize);
1377 SIVAL(pdata,l1_cUnitAvail,dfree);
1378 SSVAL(pdata,l1_cbSector,512);
1379 DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1380 (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1381 (unsigned int)dfree, 512));
1382 break;
1385 case 2:
1387 /* Return volume name */
1388 int volname_len = MIN(strlen(vname),11);
1389 data_len = l2_vol_szVolLabel + volname_len + 1;
1391 * Add volume serial number - hash of a combination of
1392 * the called hostname and the service name.
1394 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1395 SCVAL(pdata,l2_vol_cch,volname_len);
1396 StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
1397 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1398 (unsigned)st.st_ctime, volname_len,
1399 pdata+l2_vol_szVolLabel));
1400 break;
1403 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1404 case SMB_FS_ATTRIBUTE_INFORMATION:
1406 int fstype_len;
1407 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1408 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */
1409 #if 0 /* Old code. JRA. */
1410 SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */
1411 SIVAL(pdata,0,0x700FF);
1412 #endif /* Old code. */
1414 SIVAL(pdata,4,255); /* Max filename component length */
1415 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1416 and will think we can't do long filenames */
1417 fstype_len = dos_PutUniCode(pdata+12,unix_to_dos_static(fstype),sizeof(pstring), False);
1418 SIVAL(pdata,8,fstype_len);
1419 data_len = 12 + fstype_len;
1420 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1421 break;
1424 case SMB_QUERY_FS_LABEL_INFO:
1425 case SMB_FS_LABEL_INFORMATION:
1426 data_len = 4 + strlen(vname);
1427 SIVAL(pdata,0,strlen(vname));
1428 pstrcpy(pdata+4,vname);
1429 break;
1431 case SMB_QUERY_FS_VOLUME_INFO:
1432 case SMB_FS_VOLUME_INFORMATION:
1434 * Add volume serial number - hash of a combination of
1435 * the called hostname and the service name.
1437 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1438 (str_checksum(local_machine)<<16));
1440 /* NT4 always serves this up as unicode but expects it to be
1441 * delivered as ascii! (tridge && JRA)
1443 if ((get_remote_arch() != RA_WIN2K) && (global_client_caps & CAP_NT_SMBS)) {
1444 data_len = 18 + strlen(vname);
1445 SIVAL(pdata,12,strlen(vname));
1446 pstrcpy(pdata+18,vname);
1447 } else {
1448 int vnamelen;
1450 vnamelen = dos_PutUniCode(pdata+18, vname, sizeof(pstring), False);
1451 data_len = 18 + vnamelen;
1452 SIVAL(pdata,12,vnamelen);
1453 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1456 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n",
1457 (int)strlen(vname),vname));
1458 break;
1460 case SMB_QUERY_FS_SIZE_INFO:
1461 case SMB_FS_SIZE_INFORMATION:
1463 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1464 data_len = 24;
1465 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1466 block_size = lp_block_size(snum);
1467 if (bsize < block_size) {
1468 SMB_BIG_UINT factor = block_size/bsize;
1469 bsize = block_size;
1470 dsize /= factor;
1471 dfree /= factor;
1473 if (bsize > block_size) {
1474 SMB_BIG_UINT factor = bsize/block_size;
1475 bsize = block_size;
1476 dsize *= factor;
1477 dfree *= factor;
1479 bytes_per_sector = 512;
1480 sectors_per_unit = bsize/bytes_per_sector;
1481 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1482 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1483 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1484 SBIG_UINT(pdata,0,dsize);
1485 SBIG_UINT(pdata,8,dfree);
1486 SIVAL(pdata,16,sectors_per_unit);
1487 SIVAL(pdata,20,bytes_per_sector);
1488 break;
1491 case SMB_FS_FULL_SIZE_INFORMATION:
1493 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1494 data_len = 32;
1495 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1496 block_size = lp_block_size(snum);
1497 if (bsize < block_size) {
1498 SMB_BIG_UINT factor = block_size/bsize;
1499 bsize = block_size;
1500 dsize /= factor;
1501 dfree /= factor;
1503 if (bsize > block_size) {
1504 SMB_BIG_UINT factor = bsize/block_size;
1505 bsize = block_size;
1506 dsize *= factor;
1507 dfree *= factor;
1509 bytes_per_sector = 512;
1510 sectors_per_unit = bsize/bytes_per_sector;
1511 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1512 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1513 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1514 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1515 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1516 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1517 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1518 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1519 break;
1522 case SMB_QUERY_FS_DEVICE_INFO:
1523 case SMB_FS_DEVICE_INFORMATION:
1524 data_len = 8;
1525 SIVAL(pdata,0,0); /* dev type */
1526 SIVAL(pdata,4,0); /* characteristics */
1527 break;
1529 case SMB_FS_OBJECTID_INFORMATION:
1530 data_len = 64;
1531 break;
1534 * Query the version and capabilities of the CIFS UNIX extensions
1535 * in use.
1538 case SMB_QUERY_CIFS_UNIX_INFO:
1540 if (!lp_unix_extensions())
1541 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1543 data_len = 12;
1544 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
1545 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
1546 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
1547 break;
1549 case SMB_MAC_QUERY_FS_INFO:
1551 * Thursby MAC extension... ONLY on NTFS filesystems
1552 * once we do streams then we don't need this
1554 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1555 data_len = 88;
1556 SIVAL(pdata,84,0x100); /* Don't support mac... */
1557 break;
1559 /* drop through */
1560 default:
1561 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1564 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1566 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1568 return -1;
1571 /****************************************************************************
1572 Reply to a TRANS2_SETFSINFO (set filesystem info).
1573 ****************************************************************************/
1575 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1576 char **pparams, int total_params, char **ppdata, int total_data)
1578 /* Just say yes we did it - there is nothing that
1579 can be set here so it doesn't matter. */
1580 int outsize;
1581 DEBUG(3,("call_trans2setfsinfo\n"));
1583 if (!CAN_WRITE(conn))
1584 return(ERROR_DOS(ERRSRV,ERRaccess));
1586 outsize = set_message(outbuf,10,0,True);
1588 return outsize;
1591 /****************************************************************************
1592 Utility function to set bad path error.
1593 ****************************************************************************/
1595 NTSTATUS set_bad_path_error(int err, BOOL bad_path)
1597 if((err == ENOENT) && bad_path) {
1598 unix_ERR_class = ERRDOS;
1599 unix_ERR_code = ERRbadpath;
1600 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1602 return NT_STATUS_OK;
1605 /****************************************************************************
1606 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1607 file name or file id).
1608 ****************************************************************************/
1610 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1611 char **pparams, int total_params, char **ppdata, int total_data)
1613 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1614 char *params = *pparams;
1615 char *pdata = *ppdata;
1616 uint16 tran_call = SVAL(inbuf, smb_setup0);
1617 uint16 info_level;
1618 int mode=0;
1619 SMB_OFF_T size=0;
1620 SMB_BIG_UINT allocation_size = 0;
1621 unsigned int data_size;
1622 SMB_STRUCT_STAT sbuf;
1623 pstring fname1;
1624 char *fname;
1625 pstring dos_fname;
1626 char *fullpathname;
1627 char *p;
1628 int l;
1629 SMB_OFF_T pos = 0;
1630 BOOL bad_path = False;
1631 BOOL delete_pending = False;
1632 time_t c_time;
1633 files_struct *fsp = NULL;
1635 if (!params)
1636 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1638 if (tran_call == TRANSACT2_QFILEINFO) {
1639 if (total_params < 4)
1640 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1642 fsp = file_fsp(params,0);
1643 info_level = SVAL(params,2);
1645 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1647 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1649 * This is actually a QFILEINFO on a directory
1650 * handle (returned from an NT SMB). NT5.0 seems
1651 * to do this call. JRA.
1653 fname = fsp->fsp_name;
1654 unix_convert(fname,conn,0,&bad_path,&sbuf);
1655 if (!check_name(fname,conn)) {
1656 DEBUG(3,("call_trans2qfilepathinfo: check_name of %s failed (%s)\n",fname,strerror(errno)));
1657 set_bad_path_error(errno, bad_path);
1658 return(UNIXERROR(ERRDOS,ERRbadpath));
1661 if (INFO_LEVEL_IS_UNIX(info_level)) {
1662 /* Always do lstat for UNIX calls. */
1663 if (vfs_lstat(conn,fname,&sbuf)) {
1664 DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
1665 set_bad_path_error(errno, bad_path);
1666 return(UNIXERROR(ERRDOS,ERRbadpath));
1668 } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
1669 DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
1670 set_bad_path_error(errno, bad_path);
1671 return(UNIXERROR(ERRDOS,ERRbadpath));
1674 delete_pending = fsp->directory_delete_on_close;
1676 } else {
1678 * Original code - this is an open file.
1680 CHECK_FSP(fsp,conn);
1682 fname = fsp->fsp_name;
1683 if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) {
1684 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
1685 return(UNIXERROR(ERRDOS,ERRbadfid));
1688 if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1689 return(UNIXERROR(ERRDOS,ERRnoaccess));
1691 delete_pending = fsp->delete_on_close;
1693 } else {
1694 /* qpathinfo */
1695 if (total_params < 6)
1696 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1698 info_level = SVAL(params,0);
1700 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1702 fname = &fname1[0];
1703 pstrcpy(fname,&params[6]);
1705 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1707 unix_convert(fname,conn,0,&bad_path,&sbuf);
1708 if (!check_name(fname,conn)) {
1709 DEBUG(3,("call_trans2qfilepathinfo: check_name of %s failed (%s)\n",fname,strerror(errno)));
1710 set_bad_path_error(errno, bad_path);
1711 return(UNIXERROR(ERRDOS,ERRbadpath));
1713 if (INFO_LEVEL_IS_UNIX(info_level)) {
1714 /* Always do lstat for UNIX calls. */
1715 if (vfs_lstat(conn,fname,&sbuf)) {
1716 DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
1717 set_bad_path_error(errno, bad_path);
1718 return(UNIXERROR(ERRDOS,ERRbadpath));
1720 } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
1721 DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
1722 set_bad_path_error(errno, bad_path);
1723 return(UNIXERROR(ERRDOS,ERRbadpath));
1728 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
1729 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1731 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1732 fname,info_level,tran_call,total_data));
1734 p = strrchr(fname,'/');
1735 if (!p)
1736 p = fname;
1737 else
1738 p++;
1739 l = strlen(p);
1740 mode = dos_mode(conn,fname,&sbuf);
1741 fullpathname = fname;
1742 size = get_file_size(sbuf);
1743 allocation_size = get_allocation_size(fsp,&sbuf);
1744 if (mode & aDIR)
1745 size = 0;
1747 /* from now on we only want the part after the / */
1748 fname = p;
1750 params = Realloc(*pparams,2);
1751 if ( params == NULL )
1752 return ERROR_DOS(ERRDOS,ERRnomem);
1753 *pparams = params;
1754 memset((char *)params,'\0',2);
1755 data_size = max_data_bytes + 1024;
1756 pdata = Realloc(*ppdata, data_size);
1757 if ( pdata == NULL )
1758 return ERROR_DOS(ERRDOS,ERRnomem);
1759 *ppdata = pdata;
1761 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1762 /* uggh, EAs for OS2 */
1763 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1764 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1767 memset((char *)pdata,'\0',data_size);
1769 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1771 if (lp_dos_filetime_resolution(SNUM(conn))) {
1772 c_time &= ~1;
1773 sbuf.st_atime &= ~1;
1774 sbuf.st_mtime &= ~1;
1775 sbuf.st_mtime &= ~1;
1778 /* NT expects the name to be in an exact form */
1779 if (strequal(fname,"."))
1780 pstrcpy(dos_fname, "\\");
1781 else {
1782 snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname);
1783 string_replace( dos_fname, '/','\\');
1786 switch (info_level) {
1787 case SMB_INFO_STANDARD:
1788 case SMB_INFO_QUERY_EA_SIZE:
1789 data_size = (info_level==1?22:26);
1790 put_dos_date2(pdata,l1_fdateCreation,c_time);
1791 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1792 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1793 SIVAL(pdata,l1_cbFile,(uint32)size);
1794 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
1795 SSVAL(pdata,l1_attrFile,mode);
1796 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1797 break;
1799 case SMB_INFO_QUERY_EAS_FROM_LIST:
1800 data_size = 24;
1801 put_dos_date2(pdata,0,c_time);
1802 put_dos_date2(pdata,4,sbuf.st_atime);
1803 put_dos_date2(pdata,8,sbuf.st_mtime);
1804 SIVAL(pdata,12,(uint32)size);
1805 SIVAL(pdata,16,(uint32)allocation_size);
1806 SIVAL(pdata,20,mode);
1807 break;
1809 case SMB_INFO_QUERY_ALL_EAS:
1810 data_size = 4;
1811 SIVAL(pdata,0,data_size);
1812 break;
1814 case 6:
1815 return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */
1817 case SMB_FILE_BASIC_INFORMATION:
1818 case SMB_QUERY_FILE_BASIC_INFO:
1820 if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1821 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1822 else {
1823 data_size = 40;
1824 SIVAL(pdata,36,0);
1826 put_long_date(pdata,c_time);
1827 put_long_date(pdata+8,sbuf.st_atime);
1828 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1829 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1830 SIVAL(pdata,32,mode);
1832 DEBUG(5,("SMB_QFBI - "));
1835 time_t create_time = c_time;
1836 DEBUG(5,("create: %s ", ctime(&create_time)));
1839 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1840 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1841 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1842 DEBUG(5,("mode: %x\n", mode));
1844 break;
1846 case SMB_FILE_STANDARD_INFORMATION:
1847 case SMB_QUERY_FILE_STANDARD_INFO:
1849 data_size = 24;
1850 /* Fake up allocation size. */
1851 SOFF_T(pdata,0,allocation_size);
1852 SOFF_T(pdata,8,size);
1853 SIVAL(pdata,16,sbuf.st_nlink);
1854 SCVAL(pdata,20,0);
1855 SCVAL(pdata,21,(mode&aDIR)?1:0);
1856 break;
1858 case SMB_FILE_EA_INFORMATION:
1859 case SMB_QUERY_FILE_EA_INFO:
1860 data_size = 4;
1861 SIVAL(pdata,0,0);
1862 break;
1864 /* Get the 8.3 name - used if NT SMB was negotiated. */
1866 case SMB_QUERY_FILE_ALT_NAME_INFO:
1868 pstring short_name;
1869 pstrcpy(short_name,p);
1870 /* Mangle if not already 8.3 */
1871 if(!mangle_is_8_3(short_name, True)) {
1872 mangle_map(short_name,True,True,SNUM(conn));
1874 strupper(short_name);
1875 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1876 l = dos_PutUniCode(pdata + 4, short_name, sizeof(pstring), False);
1877 data_size = 4 + l;
1878 SIVAL(pdata,0,l);
1879 break;
1882 case SMB_QUERY_FILE_NAME_INFO:
1884 * The first part of this code is essential
1885 * to get security descriptors to work on mapped
1886 * drives. Don't ask how I discovered this unless
1887 * you like hearing about me suffering.... :-). JRA.
1890 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1891 l = dos_PutUniCode(pdata + 4, dos_fname,sizeof(pstring), False);
1892 data_size = 4 + l;
1893 SIVAL(pdata,0,l);
1894 break;
1896 case SMB_FILE_ALLOCATION_INFORMATION:
1897 case SMB_QUERY_FILE_ALLOCATION_INFO:
1898 data_size = 8;
1899 SOFF_T(pdata,0,allocation_size);
1900 break;
1902 case SMB_QUERY_FILE_END_OF_FILEINFO:
1903 case SMB_FILE_END_OF_FILE_INFORMATION:
1904 data_size = 8;
1905 SOFF_T(pdata,0,size);
1906 break;
1908 case SMB_QUERY_FILE_ALL_INFO:
1909 put_long_date(pdata,c_time);
1910 put_long_date(pdata+8,sbuf.st_atime);
1911 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1912 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1913 SIVAL(pdata,32,mode);
1914 pdata += 40;
1915 SOFF_T(pdata,0,allocation_size);
1916 SOFF_T(pdata,8,size);
1917 SIVAL(pdata,16,sbuf.st_nlink);
1918 SCVAL(pdata,20,delete_pending);
1919 SCVAL(pdata,21,(mode&aDIR)?1:0);
1920 pdata += 24;
1921 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);
1922 pdata += 8; /* index number */
1923 pdata += 4; /* EA info */
1924 if (mode & aRONLY)
1925 SIVAL(pdata,0,0xA9);
1926 else
1927 SIVAL(pdata,0,0xd01BF);
1928 pdata += 4;
1929 SOFF_T(pdata,0,pos); /* current offset */
1930 pdata += 8;
1931 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1932 pdata += 4;
1933 pdata += 4; /* alignment */
1934 SIVAL(pdata,0,l);
1935 pstrcpy(pdata+4,dos_fname);
1936 pdata += 4 + l;
1937 data_size = PTR_DIFF(pdata,(*ppdata));
1938 break;
1940 case SMB_FILE_INTERNAL_INFORMATION:
1941 /* This should be an index number - looks like dev/ino to me :-) */
1942 SIVAL(pdata,0,sbuf.st_dev);
1943 SIVAL(pdata,4,sbuf.st_ino);
1944 data_size = 8;
1945 break;
1947 case SMB_FILE_ACCESS_INFORMATION:
1948 SIVAL(pdata,0,0x12019F); /* ??? */
1949 data_size = 4;
1950 break;
1952 case SMB_FILE_NAME_INFORMATION:
1953 /* Pathname with leading '\'. */
1955 size_t byte_len;
1957 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
1958 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
1959 SIVAL(pdata,0,byte_len);
1960 data_size = 4 + byte_len;
1961 break;
1964 case SMB_FILE_DISPOSITION_INFORMATION:
1965 data_size = 1;
1966 SCVAL(pdata,0,delete_pending);
1967 break;
1969 case SMB_FILE_POSITION_INFORMATION:
1970 data_size = 8;
1971 SOFF_T(pdata,0,pos);
1972 break;
1974 case SMB_FILE_MODE_INFORMATION:
1975 SIVAL(pdata,0,mode);
1976 data_size = 4;
1977 break;
1979 case SMB_FILE_ALIGNMENT_INFORMATION:
1980 SIVAL(pdata,0,0); /* No alignment needed. */
1981 data_size = 4;
1982 break;
1984 #if 0
1985 /* Not yet finished... JRA */
1986 case 1018:
1988 size_t byte_len;
1990 put_long_date(pdata,c_time);
1991 put_long_date(pdata+8,sbuf.st_atime);
1992 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1993 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1994 SIVAL(pdata,32,mode);
1995 SIVAL(pdata,36,0); /* ??? */
1996 SIVAL(pdata,40,0x20); /* ??? */
1997 SIVAL(pdata,44,0); /* ??? */
1998 SOFF_T(pdata,48,size);
1999 SIVAL(pdata,56,0x1); /* ??? */
2000 SIVAL(pdata,60,0); /* ??? */
2001 SIVAL(pdata,64,0); /* ??? */
2002 SIVAL(pdata,68,length); /* Following string length in bytes. */
2003 dos_PutUniCode(pdata+72,,False);
2004 break;
2006 #endif
2008 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2009 /* Last component of pathname. */
2011 size_t byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2012 SIVAL(pdata,0,byte_len);
2013 data_size = 4 + byte_len;
2014 break;
2017 #if 0
2019 * NT4 server just returns "invalid query" to this - if we try to answer
2020 * it then NTws gets a BSOD! (tridge).
2021 * W2K seems to want this. JRA.
2023 case SMB_QUERY_FILE_STREAM_INFO:
2024 #endif
2025 case SMB_FILE_STREAM_INFORMATION:
2026 if (mode & aDIR) {
2027 data_size = 0;
2028 } else {
2029 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 14, False);
2030 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2)|FLAGS2_UNICODE_STRINGS);
2031 SIVAL(pdata,0,0); /* Next stream (none). */
2032 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2033 SOFF_T(pdata,8,size);
2034 SOFF_T(pdata,16,allocation_size);
2035 data_size = 24 + byte_len;
2037 break;
2039 case SMB_FILE_COMPRESSION_INFORMATION:
2040 SOFF_T(pdata,0,size);
2041 SIVAL(pdata,8,0); /* ??? */
2042 SIVAL(pdata,12,0); /* ??? */
2043 data_size = 16;
2044 break;
2046 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2047 put_long_date(pdata,c_time);
2048 put_long_date(pdata+8,sbuf.st_atime);
2049 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2050 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2051 SOFF_T(pdata,32,allocation_size); /* Allocation size. */
2052 SOFF_T(pdata,40,size);
2053 SIVAL(pdata,48,mode);
2054 SIVAL(pdata,52,0); /* ??? */
2055 data_size = 56;
2056 break;
2058 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2059 SIVAL(pdata,0,mode);
2060 SIVAL(pdata,4,0);
2061 data_size = 8;
2062 break;
2065 * CIFS UNIX Extensions.
2068 case SMB_QUERY_FILE_UNIX_BASIC:
2070 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2072 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2073 pdata += 8;
2075 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2076 pdata += 8;
2078 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2079 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2080 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2081 pdata += 24;
2083 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2084 SIVAL(pdata,4,0);
2085 pdata += 8;
2087 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2088 SIVAL(pdata,4,0);
2089 pdata += 8;
2091 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2092 pdata += 4;
2094 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2095 SIVAL(pdata,4,0);
2096 pdata += 8;
2098 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2099 SIVAL(pdata,4,0);
2100 pdata += 8;
2102 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2103 pdata += 8;
2105 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2106 SIVAL(pdata,4,0);
2107 pdata += 8;
2109 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2110 SIVAL(pdata,4,0);
2111 pdata += 8+1;
2112 data_size = PTR_DIFF(pdata,(*ppdata));
2115 int i;
2116 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2118 for (i=0; i<100; i++)
2119 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2120 DEBUG(4,("\n"));
2123 break;
2125 case SMB_QUERY_FILE_UNIX_LINK:
2127 pstring buffer;
2128 int len;
2130 #ifdef S_ISLNK
2131 if(!S_ISLNK(sbuf.st_mode))
2132 return(UNIXERROR(ERRSRV,ERRbadlink));
2133 #else
2134 return(UNIXERROR(ERRDOS,ERRbadlink));
2135 #endif
2136 len = conn->vfs_ops.readlink(conn,dos_to_unix_static(fullpathname), buffer, sizeof(pstring)-1); /* read link */
2137 if (len == -1)
2138 return(UNIXERROR(ERRDOS,ERRnoaccess));
2139 buffer[len] = 0;
2140 unix_to_dos(buffer);
2141 pstrcpy(pdata,buffer); /* write '\0' terminated string */
2142 pdata += strlen(buffer)+1;
2143 data_size = PTR_DIFF(pdata,(*ppdata));
2145 break;
2148 default:
2149 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2152 send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size);
2154 return(-1);
2157 /****************************************************************************
2158 Deal with the internal needs of setting the delete on close flag. Note that
2159 as the tdb locking is recursive, it is safe to call this from within
2160 open_file_shared. JRA.
2161 ****************************************************************************/
2163 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2166 * Only allow delete on close for writable shares.
2169 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2170 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2171 fsp->fsp_name ));
2172 return NT_STATUS_ACCESS_DENIED;
2175 * Only allow delete on close for files/directories opened with delete intent.
2178 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2179 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2180 fsp->fsp_name ));
2181 return NT_STATUS_ACCESS_DENIED;
2184 if(fsp->is_directory) {
2185 fsp->directory_delete_on_close = delete_on_close;
2186 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2187 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2188 } else {
2189 fsp->delete_on_close = delete_on_close;
2190 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2191 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2194 return NT_STATUS_OK;
2197 /****************************************************************************
2198 Sets the delete on close flag over all share modes on this file.
2199 Modify the share mode entry for all files open
2200 on this device and inode to tell other smbds we have
2201 changed the delete on close flag. This will be noticed
2202 in the close code, the last closer will delete the file
2203 if flag is set.
2204 ****************************************************************************/
2206 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2208 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2209 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2211 if (lock_share_entry_fsp(fsp) == False)
2212 return NT_STATUS_ACCESS_DENIED;
2214 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2215 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2216 fsp->fsp_name ));
2217 unlock_share_entry_fsp(fsp);
2218 return NT_STATUS_ACCESS_DENIED;
2221 unlock_share_entry_fsp(fsp);
2222 return NT_STATUS_OK;
2225 /****************************************************************************
2226 Returns true if this pathname is within the share, and thus safe.
2227 ****************************************************************************/
2229 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2231 #ifdef PATH_MAX
2232 char resolved_name[PATH_MAX+1];
2233 #else
2234 pstring resolved_name;
2235 #endif
2236 fstring last_component;
2237 pstring link_dest;
2238 pstring link_test;
2239 char *p;
2240 BOOL bad_path = False;
2241 SMB_STRUCT_STAT sbuf;
2243 pstrcpy(link_dest, link_dest_in);
2244 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2246 /* Store the UNIX converted path. */
2247 pstrcpy(link_dest_out, link_dest);
2249 p = strrchr(link_dest, '/');
2250 if (p) {
2251 fstrcpy(last_component, p+1);
2252 *p = '\0';
2253 } else {
2254 fstrcpy(last_component, link_dest);
2255 pstrcpy(link_dest, "./");
2258 if (conn->vfs_ops.realpath(conn,dos_to_unix_static(link_dest),resolved_name) == NULL)
2259 return -1;
2261 pstrcpy(link_dest, unix_to_dos_static(resolved_name));
2262 pstrcat(link_dest, "/");
2263 pstrcat(link_dest, last_component);
2265 if (*link_dest != '/') {
2266 /* Relative path. */
2267 pstrcpy(link_test, conn->connectpath);
2268 pstrcat(link_test, "/");
2269 pstrcat(link_test, link_dest);
2270 } else {
2271 pstrcpy(link_test, link_dest);
2275 * Check if the link is within the share.
2278 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2279 errno = EACCES;
2280 return -1;
2282 return 0;
2285 /****************************************************************************
2286 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2287 ****************************************************************************/
2289 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2290 char **pparams, int total_params, char **ppdata, int total_data)
2292 char *params = *pparams;
2293 char *pdata = *ppdata;
2294 uint16 tran_call = SVAL(inbuf, smb_setup0);
2295 uint16 info_level;
2296 int dosmode = 0;
2297 SMB_OFF_T size=0;
2298 struct utimbuf tvs;
2299 SMB_STRUCT_STAT sbuf;
2300 pstring fname1;
2301 char *fname = NULL;
2302 int fd = -1;
2303 BOOL bad_path = False;
2304 files_struct *fsp = NULL;
2305 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2306 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2307 mode_t unixmode = 0;
2309 if (tran_call == TRANSACT2_SETFILEINFO) {
2311 if (total_params < 4)
2312 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2314 fsp = file_fsp(params,0);
2315 info_level = SVAL(params,2);
2317 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2319 * This is actually a SETFILEINFO on a directory
2320 * handle (returned from an NT SMB). NT5.0 seems
2321 * to do this call. JRA.
2323 fname = fsp->fsp_name;
2324 unix_convert(fname,conn,0,&bad_path,&sbuf);
2325 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2326 DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2327 set_bad_path_error(errno, bad_path);
2328 return(UNIXERROR(ERRDOS,ERRbadpath));
2330 } else if (fsp && fsp->print_file) {
2332 * Doing a DELETE_ON_CLOSE should cancel a print job.
2334 if (((info_level == SMB_SET_FILE_DISPOSITION_INFO)||(info_level == SMB_FILE_DISPOSITION_INFORMATION)) &&
2335 CVAL(pdata,0)) {
2336 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2338 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n",
2339 fsp->fsp_name ));
2341 SSVAL(params,0,0);
2342 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2343 return(-1);
2344 } else
2345 return(UNIXERROR(ERRDOS,ERRbadpath));
2346 } else {
2348 * Original code - this is an open file.
2350 CHECK_FSP(fsp,conn);
2352 fname = fsp->fsp_name;
2353 fd = fsp->fd;
2355 if (vfs_fstat(fsp,fd,&sbuf) != 0) {
2356 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2357 return(UNIXERROR(ERRDOS,ERRbadfid));
2360 } else {
2361 /* set path info */
2362 if (total_params < 6)
2363 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2365 info_level = SVAL(params,0);
2366 fname = fname1;
2367 pstrcpy(fname,&params[6]);
2368 unix_convert(fname,conn,0,&bad_path,&sbuf);
2369 if(!check_name(fname, conn)) {
2370 set_bad_path_error(errno, bad_path);
2371 return(UNIXERROR(ERRDOS,ERRbadpath));
2375 * For CIFS UNIX extensions the target name may not exist.
2378 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2380 DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
2381 set_bad_path_error(errno, bad_path);
2382 return(UNIXERROR(ERRDOS,ERRbadpath));
2386 if (!CAN_WRITE(conn))
2387 return ERROR_DOS(ERRSRV,ERRaccess);
2389 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2390 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2392 if (VALID_STAT(sbuf))
2393 unixmode = sbuf.st_mode;
2395 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
2396 tran_call,fname,info_level,total_data));
2398 /* Realloc the parameter and data sizes */
2399 params = Realloc(*pparams,2);
2400 if(params == NULL)
2401 return ERROR_DOS(ERRDOS,ERRnomem);
2402 *pparams = params;
2404 SSVAL(params,0,0);
2406 if (fsp) {
2407 /* the pending modtime overrides the current modtime */
2408 sbuf.st_mtime = fsp->pending_modtime;
2411 size = get_file_size(sbuf);
2412 tvs.modtime = sbuf.st_mtime;
2413 tvs.actime = sbuf.st_atime;
2414 dosmode = dos_mode(conn,fname,&sbuf);
2415 unixmode = sbuf.st_mode;
2417 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2418 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2420 switch (info_level) {
2421 case SMB_INFO_STANDARD:
2423 if (total_data < l1_cbFile+4)
2424 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2426 /* access time */
2427 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2429 /* write time */
2430 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2432 dosmode = SVAL(pdata,l1_attrFile);
2433 size = IVAL(pdata,l1_cbFile);
2434 break;
2437 case SMB_INFO_SET_EA:
2438 return(ERROR_DOS(ERRDOS,ERReasnotsupported));
2440 /* XXXX um, i don't think this is right.
2441 it's also not in the cifs6.txt spec.
2443 case SMB_INFO_QUERY_EAS_FROM_LIST:
2444 if (total_data < 28)
2445 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2447 tvs.actime = make_unix_date2(pdata+8);
2448 tvs.modtime = make_unix_date2(pdata+12);
2449 size = IVAL(pdata,16);
2450 dosmode = IVAL(pdata,24);
2451 break;
2453 /* XXXX nor this. not in cifs6.txt, either. */
2454 case SMB_INFO_QUERY_ALL_EAS:
2455 if (total_data < 28)
2456 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2458 tvs.actime = make_unix_date2(pdata+8);
2459 tvs.modtime = make_unix_date2(pdata+12);
2460 size = IVAL(pdata,16);
2461 dosmode = IVAL(pdata,24);
2462 break;
2464 case SMB_SET_FILE_BASIC_INFO:
2465 case SMB_FILE_BASIC_INFORMATION:
2467 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2468 time_t write_time;
2469 time_t changed_time;
2471 if (total_data < 36)
2472 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2474 /* Ignore create time at offset pdata. */
2476 /* access time */
2477 tvs.actime = interpret_long_date(pdata+8);
2479 write_time = interpret_long_date(pdata+16);
2480 changed_time = interpret_long_date(pdata+24);
2482 tvs.modtime = MIN(write_time, changed_time);
2484 if (write_time > tvs.modtime && write_time != 0xffffffff) {
2485 tvs.modtime = write_time;
2488 /* Prefer a defined time to an undefined one. */
2489 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2490 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2491 ? changed_time
2492 : write_time);
2494 /* attributes */
2495 dosmode = IVAL(pdata,32);
2496 break;
2499 case SMB_FILE_ALLOCATION_INFORMATION:
2500 case SMB_SET_FILE_ALLOCATION_INFO:
2502 int ret = -1;
2503 SMB_BIG_UINT allocation_size;
2505 if (total_data < 8)
2506 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2508 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
2509 #ifdef LARGE_SMB_OFF_T
2510 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
2511 #else /* LARGE_SMB_OFF_T */
2512 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2513 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2514 #endif /* LARGE_SMB_OFF_T */
2515 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2516 fname, (double)allocation_size ));
2518 if (allocation_size)
2519 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
2521 if(allocation_size != get_file_size(sbuf)) {
2522 SMB_STRUCT_STAT new_sbuf;
2524 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2525 fname, (double)allocation_size ));
2527 if (fd == -1) {
2528 files_struct *new_fsp = NULL;
2529 int access_mode = 0;
2530 int action = 0;
2532 if(global_oplock_break) {
2533 /* Queue this file modify as we are the process of an oplock break. */
2535 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2536 DEBUGADD(2,( "in oplock break state.\n"));
2538 push_oplock_pending_smb_message(inbuf, length);
2539 return -1;
2542 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2543 SET_OPEN_MODE(DOS_OPEN_RDWR),
2544 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2545 0, 0, &access_mode, &action);
2547 if (new_fsp == NULL)
2548 return(UNIXERROR(ERRDOS,ERRbadpath));
2549 ret = vfs_allocate_file_space(new_fsp, allocation_size);
2550 if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2551 DEBUG(3,("fstat of fnum %d failed (%s)\n",new_fsp->fnum, strerror(errno)));
2552 ret = -1;
2554 close_file(new_fsp,True);
2555 } else {
2556 ret = vfs_allocate_file_space(fsp, allocation_size);
2557 if (vfs_fstat(fsp,fd,&new_sbuf) != 0) {
2558 DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2559 ret = -1;
2562 if (ret == -1)
2563 return ERROR_NT(NT_STATUS_DISK_FULL);
2565 /* Allocate can trucate size... */
2566 size = get_file_size(new_sbuf);
2569 break;
2572 case SMB_FILE_END_OF_FILE_INFORMATION:
2573 case SMB_SET_FILE_END_OF_FILE_INFO:
2575 if (total_data < 8)
2576 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2578 size = IVAL(pdata,0);
2579 #ifdef LARGE_SMB_OFF_T
2580 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2581 #else /* LARGE_SMB_OFF_T */
2582 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2583 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2584 #endif /* LARGE_SMB_OFF_T */
2585 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2586 break;
2589 case SMB_FILE_DISPOSITION_INFORMATION:
2590 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2592 BOOL delete_on_close;
2593 NTSTATUS status;
2595 if (total_data < 1)
2596 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2598 delete_on_close = (CVAL(pdata,0) ? True : False);
2600 if (tran_call != TRANSACT2_SETFILEINFO)
2601 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
2603 if (fsp == NULL)
2604 return(UNIXERROR(ERRDOS,ERRbadfid));
2606 status = set_delete_on_close_internal(fsp, delete_on_close);
2607 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2608 return ERROR_NT(status);
2610 /* The set is across all open files on this dev/inode pair. */
2611 status =set_delete_on_close_over_all(fsp, delete_on_close);
2612 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2613 return ERROR_NT(status);
2615 break;
2619 * CIFS UNIX extensions.
2622 case SMB_SET_FILE_UNIX_BASIC:
2624 uint32 raw_unixmode;
2626 if (total_data < 100)
2627 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2629 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
2630 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
2631 size=IVAL(pdata,0); /* first 8 Bytes are size */
2632 #ifdef LARGE_SMB_OFF_T
2633 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2634 #else /* LARGE_SMB_OFF_T */
2635 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2636 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2637 #endif /* LARGE_SMB_OFF_T */
2639 pdata+=24; /* ctime & st_blocks are not changed */
2640 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
2641 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
2642 pdata+=16;
2643 set_owner = (uid_t)IVAL(pdata,0);
2644 pdata += 8;
2645 set_grp = (gid_t)IVAL(pdata,0);
2646 pdata += 8;
2647 raw_unixmode = IVAL(pdata,28);
2648 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2649 dosmode = 0; /* Ensure dos mode change doesn't override this. */
2651 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2652 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2653 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2655 if (!VALID_STAT(sbuf)) {
2658 * The only valid use of this is to create character and block
2659 * devices, and named pipes. This is deprecated (IMHO) and
2660 * a new info level should be used for mknod. JRA.
2663 #if !defined(HAVE_MAKEDEV_FN)
2664 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2665 #else /* HAVE_MAKEDEV_FN */
2666 uint32 file_type = IVAL(pdata,0);
2667 uint32 dev_major = IVAL(pdata,4);
2668 uint32 dev_minor = IVAL(pdata,12);
2670 uid_t myuid = geteuid();
2671 gid_t mygid = getegid();
2672 SMB_DEV_T dev;
2674 if (tran_call == TRANSACT2_SETFILEINFO)
2675 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2677 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2678 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2680 dev = makedev(dev_major, dev_minor);
2682 /* We can only create as the owner/group we are. */
2684 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2685 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2686 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2687 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2689 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2690 file_type != UNIX_TYPE_FIFO)
2691 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2693 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2694 0%o for file %s\n", (double)dev, unixmode, fname ));
2696 /* Ok - do the mknod. */
2697 if (conn->vfs_ops.mknod(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
2698 return(UNIXERROR(ERRDOS,ERRnoaccess));
2700 SSVAL(params,0,0);
2701 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2702 return(-1);
2703 #endif /* HAVE_MAKEDEV_FN */
2708 * Deal with the UNIX specific mode set.
2711 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
2712 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2713 (unsigned int)unixmode, fname ));
2714 if (vfs_chmod(conn,fname,unixmode) != 0)
2715 return(UNIXERROR(ERRDOS,ERRnoaccess));
2719 * Deal with the UNIX specific uid set.
2722 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
2723 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2724 (unsigned int)set_owner, fname ));
2725 if (vfs_chown(conn,fname,set_owner, (gid_t)-1) != 0)
2726 return(UNIXERROR(ERRDOS,ERRnoaccess));
2730 * Deal with the UNIX specific gid set.
2733 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
2734 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2735 (unsigned int)set_owner, fname ));
2736 if (vfs_chown(conn,fname,(uid_t)-1, set_grp) != 0)
2737 return(UNIXERROR(ERRDOS,ERRnoaccess));
2739 break;
2742 case SMB_SET_FILE_UNIX_LINK:
2744 pstring link_dest;
2745 /* Set a symbolic link. */
2746 /* Don't allow this if follow links is false. */
2748 if (!lp_symlinks(SNUM(conn)))
2749 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2751 /* Disallow if already exists. */
2752 if (VALID_STAT(sbuf))
2753 return(ERROR_DOS(ERRDOS,ERRbadpath));
2755 pstrcpy(link_dest, pdata);
2757 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2758 return(UNIXERROR(ERRDOS,ERRnoaccess));
2759 dos_to_unix(link_dest);
2760 dos_to_unix(fname);
2762 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2763 fname, link_dest ));
2765 if (conn->vfs_ops.symlink(conn,link_dest,fname) != 0)
2766 return(UNIXERROR(ERRDOS,ERRnoaccess));
2767 SSVAL(params,0,0);
2768 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2769 return(-1);
2772 case SMB_SET_FILE_UNIX_HLINK:
2774 pstring link_dest;
2776 /* Set a hard link. */
2778 /* Disallow if already exists. */
2779 if (VALID_STAT(sbuf))
2780 return(ERROR_DOS(ERRDOS,ERRbadpath));
2782 pstrcpy(link_dest, pdata);
2784 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2785 return(UNIXERROR(ERRDOS,ERRnoaccess));
2787 dos_to_unix(link_dest);
2788 dos_to_unix(fname);
2790 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2791 fname, link_dest ));
2793 if (conn->vfs_ops.link(conn,link_dest,fname) != 0)
2794 return(UNIXERROR(ERRDOS,ERRnoaccess));
2795 SSVAL(params,0,0);
2796 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2797 return(-1);
2800 default:
2801 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2804 /* get some defaults (no modifications) if any info is zero or -1. */
2805 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2806 tvs.actime = sbuf.st_atime;
2808 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2809 tvs.modtime = sbuf.st_mtime;
2811 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2812 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2813 DEBUG(6,("size: %.0f ", (double)size));
2814 if (S_ISDIR(sbuf.st_mode))
2815 dosmode |= aDIR;
2816 else
2817 dosmode &= ~aDIR;
2819 DEBUG(6,("dosmode: %x\n" , dosmode));
2821 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2822 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2823 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2824 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2826 * Only do this test if we are not explicitly
2827 * changing the size of a file.
2829 if (!size)
2830 size = get_file_size(sbuf);
2834 * Try and set the times, size and mode of this file -
2835 * if they are different from the current values
2838 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2839 if(fsp != NULL) {
2841 * This was a setfileinfo on an open file.
2842 * NT does this a lot. It's actually pointless
2843 * setting the time here, as it will be overwritten
2844 * on the next write, so we save the request
2845 * away and will set it on file close. JRA.
2848 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2849 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n",
2850 ctime(&tvs.modtime) ));
2851 fsp->pending_modtime = tvs.modtime;
2854 } else {
2856 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2858 if(file_utime(conn, fname, &tvs)!=0)
2859 return(UNIXERROR(ERRDOS,ERRnoaccess));
2863 /* check the mode isn't different, before changing it */
2864 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
2866 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n",
2867 fname, dosmode ));
2869 if(file_chmod(conn, fname, dosmode, NULL)) {
2870 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2871 return(UNIXERROR(ERRDOS,ERRnoaccess));
2875 if(size != get_file_size(sbuf)) {
2877 int ret;
2879 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2880 fname, (double)size ));
2882 if (fd == -1) {
2883 files_struct *new_fsp = NULL;
2884 int access_mode = 0;
2885 int action = 0;
2887 if(global_oplock_break) {
2888 /* Queue this file modify as we are the process of an oplock break. */
2890 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2891 DEBUGADD(2,( "in oplock break state.\n"));
2893 push_oplock_pending_smb_message(inbuf, length);
2894 return -1;
2897 new_fsp = open_file_shared(conn, fname, &sbuf,
2898 SET_OPEN_MODE(DOS_OPEN_RDWR),
2899 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2900 0, 0, &access_mode, &action);
2902 if (new_fsp == NULL)
2903 return(UNIXERROR(ERRDOS,ERRbadpath));
2904 ret = vfs_set_filelen(new_fsp, size);
2905 close_file(new_fsp,True);
2906 } else {
2907 ret = vfs_set_filelen(fsp, size);
2910 if (ret == -1)
2911 return (UNIXERROR(ERRHRD,ERRdiskfull));
2914 SSVAL(params,0,0);
2915 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2916 return(-1);
2919 /****************************************************************************
2920 Reply to a TRANS2_MKDIR (make directory with extended attributes).
2921 ****************************************************************************/
2923 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2924 char **pparams, int total_params, char **ppdata, int total_data)
2926 char *params = *pparams;
2927 pstring directory;
2928 int ret = -1;
2929 SMB_STRUCT_STAT sbuf;
2930 BOOL bad_path = False;
2932 if (!CAN_WRITE(conn))
2933 return ERROR_DOS(ERRSRV,ERRaccess);
2935 if (total_params < 4)
2936 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2938 pstrcpy(directory, &params[4]);
2940 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
2942 unix_convert(directory,conn,0,&bad_path,&sbuf);
2943 if (check_name(directory,conn))
2944 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2946 if(ret < 0) {
2947 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
2948 set_bad_path_error(errno, bad_path);
2949 return(UNIXERROR(ERRDOS,ERRnoaccess));
2952 /* Realloc the parameter and data sizes */
2953 params = Realloc(*pparams,2);
2954 if(params == NULL)
2955 return ERROR_DOS(ERRDOS,ERRnomem);
2956 *pparams = params;
2958 SSVAL(params,0,0);
2960 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2962 return(-1);
2965 /****************************************************************************
2966 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
2967 We don't actually do this - we just send a null response.
2968 ****************************************************************************/
2970 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2971 char **pparams, int total_params, char **ppdata, int total_data)
2973 static uint16 fnf_handle = 257;
2974 char *params = *pparams;
2975 uint16 info_level;
2977 if (total_params < 6)
2978 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2980 info_level = SVAL(params,4);
2981 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
2983 switch (info_level) {
2984 case 1:
2985 case 2:
2986 break;
2987 default:
2988 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2991 /* Realloc the parameter and data sizes */
2992 params = Realloc(*pparams,6);
2993 if(params == NULL)
2994 return ERROR_DOS(ERRDOS,ERRnomem);
2995 *pparams = params;
2997 SSVAL(params,0,fnf_handle);
2998 SSVAL(params,2,0); /* No changes */
2999 SSVAL(params,4,0); /* No EA errors */
3001 fnf_handle++;
3003 if(fnf_handle == 0)
3004 fnf_handle = 257;
3006 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3008 return(-1);
3011 /****************************************************************************
3012 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3013 changes). Currently this does nothing.
3014 ****************************************************************************/
3016 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3017 char **pparams, int total_params, char **ppdata, int total_data)
3019 char *params = *pparams;
3021 DEBUG(3,("call_trans2findnotifynext\n"));
3023 /* Realloc the parameter and data sizes */
3024 params = Realloc(*pparams,4);
3025 if(params == NULL)
3026 return ERROR_DOS(ERRDOS,ERRnomem);
3027 *pparams = params;
3029 SSVAL(params,0,0); /* No changes */
3030 SSVAL(params,2,0); /* No EA errors */
3032 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3034 return(-1);
3037 /****************************************************************************
3038 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3039 ****************************************************************************/
3041 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
3042 char **pparams, int total_params, char **ppdata, int total_data)
3044 char *params = *pparams;
3045 enum remote_arch_types ra_type = get_remote_arch();
3046 BOOL NT_arch = ((ra_type == RA_WINNT) || (ra_type == RA_WIN2K));
3047 pstring pathname;
3048 int reply_size = 0;
3049 int max_referral_level;
3051 DEBUG(10,("call_trans2getdfsreferral\n"));
3053 if (total_params < 2)
3054 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3056 max_referral_level = SVAL(params,0);
3058 if(!lp_host_msdfs())
3059 return ERROR_DOS(ERRDOS,ERRbadfunc);
3061 /* if pathname is in UNICODE, convert to DOS */
3062 /* NT always sends in UNICODE, may not set UNICODE flag */
3063 if(NT_arch || (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS)) {
3064 unistr_to_dos(pathname, &params[2], sizeof(pathname));
3065 DEBUG(10,("UNICODE referral for %s\n",pathname));
3066 } else
3067 pstrcpy(pathname,&params[2]);
3069 if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
3070 return ERROR_DOS(ERRDOS,ERRbadfile);
3072 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_UNICODE_STRINGS | FLAGS2_DFS_PATHNAMES);
3073 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3075 return(-1);
3078 #define LMCAT_SPL 0x53
3079 #define LMFUNC_GETJOBID 0x60
3081 /****************************************************************************
3082 reply to a TRANS2_IOCTL - used for OS/2 printing.
3083 ****************************************************************************/
3085 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
3086 char **pparams, int total_params, char **ppdata, int total_data)
3088 char *pdata = *ppdata;
3089 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3091 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3092 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3093 pdata = Realloc(*ppdata, 32);
3094 if(pdata == NULL)
3095 return ERROR_DOS(ERRDOS,ERRnomem);
3096 *ppdata = pdata;
3098 SSVAL(pdata,0,fsp->print_jobid); /* Job number */
3099 StrnCpy(pdata+2, global_myname, 15); /* Our NetBIOS name */
3100 StrnCpy(pdata+18, lp_servicename(SNUM(conn)), 13); /* Service name */
3101 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3102 return(-1);
3103 } else {
3104 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3105 return ERROR_DOS(ERRSRV,ERRerror);
3109 /****************************************************************************
3110 Reply to a SMBfindclose (stop trans2 directory search).
3111 ****************************************************************************/
3113 int reply_findclose(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3115 int outsize = 0;
3116 int dptr_num=SVALS(inbuf,smb_vwv0);
3117 START_PROFILE(SMBfindclose);
3119 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3121 dptr_close(&dptr_num);
3123 outsize = set_message(outbuf,0,0,True);
3125 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3127 END_PROFILE(SMBfindclose);
3128 return(outsize);
3131 /****************************************************************************
3132 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3133 ****************************************************************************/
3135 int reply_findnclose(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3137 int outsize = 0;
3138 int dptr_num= -1;
3139 START_PROFILE(SMBfindnclose);
3141 dptr_num = SVAL(inbuf,smb_vwv0);
3143 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3145 /* We never give out valid handles for a
3146 findnotifyfirst - so any dptr_num is ok here.
3147 Just ignore it. */
3149 outsize = set_message(outbuf,0,0,True);
3151 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3153 END_PROFILE(SMBfindnclose);
3154 return(outsize);
3157 /****************************************************************************
3158 Reply to a SMBtranss2 - just ignore it!
3159 ****************************************************************************/
3161 int reply_transs2(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3163 START_PROFILE(SMBtranss2);
3164 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3165 END_PROFILE(SMBtranss2);
3166 return(-1);
3169 /****************************************************************************
3170 Reply to a SMBtrans2.
3171 ****************************************************************************/
3173 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3175 int outsize = 0;
3176 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3177 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3178 #if 0
3179 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3180 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3181 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3182 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3183 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3184 int32 timeout = IVALS(inbuf,smb_timeout);
3185 #endif
3186 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3187 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3188 char *params = NULL, *data = NULL;
3189 int num_params, num_params_sofar, num_data, num_data_sofar;
3190 START_PROFILE(SMBtrans2);
3192 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3193 /* Queue this open message as we are the process of an
3194 * oplock break. */
3196 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3197 DEBUGADD(2,( "in oplock break state.\n"));
3199 push_oplock_pending_smb_message(inbuf, length);
3200 END_PROFILE(SMBtrans2);
3201 return -1;
3204 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3205 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3206 END_PROFILE(SMBtrans2);
3207 return ERROR_DOS(ERRSRV,ERRaccess);
3210 outsize = set_message(outbuf,0,0,True);
3212 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3213 is so as a sanity check */
3214 if (suwcnt != 1) {
3216 * Need to have rc=0 for ioctl to get job id for OS/2.
3217 * Network printing will fail if function is not successful.
3218 * Similar function in reply.c will be used if protocol
3219 * is LANMAN1.0 instead of LM1.2X002.
3220 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3221 * outbuf doesn't have to be set(only job id is used).
3223 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3224 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3225 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3226 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3227 } else {
3228 DEBUG(2,("Invalid smb_sucnt in trans2 call(%d)\n",suwcnt));
3229 DEBUG(2,("Transaction is %d\n",tran_call));
3230 END_PROFILE(SMBtrans2);
3231 return ERROR_DOS(ERRSRV,ERRerror);
3235 /* Allocate the space for the maximum needed parameters and data */
3236 if (total_params > 0)
3237 params = (char *)malloc(total_params);
3238 if (total_data > 0)
3239 data = (char *)malloc(total_data);
3241 if ((total_params && !params) || (total_data && !data)) {
3242 DEBUG(2,("Out of memory in reply_trans2\n"));
3243 SAFE_FREE(params);
3244 SAFE_FREE(data);
3245 END_PROFILE(SMBtrans2);
3246 return ERROR_DOS(ERRDOS,ERRnomem);
3249 /* Copy the param and data bytes sent with this request into
3250 the params buffer */
3251 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3252 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3254 if (num_params > total_params || num_data > total_data)
3255 exit_server("invalid params in reply_trans2");
3257 if(params)
3258 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
3259 if(data)
3260 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
3262 if(num_data_sofar < total_data || num_params_sofar < total_params) {
3263 /* We need to send an interim response then receive the rest
3264 of the parameter/data bytes */
3265 outsize = set_message(outbuf,0,0,True);
3266 if (!send_smb(smbd_server_fd(),outbuf))
3267 exit_server("reply_trans2: send_smb failed.");
3269 while (num_data_sofar < total_data ||
3270 num_params_sofar < total_params) {
3271 BOOL ret;
3273 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3275 if ((ret &&
3276 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3277 outsize = set_message(outbuf,0,0,True);
3278 if(ret)
3279 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3280 else
3281 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3282 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3283 SAFE_FREE(params);
3284 SAFE_FREE(data);
3285 END_PROFILE(SMBtrans2);
3286 return ERROR_DOS(ERRSRV,ERRerror);
3289 /* Revise total_params and total_data in case
3290 they have changed downwards */
3291 total_params = SVAL(inbuf, smb_tpscnt);
3292 total_data = SVAL(inbuf, smb_tdscnt);
3293 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
3294 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
3295 if (num_params_sofar > total_params || num_data_sofar > total_data)
3296 exit_server("data overflow in trans2");
3298 memcpy( &params[ SVAL(inbuf, smb_spsdisp)],
3299 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
3300 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
3301 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
3305 if (Protocol >= PROTOCOL_NT1)
3306 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_IS_LONG_NAME);
3308 /* Now we must call the relevant TRANS2 function */
3309 switch(tran_call) {
3310 case TRANSACT2_OPEN:
3311 START_PROFILE_NESTED(Trans2_open);
3312 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
3313 &params, total_params, &data, total_data);
3314 END_PROFILE_NESTED(Trans2_open);
3315 break;
3317 case TRANSACT2_FINDFIRST:
3318 START_PROFILE_NESTED(Trans2_findfirst);
3319 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3320 &params, total_params, &data, total_data);
3321 END_PROFILE_NESTED(Trans2_findfirst);
3322 break;
3324 case TRANSACT2_FINDNEXT:
3325 START_PROFILE_NESTED(Trans2_findnext);
3326 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
3327 &params, total_params, &data, total_data);
3328 END_PROFILE_NESTED(Trans2_findnext);
3329 break;
3331 case TRANSACT2_QFSINFO:
3332 START_PROFILE_NESTED(Trans2_qfsinfo);
3333 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3334 &params, total_params, &data, total_data);
3335 END_PROFILE_NESTED(Trans2_qfsinfo);
3336 break;
3338 case TRANSACT2_SETFSINFO:
3339 START_PROFILE_NESTED(Trans2_setfsinfo);
3340 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
3341 &params, total_params, &data, total_data);
3342 END_PROFILE_NESTED(Trans2_setfsinfo);
3343 break;
3345 case TRANSACT2_QPATHINFO:
3346 case TRANSACT2_QFILEINFO:
3347 START_PROFILE_NESTED(Trans2_qpathinfo);
3348 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3349 &params, total_params, &data, total_data);
3350 END_PROFILE_NESTED(Trans2_qpathinfo);
3351 break;
3352 case TRANSACT2_SETPATHINFO:
3353 case TRANSACT2_SETFILEINFO:
3354 START_PROFILE_NESTED(Trans2_setpathinfo);
3355 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3356 &params, total_params, &data, total_data);
3357 END_PROFILE_NESTED(Trans2_setpathinfo);
3358 break;
3360 case TRANSACT2_FINDNOTIFYFIRST:
3361 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3362 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
3363 &params, total_params, &data, total_data);
3364 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3365 break;
3367 case TRANSACT2_FINDNOTIFYNEXT:
3368 START_PROFILE_NESTED(Trans2_findnotifynext);
3369 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
3370 &params, total_params, &data, total_data);
3371 END_PROFILE_NESTED(Trans2_findnotifynext);
3372 break;
3373 case TRANSACT2_MKDIR:
3374 START_PROFILE_NESTED(Trans2_mkdir);
3375 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3376 &params, total_params, &data, total_data);
3377 END_PROFILE_NESTED(Trans2_mkdir);
3378 break;
3380 case TRANSACT2_GET_DFS_REFERRAL:
3381 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3382 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3383 &params, total_params, &data, total_data);
3384 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3385 break;
3386 case TRANSACT2_IOCTL:
3387 START_PROFILE_NESTED(Trans2_ioctl);
3388 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3389 &params, total_params, &data, total_data);
3390 END_PROFILE_NESTED(Trans2_ioctl);
3391 break;
3392 default:
3393 /* Error in request */
3394 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3395 SAFE_FREE(params);
3396 SAFE_FREE(data);
3397 END_PROFILE(SMBtrans2);
3398 return ERROR_DOS(ERRSRV,ERRerror);
3401 /* As we do not know how many data packets will need to be
3402 returned here the various call_trans2xxxx calls
3403 must send their own. Thus a call_trans2xxx routine only
3404 returns a value other than -1 when it wants to send
3405 an error packet.
3408 SAFE_FREE(params);
3409 SAFE_FREE(data);
3410 END_PROFILE(SMBtrans2);
3411 return outsize; /* If a correct response was needed the
3412 call_trans2xxx calls have already sent
3413 it. If outsize != -1 then it is returning */