This only touches the fake kaserver support. It adds two parameters:
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blob033e76a33e1dcb9a664bbc6961c1d5852f11e6a4
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2003
5 Copyright (C) Stefan (metze) Metzmacher 2003
7 Extensively modified by Andrew Tridgell, 1995
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 extern int Protocol;
27 extern BOOL case_sensitive;
28 extern int smb_read_error;
29 extern fstring local_machine;
30 extern int global_oplock_break;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
34 #define get_file_size(sbuf) ((sbuf).st_size)
36 /* given a stat buffer return the allocated size on disk, taking into
37 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,
60 int bufsize,
61 char *params,
62 int paramsize,
63 char *pdata,
64 int datasize)
66 /* As we are using a protocol > LANMAN1 then the max_send
67 variable must have been set in the sessetupX call.
68 This takes precedence over the max_xmit field in the
69 global struct. These different max_xmit variables should
70 be merged as this is now too confusing */
72 extern int max_send;
73 int data_to_send = datasize;
74 int params_to_send = paramsize;
75 int useable_space;
76 char *pp = params;
77 char *pd = pdata;
78 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
79 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
80 int data_alignment_offset = 0;
82 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
84 set_message(outbuf,10,0,True);
86 /* If there genuinely are no parameters or data to send just send the empty packet */
88 if(params_to_send == 0 && data_to_send == 0) {
89 if (!send_smb(smbd_server_fd(),outbuf))
90 exit_server("send_trans2_replies: send_smb failed.");
91 return 0;
94 /* When sending params and data ensure that both are nicely aligned */
95 /* Only do this alignment when there is also data to send - else
96 can cause NT redirector problems. */
98 if (((params_to_send % 4) != 0) && (data_to_send != 0))
99 data_alignment_offset = 4 - (params_to_send % 4);
101 /* Space is bufsize minus Netbios over TCP header minus SMB header */
102 /* The alignment_offset is to align the param bytes on an even byte
103 boundary. NT 4.0 Beta needs this to work correctly. */
105 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
107 /* useable_space can never be more than max_send minus the alignment offset. */
109 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
111 while (params_to_send || data_to_send) {
112 /* Calculate whether we will totally or partially fill this packet */
114 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
116 /* We can never send more than useable_space */
118 * Note that 'useable_space' does not include the alignment offsets,
119 * but we must include the alignment offsets in the calculation of
120 * the length of the data we send over the wire, as the alignment offsets
121 * are sent here. Fix from Marc_Jacobsen@hp.com.
124 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
126 set_message(outbuf, 10, total_sent_thistime, True);
128 /* Set total params and data to be sent */
129 SSVAL(outbuf,smb_tprcnt,paramsize);
130 SSVAL(outbuf,smb_tdrcnt,datasize);
132 /* Calculate how many parameters and data we can fit into
133 * this packet. Parameters get precedence
136 params_sent_thistime = MIN(params_to_send,useable_space);
137 data_sent_thistime = useable_space - params_sent_thistime;
138 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
140 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
142 /* smb_proff is the offset from the start of the SMB header to the
143 parameter bytes, however the first 4 bytes of outbuf are
144 the Netbios over TCP header. Thus use smb_base() to subtract
145 them from the calculation */
147 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
149 if(params_sent_thistime == 0)
150 SSVAL(outbuf,smb_prdisp,0);
151 else
152 /* Absolute displacement of param bytes sent in this packet */
153 SSVAL(outbuf,smb_prdisp,pp - params);
155 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
156 if(data_sent_thistime == 0) {
157 SSVAL(outbuf,smb_droff,0);
158 SSVAL(outbuf,smb_drdisp, 0);
159 } else {
160 /* The offset of the data bytes is the offset of the
161 parameter bytes plus the number of parameters being sent this time */
162 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
163 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
164 SSVAL(outbuf,smb_drdisp, pd - pdata);
167 /* Copy the param bytes into the packet */
169 if(params_sent_thistime)
170 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
172 /* Copy in the data bytes */
173 if(data_sent_thistime)
174 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
175 data_alignment_offset,pd,data_sent_thistime);
177 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
178 params_sent_thistime, data_sent_thistime, useable_space));
179 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
180 params_to_send, data_to_send, paramsize, datasize));
182 /* Send the packet */
183 if (!send_smb(smbd_server_fd(),outbuf))
184 exit_server("send_trans2_replies: send_smb failed.");
186 pp += params_sent_thistime;
187 pd += data_sent_thistime;
189 params_to_send -= params_sent_thistime;
190 data_to_send -= data_sent_thistime;
192 /* Sanity check */
193 if(params_to_send < 0 || data_to_send < 0) {
194 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
195 params_to_send, data_to_send));
196 return -1;
200 return 0;
203 /****************************************************************************
204 Reply to a TRANSACT2_OPEN.
205 ****************************************************************************/
207 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
208 char **pparams, int total_params, char **ppdata, int total_data)
210 char *params = *pparams;
211 int16 open_mode;
212 int16 open_attr;
213 BOOL oplock_request;
214 #if 0
215 BOOL return_additional_info;
216 int16 open_sattr;
217 time_t open_time;
218 #endif
219 int16 open_ofun;
220 int32 open_size;
221 char *pname;
222 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];
251 srvstr_pull(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE);
253 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
254 fname,open_mode, open_attr, open_ofun, open_size));
256 if (IS_IPC(conn))
257 return(ERROR_DOS(ERRSRV,ERRaccess));
259 /* XXXX we need to handle passed times, sattr and flags */
261 unix_convert(fname,conn,0,&bad_path,&sbuf);
263 if (!check_name(fname,conn)) {
264 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
267 unixmode = unix_mode(conn,open_attr | aARCH, fname);
269 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode,
270 oplock_request, &rmode,&smb_action);
272 if (!fsp) {
273 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
276 size = get_file_size(sbuf);
277 fmode = dos_mode(conn,fname,&sbuf);
278 mtime = sbuf.st_mtime;
279 inode = sbuf.st_ino;
280 if (fmode & aDIR) {
281 close_file(fsp,False);
282 return(ERROR_DOS(ERRDOS,ERRnoaccess));
285 /* Realloc the size of parameters and data we will return */
286 params = Realloc(*pparams, 28);
287 if( params == NULL )
288 return(ERROR_DOS(ERRDOS,ERRnomem));
289 *pparams = params;
291 memset((char *)params,'\0',28);
292 SSVAL(params,0,fsp->fnum);
293 SSVAL(params,2,fmode);
294 put_dos_date2(params,4, mtime);
295 SIVAL(params,8, (uint32)size);
296 SSVAL(params,12,rmode);
298 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
299 smb_action |= EXTENDED_OPLOCK_GRANTED;
301 SSVAL(params,18,smb_action);
304 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
306 SIVAL(params,20,inode);
308 /* Send the required number of replies */
309 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
311 return -1;
314 /*********************************************************
315 Routine to check if a given string matches exactly.
316 as a special case a mask of "." does NOT match. That
317 is required for correct wildcard semantics
318 Case can be significant or not.
319 **********************************************************/
321 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
323 if (mask[0] == '.' && mask[1] == 0)
324 return False;
325 if (case_sig)
326 return strcmp(str,mask)==0;
327 if (StrCaseCmp(str,mask) != 0) {
328 return False;
330 if (ms_has_wild(str)) {
331 return False;
333 return True;
336 /****************************************************************************
337 Return the filetype for UNIX extensions.
338 ****************************************************************************/
340 static uint32 unix_filetype(mode_t mode)
342 if(S_ISREG(mode))
343 return UNIX_TYPE_FILE;
344 else if(S_ISDIR(mode))
345 return UNIX_TYPE_DIR;
346 #ifdef S_ISLNK
347 else if(S_ISLNK(mode))
348 return UNIX_TYPE_SYMLINK;
349 #endif
350 #ifdef S_ISCHR
351 else if(S_ISCHR(mode))
352 return UNIX_TYPE_CHARDEV;
353 #endif
354 #ifdef S_ISBLK
355 else if(S_ISBLK(mode))
356 return UNIX_TYPE_BLKDEV;
357 #endif
358 #ifdef S_ISFIFO
359 else if(S_ISFIFO(mode))
360 return UNIX_TYPE_FIFO;
361 #endif
362 #ifdef S_ISSOCK
363 else if(S_ISSOCK(mode))
364 return UNIX_TYPE_SOCKET;
365 #endif
367 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
368 return UNIX_TYPE_UNKNOWN;
371 /****************************************************************************
372 Return the major devicenumber for UNIX extensions.
373 ****************************************************************************/
375 static uint32 unix_dev_major(SMB_DEV_T dev)
377 #if defined(HAVE_DEVICE_MAJOR_FN)
378 return (uint32)major(dev);
379 #else
380 return (uint32)(dev >> 8);
381 #endif
384 /****************************************************************************
385 Return the minor devicenumber for UNIX extensions.
386 ****************************************************************************/
388 static uint32 unix_dev_minor(SMB_DEV_T dev)
390 #if defined(HAVE_DEVICE_MINOR_FN)
391 return (uint32)minor(dev);
392 #else
393 return (uint32)(dev & 0xff);
394 #endif
397 /****************************************************************************
398 Map wire perms onto standard UNIX permissions. Obey share restrictions.
399 ****************************************************************************/
401 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
403 mode_t ret = 0;
405 if (perms == SMB_MODE_NO_CHANGE)
406 return pst->st_mode;
408 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
409 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
410 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
411 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
412 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
413 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
414 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
415 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
416 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
417 #ifdef S_ISVTX
418 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
419 #endif
420 #ifdef S_ISGID
421 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
422 #endif
423 #ifdef S_ISUID
424 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
425 #endif
427 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
428 ret &= lp_dir_mask(SNUM(conn));
429 /* Add in force bits */
430 ret |= lp_force_dir_mode(SNUM(conn));
431 } else {
432 /* Apply mode mask */
433 ret &= lp_create_mask(SNUM(conn));
434 /* Add in force bits */
435 ret |= lp_force_create_mode(SNUM(conn));
438 return ret;
441 /****************************************************************************
442 Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
443 ****************************************************************************/
445 time_t interpret_long_unix_date(char *p)
447 DEBUG(1,("interpret_long_unix_date\n"));
448 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
449 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
450 return -1;
451 } else {
452 return interpret_long_date(p);
456 /****************************************************************************
457 Get a level dependent lanman2 dir entry.
458 ****************************************************************************/
460 static BOOL get_lanman2_dir_entry(connection_struct *conn,
461 void *inbuf, void *outbuf,
462 char *path_mask,int dirtype,int info_level,
463 int requires_resume_key,
464 BOOL dont_descend,char **ppdata,
465 char *base_data, int space_remaining,
466 BOOL *out_of_space, BOOL *got_exact_match,
467 int *last_name_off)
469 const char *dname;
470 BOOL found = False;
471 SMB_STRUCT_STAT sbuf;
472 pstring mask;
473 pstring pathreal;
474 pstring fname;
475 char *p, *q, *pdata = *ppdata;
476 uint32 reskey=0;
477 int prev_dirpos=0;
478 int mode=0;
479 SMB_OFF_T file_size = 0;
480 SMB_BIG_UINT allocation_size = 0;
481 uint32 len;
482 time_t mdate=0, adate=0, cdate=0;
483 char *nameptr;
484 BOOL was_8_3;
485 int nt_extmode; /* Used for NT connections instead of mode */
486 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
488 *fname = 0;
489 *out_of_space = False;
490 *got_exact_match = False;
492 if (!conn->dirptr)
493 return(False);
495 p = strrchr_m(path_mask,'/');
496 if(p != NULL) {
497 if(p[1] == '\0')
498 pstrcpy(mask,"*.*");
499 else
500 pstrcpy(mask, p+1);
501 } else
502 pstrcpy(mask, path_mask);
504 while (!found) {
505 BOOL got_match;
507 /* Needed if we run out of space */
508 prev_dirpos = TellDir(conn->dirptr);
509 dname = ReadDirName(conn->dirptr);
512 * Due to bugs in NT client redirectors we are not using
513 * resume keys any more - set them to zero.
514 * Check out the related comments in findfirst/findnext.
515 * JRA.
518 reskey = 0;
520 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
521 (long)conn->dirptr,TellDir(conn->dirptr)));
523 if (!dname)
524 return(False);
526 pstrcpy(fname,dname);
528 if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
529 got_match = mask_match(fname, mask, case_sensitive);
531 if(!got_match && !mangle_is_8_3(fname, False)) {
534 * It turns out that NT matches wildcards against
535 * both long *and* short names. This may explain some
536 * of the wildcard wierdness from old DOS clients
537 * that some people have been seeing.... JRA.
540 pstring newname;
541 pstrcpy( newname, fname);
542 mangle_map( newname, True, False, SNUM(conn));
543 if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
544 got_match = mask_match(newname, mask, case_sensitive);
547 if(got_match) {
548 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
549 if (dont_descend && !isdots)
550 continue;
552 pstrcpy(pathreal,conn->dirpath);
553 if(needslash)
554 pstrcat(pathreal,"/");
555 pstrcat(pathreal,dname);
557 if (INFO_LEVEL_IS_UNIX(info_level)) {
558 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
559 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
560 pathreal,strerror(errno)));
561 continue;
563 } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
565 /* Needed to show the msdfs symlinks as
566 * directories */
568 if(lp_host_msdfs() &&
569 lp_msdfs_root(SNUM(conn)) &&
570 is_msdfs_link(conn, pathreal, NULL, NULL,
571 &sbuf)) {
573 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
574 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
576 } else {
578 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
579 pathreal,strerror(errno)));
580 continue;
584 mode = dos_mode(conn,pathreal,&sbuf);
586 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
587 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
588 continue;
591 file_size = get_file_size(sbuf);
592 allocation_size = get_allocation_size(NULL,&sbuf);
593 mdate = sbuf.st_mtime;
594 adate = sbuf.st_atime;
595 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
597 if (lp_dos_filetime_resolution(SNUM(conn))) {
598 cdate &= ~1;
599 mdate &= ~1;
600 adate &= ~1;
603 if(mode & aDIR)
604 file_size = 0;
606 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
608 found = True;
612 mangle_map(fname,False,True,SNUM(conn));
614 p = pdata;
615 nameptr = p;
617 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
619 switch (info_level) {
620 case SMB_INFO_STANDARD:
621 if(requires_resume_key) {
622 SIVAL(p,0,reskey);
623 p += 4;
625 put_dos_date2(p,l1_fdateCreation,cdate);
626 put_dos_date2(p,l1_fdateLastAccess,adate);
627 put_dos_date2(p,l1_fdateLastWrite,mdate);
628 SIVAL(p,l1_cbFile,(uint32)file_size);
629 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
630 SSVAL(p,l1_attrFile,mode);
631 p += l1_achName;
632 nameptr = p;
633 p += align_string(outbuf, p, 0);
634 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
635 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS)
636 SCVAL(nameptr, -1, len-2);
637 else
638 SCVAL(nameptr, -1, len-1);
639 p += len;
640 break;
642 case SMB_INFO_QUERY_EA_SIZE:
643 if(requires_resume_key) {
644 SIVAL(p,0,reskey);
645 p += 4;
647 put_dos_date2(p,l2_fdateCreation,cdate);
648 put_dos_date2(p,l2_fdateLastAccess,adate);
649 put_dos_date2(p,l2_fdateLastWrite,mdate);
650 SIVAL(p,l2_cbFile,(uint32)file_size);
651 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
652 SSVAL(p,l2_attrFile,mode);
653 SIVAL(p,l2_cbList,0); /* No extended attributes */
654 p += l2_achName;
655 nameptr = p;
656 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
657 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS)
658 SCVAL(nameptr, -1, len-2);
659 else
660 SCVAL(nameptr, -1, len-1);
661 p += len;
662 break;
664 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
665 was_8_3 = mangle_is_8_3(fname, True);
666 p += 4;
667 SIVAL(p,0,reskey); p += 4;
668 put_long_date(p,cdate); p += 8;
669 put_long_date(p,adate); p += 8;
670 put_long_date(p,mdate); p += 8;
671 put_long_date(p,mdate); p += 8;
672 SOFF_T(p,0,file_size);
673 SOFF_T(p,8,allocation_size);
674 p += 16;
675 SIVAL(p,0,nt_extmode); p += 4;
676 q = p; p += 4;
677 SIVAL(p,0,0); p += 4;
678 /* Clear the short name buffer. This is
679 * IMPORTANT as not doing so will trigger
680 * a Win2k client bug. JRA.
682 memset(p,'\0',26);
683 if (!was_8_3) {
684 pstring mangled_name;
685 pstrcpy(mangled_name, fname);
686 mangle_map(mangled_name,True,True,SNUM(conn));
687 mangled_name[12] = 0;
688 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
689 SSVAL(p, 0, len);
690 } else {
691 SSVAL(p,0,0);
692 *(p+2) = 0;
694 p += 2 + 24;
695 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
696 SIVAL(q,0,len);
697 p += len;
698 len = PTR_DIFF(p, pdata);
699 len = (len + 3) & ~3;
700 SIVAL(pdata,0,len);
701 p = pdata + len;
702 break;
704 case SMB_FIND_FILE_DIRECTORY_INFO:
705 p += 4;
706 SIVAL(p,0,reskey); p += 4;
707 put_long_date(p,cdate); p += 8;
708 put_long_date(p,adate); p += 8;
709 put_long_date(p,mdate); p += 8;
710 put_long_date(p,mdate); p += 8;
711 SOFF_T(p,0,file_size);
712 SOFF_T(p,8,allocation_size);
713 p += 16;
714 SIVAL(p,0,nt_extmode); p += 4;
715 p += 4;
716 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
717 SIVAL(p, -4, len);
718 p += len;
719 len = PTR_DIFF(p, pdata);
720 len = (len + 3) & ~3;
721 SIVAL(pdata,0,len);
722 p = pdata + len;
723 break;
725 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
726 p += 4;
727 SIVAL(p,0,reskey); p += 4;
728 put_long_date(p,cdate); p += 8;
729 put_long_date(p,adate); p += 8;
730 put_long_date(p,mdate); p += 8;
731 put_long_date(p,mdate); p += 8;
732 SOFF_T(p,0,file_size);
733 SOFF_T(p,8,allocation_size);
734 p += 16;
735 SIVAL(p,0,nt_extmode);
736 p += 4;
738 SIVAL(p,4,0); /* ea size */
739 len = srvstr_push(outbuf, p+8, fname, -1, STR_TERMINATE_ASCII);
740 SIVAL(p, 0, len);
741 p += 8 + len;
743 len = PTR_DIFF(p, pdata);
744 len = (len + 3) & ~3;
745 SIVAL(pdata,0,len);
746 p = pdata + len;
747 break;
749 case SMB_FIND_FILE_NAMES_INFO:
750 p += 4;
751 SIVAL(p,0,reskey); p += 4;
752 p += 4;
753 /* this must *not* be null terminated or w2k gets in a loop trying to set an
754 acl on a dir (tridge) */
755 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
756 SIVAL(p, -4, len);
757 p += len;
758 len = PTR_DIFF(p, pdata);
759 len = (len + 3) & ~3;
760 SIVAL(pdata,0,len);
761 p = pdata + len;
762 break;
764 case SMB_FIND_FILE_LEVEL_261:
765 p += 4;
766 SIVAL(p,0,reskey); p += 4;
767 put_long_date(p,cdate); p += 8;
768 put_long_date(p,adate); p += 8;
769 put_long_date(p,mdate); p += 8;
770 put_long_date(p,mdate); p += 8;
771 SOFF_T(p,0,file_size);
772 SOFF_T(p,8,allocation_size);
773 p += 16;
774 SIVAL(p,0,nt_extmode);
775 p += 4;
776 len = srvstr_push(outbuf, p + 20, fname, -1, STR_TERMINATE_ASCII);
777 SIVAL(p, 0, len);
778 memset(p+4,'\0',16); /* EA size. Unknown 0 1 2 */
779 p += 20 + len; /* Strlen, EA size. Unknown 0 1 2, string itself */
780 len = PTR_DIFF(p, pdata);
781 len = (len + 3) & ~3;
782 SIVAL(pdata,0,len);
783 p = pdata + len;
784 break;
786 case SMB_FIND_FILE_LEVEL_262:
787 was_8_3 = mangle_is_8_3(fname, True);
788 p += 4;
789 SIVAL(p,0,reskey); p += 4;
790 put_long_date(p,cdate); p += 8;
791 put_long_date(p,adate); p += 8;
792 put_long_date(p,mdate); p += 8;
793 put_long_date(p,mdate); p += 8;
794 SOFF_T(p,0,file_size);
795 SOFF_T(p,8,allocation_size);
796 p += 16;
797 SIVAL(p,0,nt_extmode); p += 4;
798 q = p; p += 4;
799 SIVAL(p,0,0); p += 4;
800 /* Clear the short name buffer. This is
801 * IMPORTANT as not doing so will trigger
802 * a Win2k client bug. JRA.
804 memset(p,'\0',26);
805 if (!was_8_3) {
806 pstring mangled_name;
807 pstrcpy(mangled_name, fname);
808 mangle_map(mangled_name,True,True,SNUM(conn));
809 mangled_name[12] = 0;
810 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
811 SSVAL(p, 0, len);
812 } else {
813 SSVAL(p,0,0);
814 *(p+2) = 0;
816 p += 2 + 24;
817 memset(p, '\0', 10); /* 2 4 byte unknowns plus a zero reserved. */
818 p += 10;
819 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
820 SIVAL(q,0,len);
821 p += len;
822 len = PTR_DIFF(p, pdata);
823 len = (len + 3) & ~3;
824 SIVAL(pdata,0,len);
825 p = pdata + len;
826 break;
828 /* CIFS UNIX Extension. */
830 case SMB_FIND_FILE_UNIX:
831 p+= 4;
832 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
834 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
835 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
836 p+= 8;
838 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
839 p+= 8;
841 put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */
842 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
843 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
844 p+= 24;
846 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
847 SIVAL(p,4,0);
848 p+= 8;
850 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
851 SIVAL(p,4,0);
852 p+= 8;
854 SIVAL(p,0,unix_filetype(sbuf.st_mode));
855 p+= 4;
857 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
858 SIVAL(p,4,0);
859 p+= 8;
861 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
862 SIVAL(p,4,0);
863 p+= 8;
865 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
866 p+= 8;
868 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
869 SIVAL(p,4,0);
870 p+= 8;
872 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
873 SIVAL(p,4,0);
874 p+= 8;
876 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
877 p += len;
879 len = PTR_DIFF(p, pdata);
880 len = (len + 3) & ~3;
881 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
882 p = pdata + len;
883 /* End of SMB_QUERY_FILE_UNIX_BASIC */
885 break;
887 default:
888 return(False);
892 if (PTR_DIFF(p,pdata) > space_remaining) {
893 /* Move the dirptr back to prev_dirpos */
894 SeekDir(conn->dirptr, prev_dirpos);
895 *out_of_space = True;
896 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
897 return False; /* Not finished - just out of space */
900 /* Setup the last_filename pointer, as an offset from base_data */
901 *last_name_off = PTR_DIFF(nameptr,base_data);
902 /* Advance the data pointer to the next slot */
903 *ppdata = p;
905 return(found);
908 /****************************************************************************
909 Reply to a TRANS2_FINDFIRST.
910 ****************************************************************************/
912 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
913 char **pparams, int total_params, char **ppdata, int total_data)
915 /* We must be careful here that we don't return more than the
916 allowed number of data bytes. If this means returning fewer than
917 maxentries then so be it. We assume that the redirector has
918 enough room for the fixed number of parameter bytes it has
919 requested. */
920 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
921 char *params = *pparams;
922 char *pdata = *ppdata;
923 int dirtype = SVAL(params,0);
924 int maxentries = SVAL(params,2);
925 BOOL close_after_first = BITSETW(params+4,0);
926 BOOL close_if_end = BITSETW(params+4,1);
927 BOOL requires_resume_key = BITSETW(params+4,2);
928 int info_level = SVAL(params,6);
929 pstring directory;
930 pstring mask;
931 char *p, *wcard;
932 int last_name_off=0;
933 int dptr_num = -1;
934 int numentries = 0;
935 int i;
936 BOOL finished = False;
937 BOOL dont_descend = False;
938 BOOL out_of_space = False;
939 int space_remaining;
940 BOOL bad_path = False;
941 SMB_STRUCT_STAT sbuf;
943 if (total_params < 12)
944 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
946 *directory = *mask = 0;
948 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
949 close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
950 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
951 info_level, max_data_bytes));
953 switch (info_level) {
954 case SMB_INFO_STANDARD:
955 case SMB_INFO_QUERY_EA_SIZE:
956 case SMB_FIND_FILE_DIRECTORY_INFO:
957 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
958 case SMB_FIND_FILE_NAMES_INFO:
959 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
960 case SMB_FIND_FILE_LEVEL_261:
961 case SMB_FIND_FILE_LEVEL_262:
962 break;
963 case SMB_FIND_FILE_UNIX:
964 if (!lp_unix_extensions())
965 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
966 break;
967 default:
968 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
971 srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE);
973 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
975 unix_convert(directory,conn,0,&bad_path,&sbuf);
976 if(!check_name(directory,conn)) {
977 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
980 p = strrchr_m(directory,'/');
981 if(p == NULL) {
982 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
983 if((directory[0] == '.') && (directory[1] == '\0'))
984 pstrcpy(mask,"*");
985 else
986 pstrcpy(mask,directory);
987 pstrcpy(directory,"./");
988 } else {
989 pstrcpy(mask,p+1);
990 *p = 0;
993 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
995 pdata = Realloc(*ppdata, max_data_bytes + 1024);
996 if( pdata == NULL )
997 return(ERROR_DOS(ERRDOS,ERRnomem));
999 *ppdata = pdata;
1000 memset((char *)pdata,'\0',max_data_bytes + 1024);
1002 /* Realloc the params space */
1003 params = Realloc(*pparams, 10);
1004 if (params == NULL)
1005 return ERROR_DOS(ERRDOS,ERRnomem);
1006 *pparams = params;
1008 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1009 if (dptr_num < 0)
1010 return(UNIXERROR(ERRDOS,ERRbadfile));
1012 /* Save the wildcard match and attribs we are using on this directory -
1013 needed as lanman2 assumes these are being saved between calls */
1015 if(!(wcard = strdup(mask))) {
1016 dptr_close(&dptr_num);
1017 return ERROR_DOS(ERRDOS,ERRnomem);
1020 dptr_set_wcard(dptr_num, wcard);
1021 dptr_set_attr(dptr_num, dirtype);
1023 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
1025 /* We don't need to check for VOL here as this is returned by
1026 a different TRANS2 call. */
1028 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1029 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1030 dont_descend = True;
1032 p = pdata;
1033 space_remaining = max_data_bytes;
1034 out_of_space = False;
1036 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1037 BOOL got_exact_match = False;
1039 /* this is a heuristic to avoid seeking the dirptr except when
1040 absolutely necessary. It allows for a filename of about 40 chars */
1041 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1042 out_of_space = True;
1043 finished = False;
1044 } else {
1045 finished = !get_lanman2_dir_entry(conn,
1046 inbuf, outbuf,
1047 mask,dirtype,info_level,
1048 requires_resume_key,dont_descend,
1049 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1050 &last_name_off);
1053 if (finished && out_of_space)
1054 finished = False;
1056 if (!finished && !out_of_space)
1057 numentries++;
1060 * As an optimisation if we know we aren't looking
1061 * for a wildcard name (ie. the name matches the wildcard exactly)
1062 * then we can finish on any (first) match.
1063 * This speeds up large directory searches. JRA.
1066 if(got_exact_match)
1067 finished = True;
1069 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1072 /* Check if we can close the dirptr */
1073 if(close_after_first || (finished && close_if_end)) {
1074 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1075 dptr_close(&dptr_num);
1079 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1080 * from observation of NT.
1083 if(numentries == 0) {
1084 dptr_close(&dptr_num);
1085 return ERROR_DOS(ERRDOS,ERRbadfile);
1088 /* At this point pdata points to numentries directory entries. */
1090 /* Set up the return parameter block */
1091 SSVAL(params,0,dptr_num);
1092 SSVAL(params,2,numentries);
1093 SSVAL(params,4,finished);
1094 SSVAL(params,6,0); /* Never an EA error */
1095 SSVAL(params,8,last_name_off);
1097 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1099 if ((! *directory) && dptr_path(dptr_num))
1100 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1102 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1103 smb_fn_name(CVAL(inbuf,smb_com)),
1104 mask, directory, dirtype, numentries ) );
1107 * Force a name mangle here to ensure that the
1108 * mask as an 8.3 name is top of the mangled cache.
1109 * The reasons for this are subtle. Don't remove
1110 * this code unless you know what you are doing
1111 * (see PR#13758). JRA.
1114 if(!mangle_is_8_3_wildcards( mask, False))
1115 mangle_map(mask, True, True, SNUM(conn));
1117 return(-1);
1120 /****************************************************************************
1121 Reply to a TRANS2_FINDNEXT.
1122 ****************************************************************************/
1124 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1125 char **pparams, int total_params, char **ppdata, int total_data)
1127 /* We must be careful here that we don't return more than the
1128 allowed number of data bytes. If this means returning fewer than
1129 maxentries then so be it. We assume that the redirector has
1130 enough room for the fixed number of parameter bytes it has
1131 requested. */
1132 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1133 char *params = *pparams;
1134 char *pdata = *ppdata;
1135 int dptr_num = SVAL(params,0);
1136 int maxentries = SVAL(params,2);
1137 uint16 info_level = SVAL(params,4);
1138 uint32 resume_key = IVAL(params,6);
1139 BOOL close_after_request = BITSETW(params+10,0);
1140 BOOL close_if_end = BITSETW(params+10,1);
1141 BOOL requires_resume_key = BITSETW(params+10,2);
1142 BOOL continue_bit = BITSETW(params+10,3);
1143 pstring resume_name;
1144 pstring mask;
1145 pstring directory;
1146 char *p;
1147 uint16 dirtype;
1148 int numentries = 0;
1149 int i, last_name_off=0;
1150 BOOL finished = False;
1151 BOOL dont_descend = False;
1152 BOOL out_of_space = False;
1153 int space_remaining;
1155 if (total_params < 12)
1156 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1158 *mask = *directory = *resume_name = 0;
1160 srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE);
1162 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1163 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1164 resume_key = %d resume name = %s continue=%d level = %d\n",
1165 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1166 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1168 switch (info_level) {
1169 case SMB_INFO_STANDARD:
1170 case SMB_INFO_QUERY_EA_SIZE:
1171 case SMB_FIND_FILE_DIRECTORY_INFO:
1172 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1173 case SMB_FIND_FILE_NAMES_INFO:
1174 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1175 break;
1176 case SMB_FIND_FILE_UNIX:
1177 if (!lp_unix_extensions())
1178 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1179 break;
1180 default:
1181 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1184 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1185 if(pdata == NULL)
1186 return ERROR_DOS(ERRDOS,ERRnomem);
1188 *ppdata = pdata;
1189 memset((char *)pdata,'\0',max_data_bytes + 1024);
1191 /* Realloc the params space */
1192 params = Realloc(*pparams, 6*SIZEOFWORD);
1193 if( params == NULL )
1194 return ERROR_DOS(ERRDOS,ERRnomem);
1196 *pparams = params;
1198 /* Check that the dptr is valid */
1199 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1200 return ERROR_DOS(ERRDOS,ERRnofiles);
1202 string_set(&conn->dirpath,dptr_path(dptr_num));
1204 /* Get the wildcard mask from the dptr */
1205 if((p = dptr_wcard(dptr_num))== NULL) {
1206 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1207 return ERROR_DOS(ERRDOS,ERRnofiles);
1210 pstrcpy(mask, p);
1211 pstrcpy(directory,conn->dirpath);
1213 /* Get the attr mask from the dptr */
1214 dirtype = dptr_attr(dptr_num);
1216 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1217 dptr_num, mask, dirtype,
1218 (long)conn->dirptr,
1219 TellDir(conn->dirptr)));
1221 /* We don't need to check for VOL here as this is returned by
1222 a different TRANS2 call. */
1224 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1225 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1226 dont_descend = True;
1228 p = pdata;
1229 space_remaining = max_data_bytes;
1230 out_of_space = False;
1233 * Seek to the correct position. We no longer use the resume key but
1234 * depend on the last file name instead.
1237 if(requires_resume_key && *resume_name && !continue_bit) {
1240 * Fix for NT redirector problem triggered by resume key indexes
1241 * changing between directory scans. We now return a resume key of 0
1242 * and instead look for the filename to continue from (also given
1243 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1244 * findfirst/findnext (as is usual) then the directory pointer
1245 * should already be at the correct place. Check this by scanning
1246 * backwards looking for an exact (ie. case sensitive) filename match.
1247 * If we get to the beginning of the directory and haven't found it then scan
1248 * forwards again looking for a match. JRA.
1251 int current_pos, start_pos;
1252 const char *dname = NULL;
1253 pstring dname_pstring;
1254 void *dirptr = conn->dirptr;
1255 start_pos = TellDir(dirptr);
1256 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1257 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1259 SeekDir(dirptr, current_pos);
1260 dname = ReadDirName(dirptr);
1261 if (dname) {
1263 * Remember, mangle_map is called by
1264 * get_lanman2_dir_entry(), so the resume name
1265 * could be mangled. Ensure we do the same
1266 * here.
1269 /* make sure we get a copy that mangle_map can modify */
1271 pstrcpy(dname_pstring, dname);
1272 mangle_map( dname_pstring, False, True, SNUM(conn));
1274 if(strcsequal( resume_name, dname_pstring)) {
1275 SeekDir(dirptr, current_pos+1);
1276 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1277 break;
1283 * Scan forward from start if not found going backwards.
1286 if(current_pos < 0) {
1287 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1288 SeekDir(dirptr, start_pos);
1289 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1292 * Remember, mangle_map is called by
1293 * get_lanman2_dir_entry(), so the resume name
1294 * could be mangled. Ensure we do the same
1295 * here.
1298 if(dname) {
1299 /* make sure we get a copy that mangle_map can modify */
1301 pstrcpy(dname_pstring, dname);
1302 mangle_map(dname_pstring, False, True, SNUM(conn));
1304 if(strcsequal( resume_name, dname_pstring)) {
1305 SeekDir(dirptr, current_pos+1);
1306 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1307 break;
1310 } /* end for */
1311 } /* end if current_pos */
1312 } /* end if requires_resume_key && !continue_bit */
1314 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1315 BOOL got_exact_match = False;
1317 /* this is a heuristic to avoid seeking the dirptr except when
1318 absolutely necessary. It allows for a filename of about 40 chars */
1319 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1320 out_of_space = True;
1321 finished = False;
1322 } else {
1323 finished = !get_lanman2_dir_entry(conn,
1324 inbuf, outbuf,
1325 mask,dirtype,info_level,
1326 requires_resume_key,dont_descend,
1327 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1328 &last_name_off);
1331 if (finished && out_of_space)
1332 finished = False;
1334 if (!finished && !out_of_space)
1335 numentries++;
1338 * As an optimisation if we know we aren't looking
1339 * for a wildcard name (ie. the name matches the wildcard exactly)
1340 * then we can finish on any (first) match.
1341 * This speeds up large directory searches. JRA.
1344 if(got_exact_match)
1345 finished = True;
1347 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1350 /* Check if we can close the dirptr */
1351 if(close_after_request || (finished && close_if_end)) {
1352 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1353 dptr_close(&dptr_num); /* This frees up the saved mask */
1356 /* Set up the return parameter block */
1357 SSVAL(params,0,numentries);
1358 SSVAL(params,2,finished);
1359 SSVAL(params,4,0); /* Never an EA error */
1360 SSVAL(params,6,last_name_off);
1362 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1364 if ((! *directory) && dptr_path(dptr_num))
1365 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1367 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1368 smb_fn_name(CVAL(inbuf,smb_com)),
1369 mask, directory, dirtype, numentries ) );
1371 return(-1);
1374 /****************************************************************************
1375 Reply to a TRANS2_QFSINFO (query filesystem info).
1376 ****************************************************************************/
1378 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1379 int length, int bufsize,
1380 char **pparams, int total_params, char **ppdata, int total_data)
1382 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1383 char *pdata = *ppdata;
1384 char *params = *pparams;
1385 uint16 info_level = SVAL(params,0);
1386 int data_len, len;
1387 SMB_STRUCT_STAT st;
1388 char *vname = volume_label(SNUM(conn));
1389 int snum = SNUM(conn);
1390 char *fstype = lp_fstype(SNUM(conn));
1391 int quota_flag = 0;
1393 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1395 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1396 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1397 return ERROR_DOS(ERRSRV,ERRinvdevice);
1400 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1401 if ( pdata == NULL )
1402 return ERROR_DOS(ERRDOS,ERRnomem);
1404 *ppdata = pdata;
1405 memset((char *)pdata,'\0',max_data_bytes + 1024);
1407 switch (info_level) {
1408 case SMB_INFO_ALLOCATION:
1410 SMB_BIG_UINT dfree,dsize,bsize;
1411 data_len = 18;
1412 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1413 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1414 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1415 SIVAL(pdata,l1_cUnit,dsize);
1416 SIVAL(pdata,l1_cUnitAvail,dfree);
1417 SSVAL(pdata,l1_cbSector,512);
1418 DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1419 (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1420 (unsigned int)dfree, 512));
1421 break;
1424 case SMB_INFO_VOLUME:
1425 /* Return volume name */
1427 * Add volume serial number - hash of a combination of
1428 * the called hostname and the service name.
1430 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1431 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1432 SCVAL(pdata,l2_vol_cch,len);
1433 data_len = l2_vol_szVolLabel + len;
1434 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1435 (unsigned)st.st_ctime, len, vname));
1436 break;
1438 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1439 case SMB_FS_ATTRIBUTE_INFORMATION:
1442 #if defined(HAVE_SYS_QUOTAS)
1443 quota_flag = FILE_VOLUME_QUOTAS;
1444 #endif
1446 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1447 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1448 quota_flag); /* FS ATTRIBUTES */
1450 SIVAL(pdata,4,255); /* Max filename component length */
1451 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1452 and will think we can't do long filenames */
1453 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1454 SIVAL(pdata,8,len);
1455 data_len = 12 + len;
1456 break;
1458 case SMB_QUERY_FS_LABEL_INFO:
1459 case SMB_FS_LABEL_INFORMATION:
1460 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1461 data_len = 4 + len;
1462 SIVAL(pdata,0,len);
1463 break;
1465 case SMB_QUERY_FS_VOLUME_INFO:
1466 case SMB_FS_VOLUME_INFORMATION:
1469 * Add volume serial number - hash of a combination of
1470 * the called hostname and the service name.
1472 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1473 (str_checksum(local_machine)<<16));
1475 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1476 SIVAL(pdata,12,len);
1477 data_len = 18+len;
1478 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1479 (int)strlen(vname),vname, lp_servicename(snum)));
1480 break;
1482 case SMB_QUERY_FS_SIZE_INFO:
1483 case SMB_FS_SIZE_INFORMATION:
1485 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1486 data_len = 24;
1487 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1488 block_size = lp_block_size(snum);
1489 if (bsize < block_size) {
1490 SMB_BIG_UINT factor = block_size/bsize;
1491 bsize = block_size;
1492 dsize /= factor;
1493 dfree /= factor;
1495 if (bsize > block_size) {
1496 SMB_BIG_UINT factor = bsize/block_size;
1497 bsize = block_size;
1498 dsize *= factor;
1499 dfree *= factor;
1501 bytes_per_sector = 512;
1502 sectors_per_unit = bsize/bytes_per_sector;
1503 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1504 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1505 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1506 SBIG_UINT(pdata,0,dsize);
1507 SBIG_UINT(pdata,8,dfree);
1508 SIVAL(pdata,16,sectors_per_unit);
1509 SIVAL(pdata,20,bytes_per_sector);
1510 break;
1513 case SMB_FS_FULL_SIZE_INFORMATION:
1515 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1516 data_len = 32;
1517 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1518 block_size = lp_block_size(snum);
1519 if (bsize < block_size) {
1520 SMB_BIG_UINT factor = block_size/bsize;
1521 bsize = block_size;
1522 dsize /= factor;
1523 dfree /= factor;
1525 if (bsize > block_size) {
1526 SMB_BIG_UINT factor = bsize/block_size;
1527 bsize = block_size;
1528 dsize *= factor;
1529 dfree *= factor;
1531 bytes_per_sector = 512;
1532 sectors_per_unit = bsize/bytes_per_sector;
1533 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1534 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1535 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1536 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1537 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1538 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1539 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1540 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1541 break;
1544 case SMB_QUERY_FS_DEVICE_INFO:
1545 case SMB_FS_DEVICE_INFORMATION:
1546 data_len = 8;
1547 SIVAL(pdata,0,0); /* dev type */
1548 SIVAL(pdata,4,0); /* characteristics */
1549 break;
1551 #ifdef HAVE_SYS_QUOTAS
1552 case SMB_FS_QUOTA_INFORMATION:
1554 * what we have to send --metze:
1556 * Unknown1: 24 NULL bytes
1557 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1558 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
1559 * Quota Flags: 2 byte :
1560 * Unknown3: 6 NULL bytes
1562 * 48 bytes total
1564 * details for Quota Flags:
1566 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1567 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
1568 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1569 * 0x0001 Enable Quotas: enable quota for this fs
1573 /* we need to fake up a fsp here,
1574 * because its not send in this call
1576 files_struct fsp;
1577 SMB_NTQUOTA_STRUCT quotas;
1579 ZERO_STRUCT(fsp);
1580 ZERO_STRUCT(quotas);
1582 fsp.conn = conn;
1583 fsp.fnum = -1;
1584 fsp.fd = -1;
1586 /* access check */
1587 if (conn->admin_user != True) {
1588 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1589 lp_servicename(SNUM(conn)),conn->user));
1590 return ERROR_DOS(ERRDOS,ERRnoaccess);
1593 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
1594 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
1595 return ERROR_DOS(ERRSRV,ERRerror);
1598 data_len = 48;
1600 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
1602 /* Unknown1 24 NULL bytes*/
1603 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
1604 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
1605 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
1607 /* Default Soft Quota 8 bytes */
1608 SBIG_UINT(pdata,24,quotas.softlim);
1610 /* Default Hard Quota 8 bytes */
1611 SBIG_UINT(pdata,32,quotas.hardlim);
1613 /* Quota flag 2 bytes */
1614 SSVAL(pdata,40,quotas.qflags);
1616 /* Unknown3 6 NULL bytes */
1617 SSVAL(pdata,42,0);
1618 SIVAL(pdata,44,0);
1620 break;
1622 #endif /* HAVE_SYS_QUOTAS */
1623 case SMB_FS_OBJECTID_INFORMATION:
1624 data_len = 64;
1625 break;
1628 * Query the version and capabilities of the CIFS UNIX extensions
1629 * in use.
1632 case SMB_QUERY_CIFS_UNIX_INFO:
1633 if (!lp_unix_extensions())
1634 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1635 data_len = 12;
1636 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
1637 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
1638 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
1639 break;
1641 case SMB_MAC_QUERY_FS_INFO:
1643 * Thursby MAC extension... ONLY on NTFS filesystems
1644 * once we do streams then we don't need this
1646 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1647 data_len = 88;
1648 SIVAL(pdata,84,0x100); /* Don't support mac... */
1649 break;
1651 /* drop through */
1652 default:
1653 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1657 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1659 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1661 return -1;
1664 #ifdef HAVE_SYS_QUOTAS
1665 /****************************************************************************
1666 Reply to a TRANS2_SETFSINFO (set filesystem info).
1667 ****************************************************************************/
1669 static int call_trans2setfsinfo(connection_struct *conn,
1670 char *inbuf, char *outbuf, int length, int bufsize,
1671 char **pparams, int total_params, char **ppdata, int total_data)
1673 char *pdata = *ppdata;
1674 char *params = *pparams;
1675 files_struct *fsp = NULL;
1676 uint16 info_level;
1677 int outsize;
1678 SMB_NTQUOTA_STRUCT quotas;
1680 ZERO_STRUCT(quotas);
1682 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
1684 /* access check */
1685 if ((conn->admin_user != True)||!CAN_WRITE(conn)) {
1686 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1687 lp_servicename(SNUM(conn)),conn->user));
1688 return ERROR_DOS(ERRSRV,ERRaccess);
1691 /* */
1692 if (total_params < 4) {
1693 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
1694 total_params));
1695 return ERROR_DOS(ERRDOS,ERRinvalidparam);
1698 fsp = file_fsp(params,0);
1700 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
1701 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
1702 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
1705 info_level = SVAL(params,2);
1707 switch(info_level) {
1708 case SMB_FS_QUOTA_INFORMATION:
1709 /* note: normaly there're 48 bytes,
1710 * but we didn't use the last 6 bytes for now
1711 * --metze
1713 if (total_data < 42) {
1714 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
1715 total_data));
1716 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1719 /* unknown_1 24 NULL bytes in pdata*/
1721 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
1722 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
1723 #ifdef LARGE_SMB_OFF_T
1724 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
1725 #else /* LARGE_SMB_OFF_T */
1726 if ((IVAL(pdata,28) != 0)&&
1727 ((quotas.softlim != 0xFFFFFFFF)||
1728 (IVAL(pdata,28)!=0xFFFFFFFF))) {
1729 /* more than 32 bits? */
1730 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1732 #endif /* LARGE_SMB_OFF_T */
1734 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
1735 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
1736 #ifdef LARGE_SMB_OFF_T
1737 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
1738 #else /* LARGE_SMB_OFF_T */
1739 if ((IVAL(pdata,36) != 0)&&
1740 ((quotas.hardlim != 0xFFFFFFFF)||
1741 (IVAL(pdata,36)!=0xFFFFFFFF))) {
1742 /* more than 32 bits? */
1743 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1745 #endif /* LARGE_SMB_OFF_T */
1747 /* quota_flags 2 bytes **/
1748 quotas.qflags = SVAL(pdata,40);
1750 /* unknown_2 6 NULL bytes follow*/
1752 /* now set the quotas */
1753 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
1754 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
1755 return ERROR_DOS(ERRSRV,ERRerror);
1758 break;
1759 default:
1760 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
1761 info_level));
1762 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1763 break;
1767 * sending this reply works fine,
1768 * but I'm not sure it's the same
1769 * like windows do...
1770 * --metze
1772 outsize = set_message(outbuf,10,0,True);
1774 return outsize;
1776 #endif /* HAVE_SYS_QUOTAS */
1778 /****************************************************************************
1779 * Utility function to set bad path error.
1780 ****************************************************************************/
1782 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
1784 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
1785 err, (int)bad_path ));
1787 if(err == ENOENT) {
1788 unix_ERR_class = ERRDOS;
1789 if (bad_path) {
1790 unix_ERR_code = ERRbadpath;
1791 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1792 } else {
1793 unix_ERR_code = ERRbadfile;
1794 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
1797 return UNIXERROR(def_class,def_code);
1800 /****************************************************************************
1801 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1802 file name or file id).
1803 ****************************************************************************/
1805 static int call_trans2qfilepathinfo(connection_struct *conn,
1806 char *inbuf, char *outbuf, int length,
1807 int bufsize,
1808 char **pparams, int total_params, char **ppdata, int total_data)
1810 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1811 char *params = *pparams;
1812 char *pdata = *ppdata;
1813 uint16 tran_call = SVAL(inbuf, smb_setup0);
1814 uint16 info_level;
1815 int mode=0;
1816 SMB_OFF_T file_size=0;
1817 SMB_BIG_UINT allocation_size=0;
1818 unsigned int data_size;
1819 SMB_STRUCT_STAT sbuf;
1820 pstring fname, dos_fname;
1821 char *fullpathname;
1822 char *base_name;
1823 char *p;
1824 SMB_OFF_T pos = 0;
1825 BOOL bad_path = False;
1826 BOOL delete_pending = False;
1827 int len;
1828 time_t c_time;
1829 files_struct *fsp = NULL;
1831 if (!params)
1832 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1834 if (tran_call == TRANSACT2_QFILEINFO) {
1835 if (total_params < 4)
1836 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1838 fsp = file_fsp(params,0);
1839 info_level = SVAL(params,2);
1841 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1843 if(fsp && (fsp->fake_file_handle)) {
1845 * This is actually for the QUOTA_FAKE_FILE --metze
1848 pstrcpy(fname, fsp->fsp_name);
1849 unix_convert(fname,conn,0,&bad_path,&sbuf);
1850 if (!check_name(fname,conn)) {
1851 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno)));
1852 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1855 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1857 * This is actually a QFILEINFO on a directory
1858 * handle (returned from an NT SMB). NT5.0 seems
1859 * to do this call. JRA.
1861 pstrcpy(fname, fsp->fsp_name);
1862 unix_convert(fname,conn,0,&bad_path,&sbuf);
1863 if (!check_name(fname,conn)) {
1864 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1865 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1868 if (INFO_LEVEL_IS_UNIX(info_level)) {
1869 /* Always do lstat for UNIX calls. */
1870 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
1871 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
1872 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1874 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
1875 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
1876 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1879 delete_pending = fsp->directory_delete_on_close;
1880 } else {
1882 * Original code - this is an open file.
1884 CHECK_FSP(fsp,conn);
1886 pstrcpy(fname, fsp->fsp_name);
1887 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
1888 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
1889 return(UNIXERROR(ERRDOS,ERRbadfid));
1891 pos = fsp->position_information;
1892 delete_pending = fsp->delete_on_close;
1894 } else {
1895 /* qpathinfo */
1896 if (total_params < 6)
1897 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1899 info_level = SVAL(params,0);
1901 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1903 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
1905 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1907 unix_convert(fname,conn,0,&bad_path,&sbuf);
1908 if (!check_name(fname,conn)) {
1909 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1910 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1913 if (INFO_LEVEL_IS_UNIX(info_level)) {
1914 /* Always do lstat for UNIX calls. */
1915 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
1916 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
1917 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1919 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
1920 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
1921 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1925 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
1926 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1928 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
1929 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
1931 p = strrchr_m(fname,'/');
1932 if (!p)
1933 base_name = fname;
1934 else
1935 base_name = p+1;
1937 mode = dos_mode(conn,fname,&sbuf);
1938 if (!mode)
1939 mode = FILE_ATTRIBUTE_NORMAL;
1941 fullpathname = fname;
1942 file_size = get_file_size(sbuf);
1943 allocation_size = get_allocation_size(fsp,&sbuf);
1944 if (mode & aDIR)
1945 file_size = 0;
1947 params = Realloc(*pparams,2);
1948 if (params == NULL)
1949 return ERROR_DOS(ERRDOS,ERRnomem);
1950 *pparams = params;
1951 memset((char *)params,'\0',2);
1952 data_size = max_data_bytes + 1024;
1953 pdata = Realloc(*ppdata, data_size);
1954 if ( pdata == NULL )
1955 return ERROR_DOS(ERRDOS,ERRnomem);
1956 *ppdata = pdata;
1958 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1959 /* uggh, EAs for OS2 */
1960 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1961 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1964 memset((char *)pdata,'\0',data_size);
1966 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1968 if (lp_dos_filetime_resolution(SNUM(conn))) {
1969 c_time &= ~1;
1970 sbuf.st_atime &= ~1;
1971 sbuf.st_mtime &= ~1;
1972 sbuf.st_mtime &= ~1;
1975 /* NT expects the name to be in an exact form of the *full*
1976 filename. See the trans2 torture test */
1977 if (strequal(base_name,".")) {
1978 pstrcpy(dos_fname, "\\");
1979 } else {
1980 pstr_sprintf(dos_fname, "\\%s", fname);
1981 string_replace(dos_fname, '/', '\\');
1984 switch (info_level) {
1985 case SMB_INFO_STANDARD:
1986 case SMB_INFO_QUERY_EA_SIZE:
1987 data_size = (info_level==1?22:26);
1988 put_dos_date2(pdata,l1_fdateCreation,c_time);
1989 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1990 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1991 SIVAL(pdata,l1_cbFile,(uint32)file_size);
1992 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
1993 SSVAL(pdata,l1_attrFile,mode);
1994 SIVAL(pdata,l1_attrFile+2,0); /* this is what win2003 does */
1995 break;
1997 case SMB_INFO_IS_NAME_VALID:
1998 if (tran_call == TRANSACT2_QFILEINFO) {
1999 /* os/2 needs this ? really ?*/
2000 return ERROR_DOS(ERRDOS,ERRbadfunc);
2002 data_size = 0;
2003 break;
2005 case SMB_INFO_QUERY_EAS_FROM_LIST:
2006 data_size = 24;
2007 put_dos_date2(pdata,0,c_time);
2008 put_dos_date2(pdata,4,sbuf.st_atime);
2009 put_dos_date2(pdata,8,sbuf.st_mtime);
2010 SIVAL(pdata,12,(uint32)file_size);
2011 SIVAL(pdata,16,(uint32)allocation_size);
2012 SIVAL(pdata,20,mode);
2013 break;
2015 case SMB_INFO_QUERY_ALL_EAS:
2016 data_size = 4;
2017 SIVAL(pdata,0,0); /* ea size */
2018 break;
2020 case SMB_FILE_BASIC_INFORMATION:
2021 case SMB_QUERY_FILE_BASIC_INFO:
2023 if (info_level == SMB_QUERY_FILE_BASIC_INFO)
2024 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2025 else {
2026 data_size = 40;
2027 SIVAL(pdata,36,0);
2029 put_long_date(pdata,c_time);
2030 put_long_date(pdata+8,sbuf.st_atime);
2031 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2032 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2033 SIVAL(pdata,32,mode);
2035 DEBUG(5,("SMB_QFBI - "));
2037 time_t create_time = c_time;
2038 DEBUG(5,("create: %s ", ctime(&create_time)));
2040 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2041 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2042 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2043 DEBUG(5,("mode: %x\n", mode));
2045 break;
2047 case SMB_FILE_STANDARD_INFORMATION:
2048 case SMB_QUERY_FILE_STANDARD_INFO:
2050 data_size = 24;
2051 SOFF_T(pdata,0,allocation_size);
2052 SOFF_T(pdata,8,file_size);
2053 if (delete_pending & sbuf.st_nlink)
2054 SIVAL(pdata,16,sbuf.st_nlink - 1);
2055 else
2056 SIVAL(pdata,16,sbuf.st_nlink);
2057 SCVAL(pdata,20,0);
2058 SCVAL(pdata,21,(mode&aDIR)?1:0);
2059 break;
2061 case SMB_FILE_EA_INFORMATION:
2062 case SMB_QUERY_FILE_EA_INFO:
2063 data_size = 4;
2064 break;
2066 /* Get the 8.3 name - used if NT SMB was negotiated. */
2067 case SMB_QUERY_FILE_ALT_NAME_INFO:
2068 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2070 pstring short_name;
2072 pstrcpy(short_name,base_name);
2073 /* Mangle if not already 8.3 */
2074 if(!mangle_is_8_3(short_name, True)) {
2075 mangle_map(short_name,True,True,SNUM(conn));
2077 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2078 data_size = 4 + len;
2079 SIVAL(pdata,0,len);
2080 break;
2083 case SMB_QUERY_FILE_NAME_INFO:
2085 this must be *exactly* right for ACLs on mapped drives to work
2087 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2088 data_size = 4 + len;
2089 SIVAL(pdata,0,len);
2090 break;
2092 case SMB_FILE_ALLOCATION_INFORMATION:
2093 case SMB_QUERY_FILE_ALLOCATION_INFO:
2094 data_size = 8;
2095 SOFF_T(pdata,0,allocation_size);
2096 break;
2098 case SMB_FILE_END_OF_FILE_INFORMATION:
2099 case SMB_QUERY_FILE_END_OF_FILEINFO:
2100 data_size = 8;
2101 SOFF_T(pdata,0,file_size);
2102 break;
2104 case SMB_QUERY_FILE_ALL_INFO:
2105 case SMB_FILE_ALL_INFORMATION:
2106 put_long_date(pdata,c_time);
2107 put_long_date(pdata+8,sbuf.st_atime);
2108 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2109 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2110 SIVAL(pdata,32,mode);
2111 pdata += 40;
2112 SOFF_T(pdata,0,allocation_size);
2113 SOFF_T(pdata,8,file_size);
2114 if (delete_pending && sbuf.st_nlink)
2115 SIVAL(pdata,16,sbuf.st_nlink - 1);
2116 else
2117 SIVAL(pdata,16,sbuf.st_nlink);
2118 SCVAL(pdata,20,delete_pending);
2119 SCVAL(pdata,21,(mode&aDIR)?1:0);
2120 pdata += 24;
2121 pdata += 4; /* EA info */
2122 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2123 SIVAL(pdata,0,len);
2124 pdata += 4 + len;
2125 data_size = PTR_DIFF(pdata,(*ppdata));
2126 break;
2128 case SMB_FILE_INTERNAL_INFORMATION:
2129 /* This should be an index number - looks like
2130 dev/ino to me :-)
2132 I think this causes us to fail the IFSKIT
2133 BasicFileInformationTest. -tpot */
2135 SIVAL(pdata,0,sbuf.st_dev);
2136 SIVAL(pdata,4,sbuf.st_ino);
2137 data_size = 8;
2138 break;
2140 case SMB_FILE_ACCESS_INFORMATION:
2141 SIVAL(pdata,0,0x12019F); /* ??? */
2142 data_size = 4;
2143 break;
2145 case SMB_FILE_NAME_INFORMATION:
2146 /* Pathname with leading '\'. */
2148 size_t byte_len;
2149 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2150 SIVAL(pdata,0,byte_len);
2151 data_size = 4 + byte_len;
2152 break;
2155 case SMB_FILE_DISPOSITION_INFORMATION:
2156 data_size = 1;
2157 SCVAL(pdata,0,delete_pending);
2158 break;
2160 case SMB_FILE_POSITION_INFORMATION:
2161 data_size = 8;
2162 SOFF_T(pdata,0,pos);
2163 break;
2165 case SMB_FILE_MODE_INFORMATION:
2166 SIVAL(pdata,0,mode);
2167 data_size = 4;
2168 break;
2170 case SMB_FILE_ALIGNMENT_INFORMATION:
2171 SIVAL(pdata,0,0); /* No alignment needed. */
2172 data_size = 4;
2173 break;
2175 #if 0
2177 * NT4 server just returns "invalid query" to this - if we try to answer
2178 * it then NTws gets a BSOD! (tridge).
2179 * W2K seems to want this. JRA.
2181 case SMB_QUERY_FILE_STREAM_INFO:
2182 #endif
2183 case SMB_FILE_STREAM_INFORMATION:
2184 if (mode & aDIR) {
2185 data_size = 0;
2186 } else {
2187 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2188 SIVAL(pdata,0,0); /* ??? */
2189 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2190 SOFF_T(pdata,8,file_size);
2191 SIVAL(pdata,16,allocation_size);
2192 SIVAL(pdata,20,0); /* ??? */
2193 data_size = 24 + byte_len;
2195 break;
2197 case SMB_QUERY_COMPRESSION_INFO:
2198 case SMB_FILE_COMPRESSION_INFORMATION:
2199 SOFF_T(pdata,0,file_size);
2200 SIVAL(pdata,8,0); /* ??? */
2201 SIVAL(pdata,12,0); /* ??? */
2202 data_size = 16;
2203 break;
2205 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2206 put_long_date(pdata,c_time);
2207 put_long_date(pdata+8,sbuf.st_atime);
2208 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2209 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2210 SIVAL(pdata,32,allocation_size);
2211 SOFF_T(pdata,40,file_size);
2212 SIVAL(pdata,48,mode);
2213 SIVAL(pdata,52,0); /* ??? */
2214 data_size = 56;
2215 break;
2217 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2218 SIVAL(pdata,0,mode);
2219 SIVAL(pdata,4,0);
2220 data_size = 8;
2221 break;
2224 * CIFS UNIX Extensions.
2227 case SMB_QUERY_FILE_UNIX_BASIC:
2229 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2231 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2232 pdata += 8;
2234 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2235 pdata += 8;
2237 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2238 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2239 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2240 pdata += 24;
2242 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2243 SIVAL(pdata,4,0);
2244 pdata += 8;
2246 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2247 SIVAL(pdata,4,0);
2248 pdata += 8;
2250 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2251 pdata += 4;
2253 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2254 SIVAL(pdata,4,0);
2255 pdata += 8;
2257 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2258 SIVAL(pdata,4,0);
2259 pdata += 8;
2261 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2262 pdata += 8;
2264 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2265 SIVAL(pdata,4,0);
2266 pdata += 8;
2268 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2269 SIVAL(pdata,4,0);
2270 pdata += 8+1;
2271 data_size = PTR_DIFF(pdata,(*ppdata));
2274 int i;
2275 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2277 for (i=0; i<100; i++)
2278 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2279 DEBUG(4,("\n"));
2282 break;
2284 case SMB_QUERY_FILE_UNIX_LINK:
2286 pstring buffer;
2288 #ifdef S_ISLNK
2289 if(!S_ISLNK(sbuf.st_mode))
2290 return(UNIXERROR(ERRSRV,ERRbadlink));
2291 #else
2292 return(UNIXERROR(ERRDOS,ERRbadlink));
2293 #endif
2294 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2295 if (len == -1)
2296 return(UNIXERROR(ERRDOS,ERRnoaccess));
2297 buffer[len] = 0;
2298 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2299 pdata += len;
2300 data_size = PTR_DIFF(pdata,(*ppdata));
2302 break;
2305 default:
2306 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2309 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size);
2311 return(-1);
2314 /****************************************************************************
2315 Deal with the internal needs of setting the delete on close flag. Note that
2316 as the tdb locking is recursive, it is safe to call this from within
2317 open_file_shared. JRA.
2318 ****************************************************************************/
2320 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2323 * Only allow delete on close for writable shares.
2326 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2327 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2328 fsp->fsp_name ));
2329 return NT_STATUS_ACCESS_DENIED;
2332 * Only allow delete on close for files/directories opened with delete intent.
2335 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2336 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2337 fsp->fsp_name ));
2338 return NT_STATUS_ACCESS_DENIED;
2341 if(fsp->is_directory) {
2342 fsp->directory_delete_on_close = delete_on_close;
2343 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2344 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2345 } else {
2346 fsp->delete_on_close = delete_on_close;
2347 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2348 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2351 return NT_STATUS_OK;
2354 /****************************************************************************
2355 Sets the delete on close flag over all share modes on this file.
2356 Modify the share mode entry for all files open
2357 on this device and inode to tell other smbds we have
2358 changed the delete on close flag. This will be noticed
2359 in the close code, the last closer will delete the file
2360 if flag is set.
2361 ****************************************************************************/
2363 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2365 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2366 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2368 if (fsp->is_directory || fsp->is_stat)
2369 return NT_STATUS_OK;
2371 if (lock_share_entry_fsp(fsp) == False)
2372 return NT_STATUS_ACCESS_DENIED;
2374 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2375 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2376 fsp->fsp_name ));
2377 unlock_share_entry_fsp(fsp);
2378 return NT_STATUS_ACCESS_DENIED;
2381 unlock_share_entry_fsp(fsp);
2382 return NT_STATUS_OK;
2385 /****************************************************************************
2386 Returns true if this pathname is within the share, and thus safe.
2387 ****************************************************************************/
2389 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2391 #ifdef PATH_MAX
2392 char resolved_name[PATH_MAX+1];
2393 #else
2394 pstring resolved_name;
2395 #endif
2396 fstring last_component;
2397 pstring link_dest;
2398 pstring link_test;
2399 char *p;
2400 BOOL bad_path = False;
2401 SMB_STRUCT_STAT sbuf;
2403 pstrcpy(link_dest, link_dest_in);
2404 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2406 /* Store the UNIX converted path. */
2407 pstrcpy(link_dest_out, link_dest);
2409 p = strrchr(link_dest, '/');
2410 if (p) {
2411 fstrcpy(last_component, p+1);
2412 *p = '\0';
2413 } else {
2414 fstrcpy(last_component, link_dest);
2415 pstrcpy(link_dest, "./");
2418 if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL)
2419 return -1;
2421 pstrcpy(link_dest, resolved_name);
2422 pstrcat(link_dest, "/");
2423 pstrcat(link_dest, last_component);
2425 if (*link_dest != '/') {
2426 /* Relative path. */
2427 pstrcpy(link_test, conn->connectpath);
2428 pstrcat(link_test, "/");
2429 pstrcat(link_test, link_dest);
2430 } else {
2431 pstrcpy(link_test, link_dest);
2435 * Check if the link is within the share.
2438 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2439 errno = EACCES;
2440 return -1;
2442 return 0;
2445 /****************************************************************************
2446 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2447 ****************************************************************************/
2449 static int call_trans2setfilepathinfo(connection_struct *conn,
2450 char *inbuf, char *outbuf, int length, int bufsize,
2451 char **pparams, int total_params, char **ppdata, int total_data)
2453 char *params = *pparams;
2454 char *pdata = *ppdata;
2455 uint16 tran_call = SVAL(inbuf, smb_setup0);
2456 uint16 info_level;
2457 int dosmode=0;
2458 SMB_OFF_T size=0;
2459 struct utimbuf tvs;
2460 SMB_STRUCT_STAT sbuf;
2461 pstring fname;
2462 int fd = -1;
2463 BOOL bad_path = False;
2464 files_struct *fsp = NULL;
2465 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2466 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2467 mode_t unixmode = 0;
2469 if (!params)
2470 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2472 if (tran_call == TRANSACT2_SETFILEINFO) {
2473 if (total_params < 4)
2474 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2476 fsp = file_fsp(params,0);
2477 info_level = SVAL(params,2);
2479 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2481 * This is actually a SETFILEINFO on a directory
2482 * handle (returned from an NT SMB). NT5.0 seems
2483 * to do this call. JRA.
2485 pstrcpy(fname, fsp->fsp_name);
2486 unix_convert(fname,conn,0,&bad_path,&sbuf);
2487 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2488 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2489 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2491 } else if (fsp && fsp->print_file) {
2493 * Doing a DELETE_ON_CLOSE should cancel a print job.
2495 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
2496 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2498 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
2500 SSVAL(params,0,0);
2501 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2502 return(-1);
2503 } else
2504 return (UNIXERROR(ERRDOS,ERRbadpath));
2505 } else {
2507 * Original code - this is an open file.
2509 CHECK_FSP(fsp,conn);
2511 pstrcpy(fname, fsp->fsp_name);
2512 fd = fsp->fd;
2514 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
2515 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2516 return(UNIXERROR(ERRDOS,ERRbadfid));
2519 } else {
2520 /* set path info */
2521 if (total_params < 6)
2522 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2524 info_level = SVAL(params,0);
2525 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
2526 unix_convert(fname,conn,0,&bad_path,&sbuf);
2527 if(!check_name(fname, conn)) {
2528 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2532 * For CIFS UNIX extensions the target name may not exist.
2535 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2536 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
2537 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2541 if (!CAN_WRITE(conn))
2542 return ERROR_DOS(ERRSRV,ERRaccess);
2544 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2545 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2547 if (VALID_STAT(sbuf))
2548 unixmode = sbuf.st_mode;
2550 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
2551 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
2553 /* Realloc the parameter and data sizes */
2554 params = Realloc(*pparams,2);
2555 if(params == NULL)
2556 return ERROR_DOS(ERRDOS,ERRnomem);
2557 *pparams = params;
2559 SSVAL(params,0,0);
2561 if (fsp) {
2562 /* the pending modtime overrides the current modtime */
2563 sbuf.st_mtime = fsp->pending_modtime;
2566 size = get_file_size(sbuf);
2567 tvs.modtime = sbuf.st_mtime;
2568 tvs.actime = sbuf.st_atime;
2569 dosmode = dos_mode(conn,fname,&sbuf);
2570 unixmode = sbuf.st_mode;
2572 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2573 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2575 switch (info_level) {
2576 case SMB_INFO_STANDARD:
2578 if (total_data < 12)
2579 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2581 /* access time */
2582 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2583 /* write time */
2584 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2585 break;
2588 case SMB_INFO_SET_EA:
2589 return(ERROR_DOS(ERRDOS,ERReasnotsupported));
2591 /* XXXX um, i don't think this is right.
2592 it's also not in the cifs6.txt spec.
2594 case SMB_INFO_QUERY_EAS_FROM_LIST:
2595 if (total_data < 28)
2596 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2598 tvs.actime = make_unix_date2(pdata+8);
2599 tvs.modtime = make_unix_date2(pdata+12);
2600 size = IVAL(pdata,16);
2601 dosmode = IVAL(pdata,24);
2602 break;
2604 /* XXXX nor this. not in cifs6.txt, either. */
2605 case SMB_INFO_QUERY_ALL_EAS:
2606 if (total_data < 28)
2607 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2609 tvs.actime = make_unix_date2(pdata+8);
2610 tvs.modtime = make_unix_date2(pdata+12);
2611 size = IVAL(pdata,16);
2612 dosmode = IVAL(pdata,24);
2613 break;
2615 case SMB_SET_FILE_BASIC_INFO:
2616 case SMB_FILE_BASIC_INFORMATION:
2618 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2619 time_t write_time;
2620 time_t changed_time;
2622 if (total_data < 36)
2623 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2625 /* Ignore create time at offset pdata. */
2627 /* access time */
2628 tvs.actime = interpret_long_date(pdata+8);
2630 write_time = interpret_long_date(pdata+16);
2631 changed_time = interpret_long_date(pdata+24);
2633 tvs.modtime = MIN(write_time, changed_time);
2635 if (write_time > tvs.modtime && write_time != 0xffffffff) {
2636 tvs.modtime = write_time;
2638 /* Prefer a defined time to an undefined one. */
2639 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2640 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2641 ? changed_time : write_time);
2643 /* attributes */
2644 dosmode = IVAL(pdata,32);
2645 break;
2648 case SMB_FILE_ALLOCATION_INFORMATION:
2649 case SMB_SET_FILE_ALLOCATION_INFO:
2651 int ret = -1;
2652 SMB_BIG_UINT allocation_size;
2654 if (total_data < 8)
2655 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2657 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
2658 #ifdef LARGE_SMB_OFF_T
2659 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
2660 #else /* LARGE_SMB_OFF_T */
2661 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2662 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2663 #endif /* LARGE_SMB_OFF_T */
2664 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2665 fname, (double)allocation_size ));
2667 if (allocation_size)
2668 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
2670 if(allocation_size != get_file_size(sbuf)) {
2671 SMB_STRUCT_STAT new_sbuf;
2673 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2674 fname, (double)allocation_size ));
2676 if (fd == -1) {
2677 files_struct *new_fsp = NULL;
2678 int access_mode = 0;
2679 int action = 0;
2681 if(global_oplock_break) {
2682 /* Queue this file modify as we are the process of an oplock break. */
2684 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2685 DEBUGADD(2,( "in oplock break state.\n"));
2687 push_oplock_pending_smb_message(inbuf, length);
2688 return -1;
2691 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2692 SET_OPEN_MODE(DOS_OPEN_RDWR),
2693 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2694 0, 0, &access_mode, &action);
2696 if (new_fsp == NULL)
2697 return(UNIXERROR(ERRDOS,ERRbadpath));
2698 ret = vfs_allocate_file_space(new_fsp, allocation_size);
2699 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2700 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2701 new_fsp->fnum, strerror(errno)));
2702 ret = -1;
2704 close_file(new_fsp,True);
2705 } else {
2706 ret = vfs_allocate_file_space(fsp, allocation_size);
2707 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
2708 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2709 fsp->fnum, strerror(errno)));
2710 ret = -1;
2713 if (ret == -1)
2714 return ERROR_NT(NT_STATUS_DISK_FULL);
2716 /* Allocate can truncate size... */
2717 size = get_file_size(new_sbuf);
2720 break;
2723 case SMB_FILE_END_OF_FILE_INFORMATION:
2724 case SMB_SET_FILE_END_OF_FILE_INFO:
2726 if (total_data < 8)
2727 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2729 size = IVAL(pdata,0);
2730 #ifdef LARGE_SMB_OFF_T
2731 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2732 #else /* LARGE_SMB_OFF_T */
2733 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2734 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2735 #endif /* LARGE_SMB_OFF_T */
2736 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2737 break;
2740 case SMB_FILE_DISPOSITION_INFORMATION:
2741 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2743 BOOL delete_on_close;
2744 NTSTATUS status;
2746 if (total_data < 1)
2747 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2749 delete_on_close = (CVAL(pdata,0) ? True : False);
2751 /* Just ignore this set on a path. */
2752 if (tran_call != TRANSACT2_SETFILEINFO)
2753 break;
2755 if (fsp == NULL)
2756 return(UNIXERROR(ERRDOS,ERRbadfid));
2758 status = set_delete_on_close_internal(fsp, delete_on_close);
2760 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2761 return ERROR_NT(status);
2763 /* The set is across all open files on this dev/inode pair. */
2764 status =set_delete_on_close_over_all(fsp, delete_on_close);
2765 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2766 return ERROR_NT(status);
2768 break;
2771 case SMB_FILE_POSITION_INFORMATION:
2773 SMB_BIG_UINT position_information;
2775 if (total_data < 8)
2776 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2778 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
2779 #ifdef LARGE_SMB_OFF_T
2780 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
2781 #else /* LARGE_SMB_OFF_T */
2782 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2783 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2784 #endif /* LARGE_SMB_OFF_T */
2785 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
2786 fname, (double)position_information ));
2787 if (fsp)
2788 fsp->position_information = position_information;
2789 break;
2793 * CIFS UNIX extensions.
2796 case SMB_SET_FILE_UNIX_BASIC:
2798 uint32 raw_unixmode;
2800 if (total_data < 100)
2801 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2803 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
2804 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
2805 size=IVAL(pdata,0); /* first 8 Bytes are size */
2806 #ifdef LARGE_SMB_OFF_T
2807 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2808 #else /* LARGE_SMB_OFF_T */
2809 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2810 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2811 #endif /* LARGE_SMB_OFF_T */
2813 pdata+=24; /* ctime & st_blocks are not changed */
2814 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
2815 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
2816 pdata+=16;
2817 set_owner = (uid_t)IVAL(pdata,0);
2818 pdata += 8;
2819 set_grp = (gid_t)IVAL(pdata,0);
2820 pdata += 8;
2821 raw_unixmode = IVAL(pdata,28);
2822 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2823 dosmode = 0; /* Ensure dos mode change doesn't override this. */
2825 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2826 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2827 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2829 if (!VALID_STAT(sbuf)) {
2832 * The only valid use of this is to create character and block
2833 * devices, and named pipes. This is deprecated (IMHO) and
2834 * a new info level should be used for mknod. JRA.
2837 #if !defined(HAVE_MAKEDEV_FN)
2838 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2839 #else /* HAVE_MAKEDEV_FN */
2840 uint32 file_type = IVAL(pdata,0);
2841 uint32 dev_major = IVAL(pdata,4);
2842 uint32 dev_minor = IVAL(pdata,12);
2844 uid_t myuid = geteuid();
2845 gid_t mygid = getegid();
2846 SMB_DEV_T dev;
2848 if (tran_call == TRANSACT2_SETFILEINFO)
2849 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2851 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2852 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2854 dev = makedev(dev_major, dev_minor);
2856 /* We can only create as the owner/group we are. */
2858 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2859 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2860 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2861 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2863 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2864 file_type != UNIX_TYPE_FIFO)
2865 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2867 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2868 0%o for file %s\n", (double)dev, unixmode, fname ));
2870 /* Ok - do the mknod. */
2871 if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
2872 return(UNIXERROR(ERRDOS,ERRnoaccess));
2874 inherit_access_acl(conn, fname, unixmode);
2876 SSVAL(params,0,0);
2877 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2878 return(-1);
2879 #endif /* HAVE_MAKEDEV_FN */
2884 * Deal with the UNIX specific mode set.
2887 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
2888 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2889 (unsigned int)unixmode, fname ));
2890 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
2891 return(UNIXERROR(ERRDOS,ERRnoaccess));
2895 * Deal with the UNIX specific uid set.
2898 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
2899 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2900 (unsigned int)set_owner, fname ));
2901 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
2902 return(UNIXERROR(ERRDOS,ERRnoaccess));
2906 * Deal with the UNIX specific gid set.
2909 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
2910 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2911 (unsigned int)set_owner, fname ));
2912 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
2913 return(UNIXERROR(ERRDOS,ERRnoaccess));
2915 break;
2918 case SMB_SET_FILE_UNIX_LINK:
2920 pstring link_dest;
2921 /* Set a symbolic link. */
2922 /* Don't allow this if follow links is false. */
2924 if (!lp_symlinks(SNUM(conn)))
2925 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2927 /* Disallow if already exists. */
2928 if (VALID_STAT(sbuf))
2929 return(ERROR_DOS(ERRDOS,ERRbadpath));
2931 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2933 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2934 return(UNIXERROR(ERRDOS,ERRnoaccess));
2936 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2937 fname, link_dest ));
2939 if (SMB_VFS_SYMLINK(conn,link_dest,fname) != 0)
2940 return(UNIXERROR(ERRDOS,ERRnoaccess));
2941 SSVAL(params,0,0);
2942 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2943 return(-1);
2946 case SMB_SET_FILE_UNIX_HLINK:
2948 pstring link_dest;
2950 /* Set a hard link. */
2952 /* Disallow if already exists. */
2953 if (VALID_STAT(sbuf))
2954 return(ERROR_DOS(ERRDOS,ERRbadpath));
2956 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2958 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2959 return(UNIXERROR(ERRDOS,ERRnoaccess));
2961 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2962 fname, link_dest ));
2964 if (SMB_VFS_LINK(conn,link_dest,fname) != 0)
2965 return(UNIXERROR(ERRDOS,ERRnoaccess));
2966 SSVAL(params,0,0);
2967 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2968 return(-1);
2971 case SMB_FILE_RENAME_INFORMATION:
2973 BOOL overwrite;
2974 uint32 root_fid;
2975 uint32 len;
2976 pstring newname;
2977 pstring base_name;
2978 char *p;
2979 NTSTATUS status;
2981 if (total_data < 12)
2982 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2984 overwrite = (CVAL(pdata,0) ? True : False);
2985 root_fid = IVAL(pdata,4);
2986 len = IVAL(pdata,8);
2987 srvstr_pull(inbuf, newname, &pdata[12], sizeof(newname), len, 0);
2989 /* Check the new name has no '\' characters. */
2990 if (strchr_m(newname, '\\') || strchr_m(newname, '/'))
2991 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2993 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
2995 /* Create the base directory. */
2996 pstrcpy(base_name, fname);
2997 p = strrchr_m(base_name, '/');
2998 if (p)
2999 *p = '\0';
3000 /* Append the new name. */
3001 pstrcat(base_name, "/");
3002 pstrcat(base_name, newname);
3004 if (fsp) {
3005 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3006 fsp->fnum, fsp->fsp_name, base_name ));
3007 status = rename_internals_fsp(conn, fsp, base_name, overwrite);
3008 } else {
3009 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3010 fname, newname ));
3011 status = rename_internals(conn, fname, base_name, overwrite);
3013 if (!NT_STATUS_IS_OK(status))
3014 return ERROR_NT(status);
3015 process_pending_change_notify_queue((time_t)0);
3016 SSVAL(params,0,0);
3017 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3018 return(-1);
3020 default:
3021 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3024 /* get some defaults (no modifications) if any info is zero or -1. */
3025 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
3026 tvs.actime = sbuf.st_atime;
3028 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3029 tvs.modtime = sbuf.st_mtime;
3031 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3032 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3033 DEBUG(6,("size: %.0f ", (double)size));
3035 if (dosmode) {
3036 if (S_ISDIR(sbuf.st_mode))
3037 dosmode |= aDIR;
3038 else
3039 dosmode &= ~aDIR;
3042 DEBUG(6,("dosmode: %x\n" , dosmode));
3044 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3045 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3046 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3047 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3050 * Only do this test if we are not explicitly
3051 * changing the size of a file.
3053 if (!size)
3054 size = get_file_size(sbuf);
3058 * Try and set the times, size and mode of this file -
3059 * if they are different from the current values
3061 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3062 if(fsp != NULL) {
3064 * This was a setfileinfo on an open file.
3065 * NT does this a lot. It's actually pointless
3066 * setting the time here, as it will be overwritten
3067 * on the next write, so we save the request
3068 * away and will set it on file close. JRA.
3071 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3072 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3073 fsp->pending_modtime = tvs.modtime;
3076 } else {
3078 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3080 if(file_utime(conn, fname, &tvs)!=0)
3081 return(UNIXERROR(ERRDOS,ERRnoaccess));
3085 /* check the mode isn't different, before changing it */
3086 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3088 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3090 if(file_chmod(conn, fname, dosmode, NULL)) {
3091 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
3092 return(UNIXERROR(ERRDOS,ERRnoaccess));
3096 if (size != get_file_size(sbuf)) {
3098 int ret;
3100 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3101 fname, (double)size ));
3103 if (fd == -1) {
3104 files_struct *new_fsp = NULL;
3105 int access_mode = 0;
3106 int action = 0;
3108 if(global_oplock_break) {
3109 /* Queue this file modify as we are the process of an oplock break. */
3111 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3112 DEBUGADD(2,( "in oplock break state.\n"));
3114 push_oplock_pending_smb_message(inbuf, length);
3115 return -1;
3118 new_fsp = open_file_shared(conn, fname, &sbuf,
3119 SET_OPEN_MODE(DOS_OPEN_RDWR),
3120 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3121 0, 0, &access_mode, &action);
3123 if (new_fsp == NULL)
3124 return(UNIXERROR(ERRDOS,ERRbadpath));
3125 ret = vfs_set_filelen(new_fsp, size);
3126 close_file(new_fsp,True);
3127 } else {
3128 ret = vfs_set_filelen(fsp, size);
3131 if (ret == -1)
3132 return (UNIXERROR(ERRHRD,ERRdiskfull));
3135 SSVAL(params,0,0);
3136 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3138 return(-1);
3141 /****************************************************************************
3142 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3143 ****************************************************************************/
3145 static int call_trans2mkdir(connection_struct *conn,
3146 char *inbuf, char *outbuf, int length, int bufsize,
3147 char **pparams, int total_params, char **ppdata, int total_data)
3149 char *params = *pparams;
3150 pstring directory;
3151 int ret = -1;
3152 SMB_STRUCT_STAT sbuf;
3153 BOOL bad_path = False;
3155 if (!CAN_WRITE(conn))
3156 return ERROR_DOS(ERRSRV,ERRaccess);
3158 if (total_params < 4)
3159 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3161 srvstr_pull(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE);
3163 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3165 unix_convert(directory,conn,0,&bad_path,&sbuf);
3166 if (check_name(directory,conn))
3167 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3169 if(ret < 0) {
3170 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3171 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
3174 /* Realloc the parameter and data sizes */
3175 params = Realloc(*pparams,2);
3176 if(params == NULL)
3177 return ERROR_DOS(ERRDOS,ERRnomem);
3178 *pparams = params;
3180 SSVAL(params,0,0);
3182 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3184 return(-1);
3187 /****************************************************************************
3188 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3189 We don't actually do this - we just send a null response.
3190 ****************************************************************************/
3192 static int call_trans2findnotifyfirst(connection_struct *conn,
3193 char *inbuf, char *outbuf, int length, int bufsize,
3194 char **pparams, int total_params, char **ppdata, int total_data)
3196 static uint16 fnf_handle = 257;
3197 char *params = *pparams;
3198 uint16 info_level;
3200 if (total_params < 6)
3201 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3203 info_level = SVAL(params,4);
3204 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3206 switch (info_level) {
3207 case 1:
3208 case 2:
3209 break;
3210 default:
3211 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3214 /* Realloc the parameter and data sizes */
3215 params = Realloc(*pparams,6);
3216 if(params == NULL)
3217 return ERROR_DOS(ERRDOS,ERRnomem);
3218 *pparams = params;
3220 SSVAL(params,0,fnf_handle);
3221 SSVAL(params,2,0); /* No changes */
3222 SSVAL(params,4,0); /* No EA errors */
3224 fnf_handle++;
3226 if(fnf_handle == 0)
3227 fnf_handle = 257;
3229 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3231 return(-1);
3234 /****************************************************************************
3235 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3236 changes). Currently this does nothing.
3237 ****************************************************************************/
3239 static int call_trans2findnotifynext(connection_struct *conn,
3240 char *inbuf, char *outbuf, int length, int bufsize,
3241 char **pparams, int total_params, char **ppdata, int total_data)
3243 char *params = *pparams;
3245 DEBUG(3,("call_trans2findnotifynext\n"));
3247 /* Realloc the parameter and data sizes */
3248 params = Realloc(*pparams,4);
3249 if(params == NULL)
3250 return ERROR_DOS(ERRDOS,ERRnomem);
3251 *pparams = params;
3253 SSVAL(params,0,0); /* No changes */
3254 SSVAL(params,2,0); /* No EA errors */
3256 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3258 return(-1);
3261 /****************************************************************************
3262 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3263 ****************************************************************************/
3265 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3266 char* outbuf, int length, int bufsize,
3267 char **pparams, int total_params, char **ppdata, int total_data)
3269 char *params = *pparams;
3270 pstring pathname;
3271 int reply_size = 0;
3272 int max_referral_level;
3274 DEBUG(10,("call_trans2getdfsreferral\n"));
3276 if (total_params < 2)
3277 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3279 max_referral_level = SVAL(params,0);
3281 if(!lp_host_msdfs())
3282 return ERROR_DOS(ERRDOS,ERRbadfunc);
3284 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
3286 if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
3287 return ERROR_DOS(ERRDOS,ERRbadfile);
3289 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3290 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3292 return(-1);
3295 #define LMCAT_SPL 0x53
3296 #define LMFUNC_GETJOBID 0x60
3298 /****************************************************************************
3299 Reply to a TRANS2_IOCTL - used for OS/2 printing.
3300 ****************************************************************************/
3302 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3303 char* outbuf, int length, int bufsize,
3304 char **pparams, int total_params, char **ppdata, int total_data)
3306 char *pdata = *ppdata;
3307 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3309 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3310 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3311 pdata = Realloc(*ppdata, 32);
3312 if(pdata == NULL)
3313 return ERROR_DOS(ERRDOS,ERRnomem);
3314 *ppdata = pdata;
3316 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3317 CAN ACCEPT THIS IN UNICODE. JRA. */
3319 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
3320 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3321 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3322 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3323 return(-1);
3324 } else {
3325 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3326 return ERROR_DOS(ERRSRV,ERRerror);
3330 /****************************************************************************
3331 Reply to a SMBfindclose (stop trans2 directory search).
3332 ****************************************************************************/
3334 int reply_findclose(connection_struct *conn,
3335 char *inbuf,char *outbuf,int length,int bufsize)
3337 int outsize = 0;
3338 int dptr_num=SVALS(inbuf,smb_vwv0);
3339 START_PROFILE(SMBfindclose);
3341 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3343 dptr_close(&dptr_num);
3345 outsize = set_message(outbuf,0,0,True);
3347 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3349 END_PROFILE(SMBfindclose);
3350 return(outsize);
3353 /****************************************************************************
3354 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3355 ****************************************************************************/
3357 int reply_findnclose(connection_struct *conn,
3358 char *inbuf,char *outbuf,int length,int bufsize)
3360 int outsize = 0;
3361 int dptr_num= -1;
3362 START_PROFILE(SMBfindnclose);
3364 dptr_num = SVAL(inbuf,smb_vwv0);
3366 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3368 /* We never give out valid handles for a
3369 findnotifyfirst - so any dptr_num is ok here.
3370 Just ignore it. */
3372 outsize = set_message(outbuf,0,0,True);
3374 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3376 END_PROFILE(SMBfindnclose);
3377 return(outsize);
3380 /****************************************************************************
3381 Reply to a SMBtranss2 - just ignore it!
3382 ****************************************************************************/
3384 int reply_transs2(connection_struct *conn,
3385 char *inbuf,char *outbuf,int length,int bufsize)
3387 START_PROFILE(SMBtranss2);
3388 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3389 END_PROFILE(SMBtranss2);
3390 return(-1);
3393 /****************************************************************************
3394 Reply to a SMBtrans2.
3395 ****************************************************************************/
3397 int reply_trans2(connection_struct *conn,
3398 char *inbuf,char *outbuf,int length,int bufsize)
3400 int outsize = 0;
3401 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3402 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3403 #if 0
3404 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3405 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3406 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3407 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3408 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3409 int32 timeout = IVALS(inbuf,smb_timeout);
3410 #endif
3411 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3412 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3413 char *params = NULL, *data = NULL;
3414 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
3415 START_PROFILE(SMBtrans2);
3417 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3418 /* Queue this open message as we are the process of an
3419 * oplock break. */
3421 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3422 DEBUGADD(2,( "in oplock break state.\n"));
3424 push_oplock_pending_smb_message(inbuf, length);
3425 END_PROFILE(SMBtrans2);
3426 return -1;
3429 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3430 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3431 END_PROFILE(SMBtrans2);
3432 return ERROR_DOS(ERRSRV,ERRaccess);
3435 outsize = set_message(outbuf,0,0,True);
3437 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3438 is so as a sanity check */
3439 if (suwcnt != 1) {
3441 * Need to have rc=0 for ioctl to get job id for OS/2.
3442 * Network printing will fail if function is not successful.
3443 * Similar function in reply.c will be used if protocol
3444 * is LANMAN1.0 instead of LM1.2X002.
3445 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3446 * outbuf doesn't have to be set(only job id is used).
3448 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3449 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3450 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3451 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3452 } else {
3453 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
3454 DEBUG(2,("Transaction is %d\n",tran_call));
3455 END_PROFILE(SMBtrans2);
3456 ERROR_DOS(ERRDOS,ERRinvalidparam);
3460 /* Allocate the space for the maximum needed parameters and data */
3461 if (total_params > 0)
3462 params = (char *)malloc(total_params);
3463 if (total_data > 0)
3464 data = (char *)malloc(total_data);
3466 if ((total_params && !params) || (total_data && !data)) {
3467 DEBUG(2,("Out of memory in reply_trans2\n"));
3468 SAFE_FREE(params);
3469 SAFE_FREE(data);
3470 END_PROFILE(SMBtrans2);
3471 return ERROR_DOS(ERRDOS,ERRnomem);
3474 /* Copy the param and data bytes sent with this request into
3475 the params buffer */
3476 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3477 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3479 if (num_params > total_params || num_data > total_data)
3480 exit_server("invalid params in reply_trans2");
3482 if(params) {
3483 unsigned int psoff = SVAL(inbuf, smb_psoff);
3484 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
3485 goto bad_param;
3486 if (smb_base(inbuf) + psoff + num_params > inbuf + length)
3487 goto bad_param;
3488 memcpy( params, smb_base(inbuf) + psoff, num_params);
3490 if(data) {
3491 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
3492 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
3493 goto bad_param;
3494 if (smb_base(inbuf) + dsoff + num_data > inbuf + length)
3495 goto bad_param;
3496 memcpy( data, smb_base(inbuf) + dsoff, num_data);
3499 srv_signing_trans_start(SVAL(inbuf,smb_mid));
3501 if(num_data_sofar < total_data || num_params_sofar < total_params) {
3502 /* We need to send an interim response then receive the rest
3503 of the parameter/data bytes */
3504 outsize = set_message(outbuf,0,0,True);
3505 if (!send_smb(smbd_server_fd(),outbuf))
3506 exit_server("reply_trans2: send_smb failed.");
3508 while (num_data_sofar < total_data ||
3509 num_params_sofar < total_params) {
3510 BOOL ret;
3511 unsigned int param_disp;
3512 unsigned int param_off;
3513 unsigned int data_disp;
3514 unsigned int data_off;
3516 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3518 if ((ret &&
3519 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3520 outsize = set_message(outbuf,0,0,True);
3521 if(ret)
3522 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3523 else
3524 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3525 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3526 goto bad_param;
3529 /* Revise total_params and total_data in case
3530 they have changed downwards */
3531 if (SVAL(inbuf, smb_tpscnt) < total_params)
3532 total_params = SVAL(inbuf, smb_tpscnt);
3533 if (SVAL(inbuf, smb_tdscnt) < total_data)
3534 total_data = SVAL(inbuf, smb_tdscnt);
3536 num_params = SVAL(inbuf,smb_spscnt);
3537 param_off = SVAL(inbuf, smb_spsoff);
3538 param_disp = SVAL(inbuf, smb_spsdisp);
3539 num_params_sofar += num_params;
3541 num_data = SVAL(inbuf, smb_sdscnt);
3542 data_off = SVAL(inbuf, smb_sdsoff);
3543 data_disp = SVAL(inbuf, smb_sdsdisp);
3544 num_data_sofar += num_data;
3546 if (num_params_sofar > total_params || num_data_sofar > total_data)
3547 goto bad_param;
3549 if (num_params) {
3550 if (param_disp + num_params >= total_params)
3551 goto bad_param;
3552 if ((param_disp + num_params < param_disp) ||
3553 (param_disp + num_params < num_params))
3554 goto bad_param;
3555 if (smb_base(inbuf) + param_off + num_params >= inbuf + bufsize)
3556 goto bad_param;
3557 if (params + param_disp < params)
3558 goto bad_param;
3560 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
3562 if (num_data) {
3563 if (data_disp + num_data >= total_data)
3564 goto bad_param;
3565 if ((data_disp + num_data < data_disp) ||
3566 (data_disp + num_data < num_data))
3567 goto bad_param;
3568 if (smb_base(inbuf) + data_off + num_data >= inbuf + bufsize)
3569 goto bad_param;
3570 if (data + data_disp < data)
3571 goto bad_param;
3573 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
3578 if (Protocol >= PROTOCOL_NT1) {
3579 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
3582 /* Now we must call the relevant TRANS2 function */
3583 switch(tran_call) {
3584 case TRANSACT2_OPEN:
3585 START_PROFILE_NESTED(Trans2_open);
3586 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
3587 &params, total_params, &data, total_data);
3588 END_PROFILE_NESTED(Trans2_open);
3589 break;
3591 case TRANSACT2_FINDFIRST:
3592 START_PROFILE_NESTED(Trans2_findfirst);
3593 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3594 &params, total_params, &data, total_data);
3595 END_PROFILE_NESTED(Trans2_findfirst);
3596 break;
3598 case TRANSACT2_FINDNEXT:
3599 START_PROFILE_NESTED(Trans2_findnext);
3600 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
3601 &params, total_params, &data, total_data);
3602 END_PROFILE_NESTED(Trans2_findnext);
3603 break;
3605 case TRANSACT2_QFSINFO:
3606 START_PROFILE_NESTED(Trans2_qfsinfo);
3607 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3608 &params, total_params, &data, total_data);
3609 END_PROFILE_NESTED(Trans2_qfsinfo);
3610 break;
3612 #ifdef HAVE_SYS_QUOTAS
3613 case TRANSACT2_SETFSINFO:
3614 START_PROFILE_NESTED(Trans2_setfsinfo);
3615 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
3616 &params, total_params, &data, total_data);
3617 END_PROFILE_NESTED(Trans2_setfsinfo);
3618 break;
3619 #endif
3620 case TRANSACT2_QPATHINFO:
3621 case TRANSACT2_QFILEINFO:
3622 START_PROFILE_NESTED(Trans2_qpathinfo);
3623 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3624 &params, total_params, &data, total_data);
3625 END_PROFILE_NESTED(Trans2_qpathinfo);
3626 break;
3627 case TRANSACT2_SETPATHINFO:
3628 case TRANSACT2_SETFILEINFO:
3629 START_PROFILE_NESTED(Trans2_setpathinfo);
3630 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3631 &params, total_params, &data, total_data);
3632 END_PROFILE_NESTED(Trans2_setpathinfo);
3633 break;
3635 case TRANSACT2_FINDNOTIFYFIRST:
3636 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3637 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
3638 &params, total_params, &data, total_data);
3639 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3640 break;
3642 case TRANSACT2_FINDNOTIFYNEXT:
3643 START_PROFILE_NESTED(Trans2_findnotifynext);
3644 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
3645 &params, total_params, &data, total_data);
3646 END_PROFILE_NESTED(Trans2_findnotifynext);
3647 break;
3648 case TRANSACT2_MKDIR:
3649 START_PROFILE_NESTED(Trans2_mkdir);
3650 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3651 &params, total_params, &data, total_data);
3652 END_PROFILE_NESTED(Trans2_mkdir);
3653 break;
3655 case TRANSACT2_GET_DFS_REFERRAL:
3656 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3657 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3658 &params, total_params, &data, total_data);
3659 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3660 break;
3661 case TRANSACT2_IOCTL:
3662 START_PROFILE_NESTED(Trans2_ioctl);
3663 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3664 &params, total_params, &data, total_data);
3665 END_PROFILE_NESTED(Trans2_ioctl);
3666 break;
3667 default:
3668 /* Error in request */
3669 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3670 SAFE_FREE(params);
3671 SAFE_FREE(data);
3672 END_PROFILE(SMBtrans2);
3673 srv_signing_trans_stop();
3674 return ERROR_DOS(ERRSRV,ERRerror);
3677 /* As we do not know how many data packets will need to be
3678 returned here the various call_trans2xxxx calls
3679 must send their own. Thus a call_trans2xxx routine only
3680 returns a value other than -1 when it wants to send
3681 an error packet.
3684 srv_signing_trans_stop();
3686 SAFE_FREE(params);
3687 SAFE_FREE(data);
3688 END_PROFILE(SMBtrans2);
3689 return outsize; /* If a correct response was needed the
3690 call_trans2xxx calls have already sent
3691 it. If outsize != -1 then it is returning */
3693 bad_param:
3695 srv_signing_trans_stop();
3696 SAFE_FREE(params);
3697 SAFE_FREE(data);
3698 END_PROFILE(SMBtrans2);
3699 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);