A fix to allow configure to find iconv on a number of systems including those
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blob56d1aae3a2a562fac4804f44f7c2cd2f7e8d6c20
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,block_size,sectors_per_unit,bytes_per_sector;
1411 data_len = 18;
1412 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1413 block_size = lp_block_size(snum);
1414 if (bsize < block_size) {
1415 SMB_BIG_UINT factor = block_size/bsize;
1416 bsize = block_size;
1417 dsize /= factor;
1418 dfree /= factor;
1420 if (bsize > block_size) {
1421 SMB_BIG_UINT factor = bsize/block_size;
1422 bsize = block_size;
1423 dsize *= factor;
1424 dfree *= factor;
1426 bytes_per_sector = 512;
1427 sectors_per_unit = bsize/bytes_per_sector;
1429 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1430 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1431 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1433 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1434 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1435 SIVAL(pdata,l1_cUnit,dsize);
1436 SIVAL(pdata,l1_cUnitAvail,dfree);
1437 SSVAL(pdata,l1_cbSector,bytes_per_sector);
1438 break;
1441 case SMB_INFO_VOLUME:
1442 /* Return volume name */
1444 * Add volume serial number - hash of a combination of
1445 * the called hostname and the service name.
1447 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1448 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1449 SCVAL(pdata,l2_vol_cch,len);
1450 data_len = l2_vol_szVolLabel + len;
1451 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1452 (unsigned)st.st_ctime, len, vname));
1453 break;
1455 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1456 case SMB_FS_ATTRIBUTE_INFORMATION:
1459 #if defined(HAVE_SYS_QUOTAS)
1460 quota_flag = FILE_VOLUME_QUOTAS;
1461 #endif
1463 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1464 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1465 quota_flag); /* FS ATTRIBUTES */
1467 SIVAL(pdata,4,255); /* Max filename component length */
1468 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1469 and will think we can't do long filenames */
1470 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1471 SIVAL(pdata,8,len);
1472 data_len = 12 + len;
1473 break;
1475 case SMB_QUERY_FS_LABEL_INFO:
1476 case SMB_FS_LABEL_INFORMATION:
1477 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1478 data_len = 4 + len;
1479 SIVAL(pdata,0,len);
1480 break;
1482 case SMB_QUERY_FS_VOLUME_INFO:
1483 case SMB_FS_VOLUME_INFORMATION:
1486 * Add volume serial number - hash of a combination of
1487 * the called hostname and the service name.
1489 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1490 (str_checksum(local_machine)<<16));
1492 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1493 SIVAL(pdata,12,len);
1494 data_len = 18+len;
1495 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1496 (int)strlen(vname),vname, lp_servicename(snum)));
1497 break;
1499 case SMB_QUERY_FS_SIZE_INFO:
1500 case SMB_FS_SIZE_INFORMATION:
1502 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1503 data_len = 24;
1504 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1505 block_size = lp_block_size(snum);
1506 if (bsize < block_size) {
1507 SMB_BIG_UINT factor = block_size/bsize;
1508 bsize = block_size;
1509 dsize /= factor;
1510 dfree /= factor;
1512 if (bsize > block_size) {
1513 SMB_BIG_UINT factor = bsize/block_size;
1514 bsize = block_size;
1515 dsize *= factor;
1516 dfree *= factor;
1518 bytes_per_sector = 512;
1519 sectors_per_unit = bsize/bytes_per_sector;
1520 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1521 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1522 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1523 SBIG_UINT(pdata,0,dsize);
1524 SBIG_UINT(pdata,8,dfree);
1525 SIVAL(pdata,16,sectors_per_unit);
1526 SIVAL(pdata,20,bytes_per_sector);
1527 break;
1530 case SMB_FS_FULL_SIZE_INFORMATION:
1532 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1533 data_len = 32;
1534 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1535 block_size = lp_block_size(snum);
1536 if (bsize < block_size) {
1537 SMB_BIG_UINT factor = block_size/bsize;
1538 bsize = block_size;
1539 dsize /= factor;
1540 dfree /= factor;
1542 if (bsize > block_size) {
1543 SMB_BIG_UINT factor = bsize/block_size;
1544 bsize = block_size;
1545 dsize *= factor;
1546 dfree *= factor;
1548 bytes_per_sector = 512;
1549 sectors_per_unit = bsize/bytes_per_sector;
1550 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1551 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1552 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1553 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1554 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1555 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1556 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1557 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1558 break;
1561 case SMB_QUERY_FS_DEVICE_INFO:
1562 case SMB_FS_DEVICE_INFORMATION:
1563 data_len = 8;
1564 SIVAL(pdata,0,0); /* dev type */
1565 SIVAL(pdata,4,0); /* characteristics */
1566 break;
1568 #ifdef HAVE_SYS_QUOTAS
1569 case SMB_FS_QUOTA_INFORMATION:
1571 * what we have to send --metze:
1573 * Unknown1: 24 NULL bytes
1574 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1575 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
1576 * Quota Flags: 2 byte :
1577 * Unknown3: 6 NULL bytes
1579 * 48 bytes total
1581 * details for Quota Flags:
1583 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1584 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
1585 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1586 * 0x0001 Enable Quotas: enable quota for this fs
1590 /* we need to fake up a fsp here,
1591 * because its not send in this call
1593 files_struct fsp;
1594 SMB_NTQUOTA_STRUCT quotas;
1596 ZERO_STRUCT(fsp);
1597 ZERO_STRUCT(quotas);
1599 fsp.conn = conn;
1600 fsp.fnum = -1;
1601 fsp.fd = -1;
1603 /* access check */
1604 if (conn->admin_user != True) {
1605 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1606 lp_servicename(SNUM(conn)),conn->user));
1607 return ERROR_DOS(ERRDOS,ERRnoaccess);
1610 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
1611 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
1612 return ERROR_DOS(ERRSRV,ERRerror);
1615 data_len = 48;
1617 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
1619 /* Unknown1 24 NULL bytes*/
1620 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
1621 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
1622 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
1624 /* Default Soft Quota 8 bytes */
1625 SBIG_UINT(pdata,24,quotas.softlim);
1627 /* Default Hard Quota 8 bytes */
1628 SBIG_UINT(pdata,32,quotas.hardlim);
1630 /* Quota flag 2 bytes */
1631 SSVAL(pdata,40,quotas.qflags);
1633 /* Unknown3 6 NULL bytes */
1634 SSVAL(pdata,42,0);
1635 SIVAL(pdata,44,0);
1637 break;
1639 #endif /* HAVE_SYS_QUOTAS */
1640 case SMB_FS_OBJECTID_INFORMATION:
1641 data_len = 64;
1642 break;
1645 * Query the version and capabilities of the CIFS UNIX extensions
1646 * in use.
1649 case SMB_QUERY_CIFS_UNIX_INFO:
1650 if (!lp_unix_extensions())
1651 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1652 data_len = 12;
1653 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
1654 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
1655 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
1656 break;
1658 case SMB_MAC_QUERY_FS_INFO:
1660 * Thursby MAC extension... ONLY on NTFS filesystems
1661 * once we do streams then we don't need this
1663 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1664 data_len = 88;
1665 SIVAL(pdata,84,0x100); /* Don't support mac... */
1666 break;
1668 /* drop through */
1669 default:
1670 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1674 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1676 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1678 return -1;
1681 #ifdef HAVE_SYS_QUOTAS
1682 /****************************************************************************
1683 Reply to a TRANS2_SETFSINFO (set filesystem info).
1684 ****************************************************************************/
1686 static int call_trans2setfsinfo(connection_struct *conn,
1687 char *inbuf, char *outbuf, int length, int bufsize,
1688 char **pparams, int total_params, char **ppdata, int total_data)
1690 char *pdata = *ppdata;
1691 char *params = *pparams;
1692 files_struct *fsp = NULL;
1693 uint16 info_level;
1694 int outsize;
1695 SMB_NTQUOTA_STRUCT quotas;
1697 ZERO_STRUCT(quotas);
1699 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
1701 /* access check */
1702 if ((conn->admin_user != True)||!CAN_WRITE(conn)) {
1703 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1704 lp_servicename(SNUM(conn)),conn->user));
1705 return ERROR_DOS(ERRSRV,ERRaccess);
1708 /* */
1709 if (total_params < 4) {
1710 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
1711 total_params));
1712 return ERROR_DOS(ERRDOS,ERRinvalidparam);
1715 fsp = file_fsp(params,0);
1717 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
1718 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
1719 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
1722 info_level = SVAL(params,2);
1724 switch(info_level) {
1725 case SMB_FS_QUOTA_INFORMATION:
1726 /* note: normaly there're 48 bytes,
1727 * but we didn't use the last 6 bytes for now
1728 * --metze
1730 if (total_data < 42) {
1731 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
1732 total_data));
1733 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1736 /* unknown_1 24 NULL bytes in pdata*/
1738 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
1739 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
1740 #ifdef LARGE_SMB_OFF_T
1741 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
1742 #else /* LARGE_SMB_OFF_T */
1743 if ((IVAL(pdata,28) != 0)&&
1744 ((quotas.softlim != 0xFFFFFFFF)||
1745 (IVAL(pdata,28)!=0xFFFFFFFF))) {
1746 /* more than 32 bits? */
1747 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1749 #endif /* LARGE_SMB_OFF_T */
1751 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
1752 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
1753 #ifdef LARGE_SMB_OFF_T
1754 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
1755 #else /* LARGE_SMB_OFF_T */
1756 if ((IVAL(pdata,36) != 0)&&
1757 ((quotas.hardlim != 0xFFFFFFFF)||
1758 (IVAL(pdata,36)!=0xFFFFFFFF))) {
1759 /* more than 32 bits? */
1760 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1762 #endif /* LARGE_SMB_OFF_T */
1764 /* quota_flags 2 bytes **/
1765 quotas.qflags = SVAL(pdata,40);
1767 /* unknown_2 6 NULL bytes follow*/
1769 /* now set the quotas */
1770 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
1771 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
1772 return ERROR_DOS(ERRSRV,ERRerror);
1775 break;
1776 default:
1777 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
1778 info_level));
1779 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1780 break;
1784 * sending this reply works fine,
1785 * but I'm not sure it's the same
1786 * like windows do...
1787 * --metze
1789 outsize = set_message(outbuf,10,0,True);
1791 return outsize;
1793 #endif /* HAVE_SYS_QUOTAS */
1795 /****************************************************************************
1796 * Utility function to set bad path error.
1797 ****************************************************************************/
1799 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
1801 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
1802 err, (int)bad_path ));
1804 if(err == ENOENT) {
1805 if (bad_path) {
1806 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1807 } else {
1808 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
1811 return UNIXERROR(def_class,def_code);
1814 /****************************************************************************
1815 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1816 file name or file id).
1817 ****************************************************************************/
1819 static int call_trans2qfilepathinfo(connection_struct *conn,
1820 char *inbuf, char *outbuf, int length,
1821 int bufsize,
1822 char **pparams, int total_params, char **ppdata, int total_data)
1824 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1825 char *params = *pparams;
1826 char *pdata = *ppdata;
1827 uint16 tran_call = SVAL(inbuf, smb_setup0);
1828 uint16 info_level;
1829 int mode=0;
1830 SMB_OFF_T file_size=0;
1831 SMB_BIG_UINT allocation_size=0;
1832 unsigned int data_size;
1833 SMB_STRUCT_STAT sbuf;
1834 pstring fname, dos_fname;
1835 char *fullpathname;
1836 char *base_name;
1837 char *p;
1838 SMB_OFF_T pos = 0;
1839 BOOL bad_path = False;
1840 BOOL delete_pending = False;
1841 int len;
1842 time_t c_time;
1843 files_struct *fsp = NULL;
1845 if (!params)
1846 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1848 if (tran_call == TRANSACT2_QFILEINFO) {
1849 if (total_params < 4)
1850 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1852 fsp = file_fsp(params,0);
1853 info_level = SVAL(params,2);
1855 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1857 if(fsp && (fsp->fake_file_handle)) {
1859 * This is actually for the QUOTA_FAKE_FILE --metze
1862 pstrcpy(fname, fsp->fsp_name);
1863 unix_convert(fname,conn,0,&bad_path,&sbuf);
1864 if (!check_name(fname,conn)) {
1865 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno)));
1866 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1869 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1871 * This is actually a QFILEINFO on a directory
1872 * handle (returned from an NT SMB). NT5.0 seems
1873 * to do this call. JRA.
1875 pstrcpy(fname, fsp->fsp_name);
1876 unix_convert(fname,conn,0,&bad_path,&sbuf);
1877 if (!check_name(fname,conn)) {
1878 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1879 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1882 if (INFO_LEVEL_IS_UNIX(info_level)) {
1883 /* Always do lstat for UNIX calls. */
1884 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
1885 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
1886 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1888 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
1889 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
1890 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1893 delete_pending = fsp->directory_delete_on_close;
1894 } else {
1896 * Original code - this is an open file.
1898 CHECK_FSP(fsp,conn);
1900 pstrcpy(fname, fsp->fsp_name);
1901 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
1902 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
1903 return(UNIXERROR(ERRDOS,ERRbadfid));
1905 pos = fsp->position_information;
1906 delete_pending = fsp->delete_on_close;
1908 } else {
1909 /* qpathinfo */
1910 if (total_params < 6)
1911 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1913 info_level = SVAL(params,0);
1915 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1917 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
1919 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1921 unix_convert(fname,conn,0,&bad_path,&sbuf);
1922 if (!check_name(fname,conn)) {
1923 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1924 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1927 if (INFO_LEVEL_IS_UNIX(info_level)) {
1928 /* Always do lstat for UNIX calls. */
1929 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
1930 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
1931 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1933 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
1934 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
1935 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1939 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
1940 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1942 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
1943 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
1945 p = strrchr_m(fname,'/');
1946 if (!p)
1947 base_name = fname;
1948 else
1949 base_name = p+1;
1951 mode = dos_mode(conn,fname,&sbuf);
1952 if (!mode)
1953 mode = FILE_ATTRIBUTE_NORMAL;
1955 fullpathname = fname;
1956 file_size = get_file_size(sbuf);
1957 allocation_size = get_allocation_size(fsp,&sbuf);
1958 if (mode & aDIR)
1959 file_size = 0;
1961 params = Realloc(*pparams,2);
1962 if (params == NULL)
1963 return ERROR_DOS(ERRDOS,ERRnomem);
1964 *pparams = params;
1965 memset((char *)params,'\0',2);
1966 data_size = max_data_bytes + 1024;
1967 pdata = Realloc(*ppdata, data_size);
1968 if ( pdata == NULL )
1969 return ERROR_DOS(ERRDOS,ERRnomem);
1970 *ppdata = pdata;
1972 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1973 /* uggh, EAs for OS2 */
1974 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1975 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1978 memset((char *)pdata,'\0',data_size);
1980 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1982 if (lp_dos_filetime_resolution(SNUM(conn))) {
1983 c_time &= ~1;
1984 sbuf.st_atime &= ~1;
1985 sbuf.st_mtime &= ~1;
1986 sbuf.st_mtime &= ~1;
1989 /* NT expects the name to be in an exact form of the *full*
1990 filename. See the trans2 torture test */
1991 if (strequal(base_name,".")) {
1992 pstrcpy(dos_fname, "\\");
1993 } else {
1994 pstr_sprintf(dos_fname, "\\%s", fname);
1995 string_replace(dos_fname, '/', '\\');
1998 switch (info_level) {
1999 case SMB_INFO_STANDARD:
2000 case SMB_INFO_QUERY_EA_SIZE:
2001 data_size = (info_level==1?22:26);
2002 put_dos_date2(pdata,l1_fdateCreation,c_time);
2003 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2004 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2005 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2006 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2007 SSVAL(pdata,l1_attrFile,mode);
2008 SIVAL(pdata,l1_attrFile+2,0); /* this is what win2003 does */
2009 break;
2011 case SMB_INFO_IS_NAME_VALID:
2012 if (tran_call == TRANSACT2_QFILEINFO) {
2013 /* os/2 needs this ? really ?*/
2014 return ERROR_DOS(ERRDOS,ERRbadfunc);
2016 data_size = 0;
2017 break;
2019 case SMB_INFO_QUERY_EAS_FROM_LIST:
2020 data_size = 24;
2021 put_dos_date2(pdata,0,c_time);
2022 put_dos_date2(pdata,4,sbuf.st_atime);
2023 put_dos_date2(pdata,8,sbuf.st_mtime);
2024 SIVAL(pdata,12,(uint32)file_size);
2025 SIVAL(pdata,16,(uint32)allocation_size);
2026 SIVAL(pdata,20,mode);
2027 break;
2029 case SMB_INFO_QUERY_ALL_EAS:
2030 data_size = 4;
2031 SIVAL(pdata,0,0); /* ea size */
2032 break;
2034 case SMB_FILE_BASIC_INFORMATION:
2035 case SMB_QUERY_FILE_BASIC_INFO:
2037 if (info_level == SMB_QUERY_FILE_BASIC_INFO)
2038 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2039 else {
2040 data_size = 40;
2041 SIVAL(pdata,36,0);
2043 put_long_date(pdata,c_time);
2044 put_long_date(pdata+8,sbuf.st_atime);
2045 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2046 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2047 SIVAL(pdata,32,mode);
2049 DEBUG(5,("SMB_QFBI - "));
2051 time_t create_time = c_time;
2052 DEBUG(5,("create: %s ", ctime(&create_time)));
2054 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2055 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2056 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2057 DEBUG(5,("mode: %x\n", mode));
2059 break;
2061 case SMB_FILE_STANDARD_INFORMATION:
2062 case SMB_QUERY_FILE_STANDARD_INFO:
2064 data_size = 24;
2065 SOFF_T(pdata,0,allocation_size);
2066 SOFF_T(pdata,8,file_size);
2067 if (delete_pending & sbuf.st_nlink)
2068 SIVAL(pdata,16,sbuf.st_nlink - 1);
2069 else
2070 SIVAL(pdata,16,sbuf.st_nlink);
2071 SCVAL(pdata,20,0);
2072 SCVAL(pdata,21,(mode&aDIR)?1:0);
2073 break;
2075 case SMB_FILE_EA_INFORMATION:
2076 case SMB_QUERY_FILE_EA_INFO:
2077 data_size = 4;
2078 break;
2080 /* Get the 8.3 name - used if NT SMB was negotiated. */
2081 case SMB_QUERY_FILE_ALT_NAME_INFO:
2082 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2084 pstring short_name;
2086 pstrcpy(short_name,base_name);
2087 /* Mangle if not already 8.3 */
2088 if(!mangle_is_8_3(short_name, True)) {
2089 mangle_map(short_name,True,True,SNUM(conn));
2091 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2092 data_size = 4 + len;
2093 SIVAL(pdata,0,len);
2094 break;
2097 case SMB_QUERY_FILE_NAME_INFO:
2099 this must be *exactly* right for ACLs on mapped drives to work
2101 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2102 data_size = 4 + len;
2103 SIVAL(pdata,0,len);
2104 break;
2106 case SMB_FILE_ALLOCATION_INFORMATION:
2107 case SMB_QUERY_FILE_ALLOCATION_INFO:
2108 data_size = 8;
2109 SOFF_T(pdata,0,allocation_size);
2110 break;
2112 case SMB_FILE_END_OF_FILE_INFORMATION:
2113 case SMB_QUERY_FILE_END_OF_FILEINFO:
2114 data_size = 8;
2115 SOFF_T(pdata,0,file_size);
2116 break;
2118 case SMB_QUERY_FILE_ALL_INFO:
2119 case SMB_FILE_ALL_INFORMATION:
2120 put_long_date(pdata,c_time);
2121 put_long_date(pdata+8,sbuf.st_atime);
2122 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2123 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2124 SIVAL(pdata,32,mode);
2125 pdata += 40;
2126 SOFF_T(pdata,0,allocation_size);
2127 SOFF_T(pdata,8,file_size);
2128 if (delete_pending && sbuf.st_nlink)
2129 SIVAL(pdata,16,sbuf.st_nlink - 1);
2130 else
2131 SIVAL(pdata,16,sbuf.st_nlink);
2132 SCVAL(pdata,20,delete_pending);
2133 SCVAL(pdata,21,(mode&aDIR)?1:0);
2134 pdata += 24;
2135 pdata += 4; /* EA info */
2136 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2137 SIVAL(pdata,0,len);
2138 pdata += 4 + len;
2139 data_size = PTR_DIFF(pdata,(*ppdata));
2140 break;
2142 case SMB_FILE_INTERNAL_INFORMATION:
2143 /* This should be an index number - looks like
2144 dev/ino to me :-)
2146 I think this causes us to fail the IFSKIT
2147 BasicFileInformationTest. -tpot */
2149 SIVAL(pdata,0,sbuf.st_dev);
2150 SIVAL(pdata,4,sbuf.st_ino);
2151 data_size = 8;
2152 break;
2154 case SMB_FILE_ACCESS_INFORMATION:
2155 SIVAL(pdata,0,0x12019F); /* ??? */
2156 data_size = 4;
2157 break;
2159 case SMB_FILE_NAME_INFORMATION:
2160 /* Pathname with leading '\'. */
2162 size_t byte_len;
2163 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2164 SIVAL(pdata,0,byte_len);
2165 data_size = 4 + byte_len;
2166 break;
2169 case SMB_FILE_DISPOSITION_INFORMATION:
2170 data_size = 1;
2171 SCVAL(pdata,0,delete_pending);
2172 break;
2174 case SMB_FILE_POSITION_INFORMATION:
2175 data_size = 8;
2176 SOFF_T(pdata,0,pos);
2177 break;
2179 case SMB_FILE_MODE_INFORMATION:
2180 SIVAL(pdata,0,mode);
2181 data_size = 4;
2182 break;
2184 case SMB_FILE_ALIGNMENT_INFORMATION:
2185 SIVAL(pdata,0,0); /* No alignment needed. */
2186 data_size = 4;
2187 break;
2189 #if 0
2191 * NT4 server just returns "invalid query" to this - if we try to answer
2192 * it then NTws gets a BSOD! (tridge).
2193 * W2K seems to want this. JRA.
2195 case SMB_QUERY_FILE_STREAM_INFO:
2196 #endif
2197 case SMB_FILE_STREAM_INFORMATION:
2198 if (mode & aDIR) {
2199 data_size = 0;
2200 } else {
2201 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2202 SIVAL(pdata,0,0); /* ??? */
2203 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2204 SOFF_T(pdata,8,file_size);
2205 SIVAL(pdata,16,allocation_size);
2206 SIVAL(pdata,20,0); /* ??? */
2207 data_size = 24 + byte_len;
2209 break;
2211 case SMB_QUERY_COMPRESSION_INFO:
2212 case SMB_FILE_COMPRESSION_INFORMATION:
2213 SOFF_T(pdata,0,file_size);
2214 SIVAL(pdata,8,0); /* ??? */
2215 SIVAL(pdata,12,0); /* ??? */
2216 data_size = 16;
2217 break;
2219 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2220 put_long_date(pdata,c_time);
2221 put_long_date(pdata+8,sbuf.st_atime);
2222 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2223 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2224 SIVAL(pdata,32,allocation_size);
2225 SOFF_T(pdata,40,file_size);
2226 SIVAL(pdata,48,mode);
2227 SIVAL(pdata,52,0); /* ??? */
2228 data_size = 56;
2229 break;
2231 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2232 SIVAL(pdata,0,mode);
2233 SIVAL(pdata,4,0);
2234 data_size = 8;
2235 break;
2238 * CIFS UNIX Extensions.
2241 case SMB_QUERY_FILE_UNIX_BASIC:
2243 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2245 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2246 pdata += 8;
2248 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2249 pdata += 8;
2251 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2252 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2253 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2254 pdata += 24;
2256 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2257 SIVAL(pdata,4,0);
2258 pdata += 8;
2260 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2261 SIVAL(pdata,4,0);
2262 pdata += 8;
2264 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2265 pdata += 4;
2267 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2268 SIVAL(pdata,4,0);
2269 pdata += 8;
2271 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2272 SIVAL(pdata,4,0);
2273 pdata += 8;
2275 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2276 pdata += 8;
2278 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2279 SIVAL(pdata,4,0);
2280 pdata += 8;
2282 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2283 SIVAL(pdata,4,0);
2284 pdata += 8+1;
2285 data_size = PTR_DIFF(pdata,(*ppdata));
2288 int i;
2289 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2291 for (i=0; i<100; i++)
2292 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2293 DEBUG(4,("\n"));
2296 break;
2298 case SMB_QUERY_FILE_UNIX_LINK:
2300 pstring buffer;
2302 #ifdef S_ISLNK
2303 if(!S_ISLNK(sbuf.st_mode))
2304 return(UNIXERROR(ERRSRV,ERRbadlink));
2305 #else
2306 return(UNIXERROR(ERRDOS,ERRbadlink));
2307 #endif
2308 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2309 if (len == -1)
2310 return(UNIXERROR(ERRDOS,ERRnoaccess));
2311 buffer[len] = 0;
2312 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2313 pdata += len;
2314 data_size = PTR_DIFF(pdata,(*ppdata));
2316 break;
2319 default:
2320 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2323 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size);
2325 return(-1);
2328 /****************************************************************************
2329 Deal with the internal needs of setting the delete on close flag. Note that
2330 as the tdb locking is recursive, it is safe to call this from within
2331 open_file_shared. JRA.
2332 ****************************************************************************/
2334 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2337 * Only allow delete on close for writable shares.
2340 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2341 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2342 fsp->fsp_name ));
2343 return NT_STATUS_ACCESS_DENIED;
2346 * Only allow delete on close for files/directories opened with delete intent.
2349 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2350 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2351 fsp->fsp_name ));
2352 return NT_STATUS_ACCESS_DENIED;
2355 if(fsp->is_directory) {
2356 fsp->directory_delete_on_close = delete_on_close;
2357 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2358 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2359 } else {
2360 fsp->delete_on_close = delete_on_close;
2361 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2362 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2365 return NT_STATUS_OK;
2368 /****************************************************************************
2369 Sets the delete on close flag over all share modes on this file.
2370 Modify the share mode entry for all files open
2371 on this device and inode to tell other smbds we have
2372 changed the delete on close flag. This will be noticed
2373 in the close code, the last closer will delete the file
2374 if flag is set.
2375 ****************************************************************************/
2377 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2379 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2380 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2382 if (fsp->is_directory || fsp->is_stat)
2383 return NT_STATUS_OK;
2385 if (lock_share_entry_fsp(fsp) == False)
2386 return NT_STATUS_ACCESS_DENIED;
2388 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2389 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2390 fsp->fsp_name ));
2391 unlock_share_entry_fsp(fsp);
2392 return NT_STATUS_ACCESS_DENIED;
2395 unlock_share_entry_fsp(fsp);
2396 return NT_STATUS_OK;
2399 /****************************************************************************
2400 Returns true if this pathname is within the share, and thus safe.
2401 ****************************************************************************/
2403 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2405 #ifdef PATH_MAX
2406 char resolved_name[PATH_MAX+1];
2407 #else
2408 pstring resolved_name;
2409 #endif
2410 fstring last_component;
2411 pstring link_dest;
2412 pstring link_test;
2413 char *p;
2414 BOOL bad_path = False;
2415 SMB_STRUCT_STAT sbuf;
2417 pstrcpy(link_dest, link_dest_in);
2418 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2420 /* Store the UNIX converted path. */
2421 pstrcpy(link_dest_out, link_dest);
2423 p = strrchr(link_dest, '/');
2424 if (p) {
2425 fstrcpy(last_component, p+1);
2426 *p = '\0';
2427 } else {
2428 fstrcpy(last_component, link_dest);
2429 pstrcpy(link_dest, "./");
2432 if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL)
2433 return -1;
2435 pstrcpy(link_dest, resolved_name);
2436 pstrcat(link_dest, "/");
2437 pstrcat(link_dest, last_component);
2439 if (*link_dest != '/') {
2440 /* Relative path. */
2441 pstrcpy(link_test, conn->connectpath);
2442 pstrcat(link_test, "/");
2443 pstrcat(link_test, link_dest);
2444 } else {
2445 pstrcpy(link_test, link_dest);
2449 * Check if the link is within the share.
2452 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2453 errno = EACCES;
2454 return -1;
2456 return 0;
2459 /****************************************************************************
2460 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2461 ****************************************************************************/
2463 static int call_trans2setfilepathinfo(connection_struct *conn,
2464 char *inbuf, char *outbuf, int length, int bufsize,
2465 char **pparams, int total_params, char **ppdata, int total_data)
2467 char *params = *pparams;
2468 char *pdata = *ppdata;
2469 uint16 tran_call = SVAL(inbuf, smb_setup0);
2470 uint16 info_level;
2471 int dosmode=0;
2472 SMB_OFF_T size=0;
2473 struct utimbuf tvs;
2474 SMB_STRUCT_STAT sbuf;
2475 pstring fname;
2476 int fd = -1;
2477 BOOL bad_path = False;
2478 files_struct *fsp = NULL;
2479 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2480 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2481 mode_t unixmode = 0;
2483 if (!params)
2484 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2486 if (tran_call == TRANSACT2_SETFILEINFO) {
2487 if (total_params < 4)
2488 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2490 fsp = file_fsp(params,0);
2491 info_level = SVAL(params,2);
2493 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2495 * This is actually a SETFILEINFO on a directory
2496 * handle (returned from an NT SMB). NT5.0 seems
2497 * to do this call. JRA.
2499 pstrcpy(fname, fsp->fsp_name);
2500 unix_convert(fname,conn,0,&bad_path,&sbuf);
2501 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2502 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2503 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2505 } else if (fsp && fsp->print_file) {
2507 * Doing a DELETE_ON_CLOSE should cancel a print job.
2509 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
2510 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2512 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
2514 SSVAL(params,0,0);
2515 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2516 return(-1);
2517 } else
2518 return (UNIXERROR(ERRDOS,ERRbadpath));
2519 } else {
2521 * Original code - this is an open file.
2523 CHECK_FSP(fsp,conn);
2525 pstrcpy(fname, fsp->fsp_name);
2526 fd = fsp->fd;
2528 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
2529 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2530 return(UNIXERROR(ERRDOS,ERRbadfid));
2533 } else {
2534 /* set path info */
2535 if (total_params < 6)
2536 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2538 info_level = SVAL(params,0);
2539 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
2540 unix_convert(fname,conn,0,&bad_path,&sbuf);
2541 if(!check_name(fname, conn)) {
2542 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2546 * For CIFS UNIX extensions the target name may not exist.
2549 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2550 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
2551 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2555 if (!CAN_WRITE(conn))
2556 return ERROR_DOS(ERRSRV,ERRaccess);
2558 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2559 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2561 if (VALID_STAT(sbuf))
2562 unixmode = sbuf.st_mode;
2564 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
2565 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
2567 /* Realloc the parameter and data sizes */
2568 params = Realloc(*pparams,2);
2569 if(params == NULL)
2570 return ERROR_DOS(ERRDOS,ERRnomem);
2571 *pparams = params;
2573 SSVAL(params,0,0);
2575 if (fsp) {
2576 /* the pending modtime overrides the current modtime */
2577 sbuf.st_mtime = fsp->pending_modtime;
2580 size = get_file_size(sbuf);
2581 tvs.modtime = sbuf.st_mtime;
2582 tvs.actime = sbuf.st_atime;
2583 dosmode = dos_mode(conn,fname,&sbuf);
2584 unixmode = sbuf.st_mode;
2586 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2587 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2589 switch (info_level) {
2590 case SMB_INFO_STANDARD:
2592 if (total_data < 12)
2593 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2595 /* access time */
2596 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2597 /* write time */
2598 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2599 break;
2602 case SMB_INFO_SET_EA:
2603 return(ERROR_DOS(ERRDOS,ERReasnotsupported));
2605 /* XXXX um, i don't think this is right.
2606 it's also not in the cifs6.txt spec.
2608 case SMB_INFO_QUERY_EAS_FROM_LIST:
2609 if (total_data < 28)
2610 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2612 tvs.actime = make_unix_date2(pdata+8);
2613 tvs.modtime = make_unix_date2(pdata+12);
2614 size = IVAL(pdata,16);
2615 dosmode = IVAL(pdata,24);
2616 break;
2618 /* XXXX nor this. not in cifs6.txt, either. */
2619 case SMB_INFO_QUERY_ALL_EAS:
2620 if (total_data < 28)
2621 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2623 tvs.actime = make_unix_date2(pdata+8);
2624 tvs.modtime = make_unix_date2(pdata+12);
2625 size = IVAL(pdata,16);
2626 dosmode = IVAL(pdata,24);
2627 break;
2629 case SMB_SET_FILE_BASIC_INFO:
2630 case SMB_FILE_BASIC_INFORMATION:
2632 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2633 time_t write_time;
2634 time_t changed_time;
2636 if (total_data < 36)
2637 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2639 /* Ignore create time at offset pdata. */
2641 /* access time */
2642 tvs.actime = interpret_long_date(pdata+8);
2644 write_time = interpret_long_date(pdata+16);
2645 changed_time = interpret_long_date(pdata+24);
2647 tvs.modtime = MIN(write_time, changed_time);
2649 if (write_time > tvs.modtime && write_time != 0xffffffff) {
2650 tvs.modtime = write_time;
2652 /* Prefer a defined time to an undefined one. */
2653 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2654 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2655 ? changed_time : write_time);
2657 /* attributes */
2658 dosmode = IVAL(pdata,32);
2659 break;
2662 case SMB_FILE_ALLOCATION_INFORMATION:
2663 case SMB_SET_FILE_ALLOCATION_INFO:
2665 int ret = -1;
2666 SMB_BIG_UINT allocation_size;
2668 if (total_data < 8)
2669 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2671 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
2672 #ifdef LARGE_SMB_OFF_T
2673 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
2674 #else /* LARGE_SMB_OFF_T */
2675 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2676 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2677 #endif /* LARGE_SMB_OFF_T */
2678 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2679 fname, (double)allocation_size ));
2681 if (allocation_size)
2682 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
2684 if(allocation_size != get_file_size(sbuf)) {
2685 SMB_STRUCT_STAT new_sbuf;
2687 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2688 fname, (double)allocation_size ));
2690 if (fd == -1) {
2691 files_struct *new_fsp = NULL;
2692 int access_mode = 0;
2693 int action = 0;
2695 if(global_oplock_break) {
2696 /* Queue this file modify as we are the process of an oplock break. */
2698 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2699 DEBUGADD(2,( "in oplock break state.\n"));
2701 push_oplock_pending_smb_message(inbuf, length);
2702 return -1;
2705 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2706 SET_OPEN_MODE(DOS_OPEN_RDWR),
2707 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2708 0, 0, &access_mode, &action);
2710 if (new_fsp == NULL)
2711 return(UNIXERROR(ERRDOS,ERRbadpath));
2712 ret = vfs_allocate_file_space(new_fsp, allocation_size);
2713 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2714 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2715 new_fsp->fnum, strerror(errno)));
2716 ret = -1;
2718 close_file(new_fsp,True);
2719 } else {
2720 ret = vfs_allocate_file_space(fsp, allocation_size);
2721 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
2722 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2723 fsp->fnum, strerror(errno)));
2724 ret = -1;
2727 if (ret == -1)
2728 return ERROR_NT(NT_STATUS_DISK_FULL);
2730 /* Allocate can truncate size... */
2731 size = get_file_size(new_sbuf);
2734 break;
2737 case SMB_FILE_END_OF_FILE_INFORMATION:
2738 case SMB_SET_FILE_END_OF_FILE_INFO:
2740 if (total_data < 8)
2741 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2743 size = IVAL(pdata,0);
2744 #ifdef LARGE_SMB_OFF_T
2745 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2746 #else /* LARGE_SMB_OFF_T */
2747 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2748 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2749 #endif /* LARGE_SMB_OFF_T */
2750 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2751 break;
2754 case SMB_FILE_DISPOSITION_INFORMATION:
2755 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2757 BOOL delete_on_close;
2758 NTSTATUS status;
2760 if (total_data < 1)
2761 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2763 delete_on_close = (CVAL(pdata,0) ? True : False);
2765 /* Just ignore this set on a path. */
2766 if (tran_call != TRANSACT2_SETFILEINFO)
2767 break;
2769 if (fsp == NULL)
2770 return(UNIXERROR(ERRDOS,ERRbadfid));
2772 status = set_delete_on_close_internal(fsp, delete_on_close);
2774 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2775 return ERROR_NT(status);
2777 /* The set is across all open files on this dev/inode pair. */
2778 status =set_delete_on_close_over_all(fsp, delete_on_close);
2779 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2780 return ERROR_NT(status);
2782 break;
2785 case SMB_FILE_POSITION_INFORMATION:
2787 SMB_BIG_UINT position_information;
2789 if (total_data < 8)
2790 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2792 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
2793 #ifdef LARGE_SMB_OFF_T
2794 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
2795 #else /* LARGE_SMB_OFF_T */
2796 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2797 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2798 #endif /* LARGE_SMB_OFF_T */
2799 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
2800 fname, (double)position_information ));
2801 if (fsp)
2802 fsp->position_information = position_information;
2803 break;
2807 * CIFS UNIX extensions.
2810 case SMB_SET_FILE_UNIX_BASIC:
2812 uint32 raw_unixmode;
2814 if (total_data < 100)
2815 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2817 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
2818 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
2819 size=IVAL(pdata,0); /* first 8 Bytes are size */
2820 #ifdef LARGE_SMB_OFF_T
2821 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2822 #else /* LARGE_SMB_OFF_T */
2823 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2824 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2825 #endif /* LARGE_SMB_OFF_T */
2827 pdata+=24; /* ctime & st_blocks are not changed */
2828 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
2829 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
2830 pdata+=16;
2831 set_owner = (uid_t)IVAL(pdata,0);
2832 pdata += 8;
2833 set_grp = (gid_t)IVAL(pdata,0);
2834 pdata += 8;
2835 raw_unixmode = IVAL(pdata,28);
2836 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2837 dosmode = 0; /* Ensure dos mode change doesn't override this. */
2839 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2840 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2841 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2843 if (!VALID_STAT(sbuf)) {
2846 * The only valid use of this is to create character and block
2847 * devices, and named pipes. This is deprecated (IMHO) and
2848 * a new info level should be used for mknod. JRA.
2851 #if !defined(HAVE_MAKEDEV_FN)
2852 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2853 #else /* HAVE_MAKEDEV_FN */
2854 uint32 file_type = IVAL(pdata,0);
2855 uint32 dev_major = IVAL(pdata,4);
2856 uint32 dev_minor = IVAL(pdata,12);
2858 uid_t myuid = geteuid();
2859 gid_t mygid = getegid();
2860 SMB_DEV_T dev;
2862 if (tran_call == TRANSACT2_SETFILEINFO)
2863 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2865 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2866 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2868 dev = makedev(dev_major, dev_minor);
2870 /* We can only create as the owner/group we are. */
2872 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2873 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2874 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2875 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2877 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2878 file_type != UNIX_TYPE_FIFO)
2879 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2881 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2882 0%o for file %s\n", (double)dev, unixmode, fname ));
2884 /* Ok - do the mknod. */
2885 if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
2886 return(UNIXERROR(ERRDOS,ERRnoaccess));
2888 inherit_access_acl(conn, fname, unixmode);
2890 SSVAL(params,0,0);
2891 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2892 return(-1);
2893 #endif /* HAVE_MAKEDEV_FN */
2898 * Deal with the UNIX specific mode set.
2901 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
2902 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2903 (unsigned int)unixmode, fname ));
2904 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
2905 return(UNIXERROR(ERRDOS,ERRnoaccess));
2909 * Deal with the UNIX specific uid set.
2912 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
2913 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2914 (unsigned int)set_owner, fname ));
2915 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
2916 return(UNIXERROR(ERRDOS,ERRnoaccess));
2920 * Deal with the UNIX specific gid set.
2923 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
2924 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2925 (unsigned int)set_owner, fname ));
2926 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
2927 return(UNIXERROR(ERRDOS,ERRnoaccess));
2929 break;
2932 case SMB_SET_FILE_UNIX_LINK:
2934 pstring link_dest;
2935 /* Set a symbolic link. */
2936 /* Don't allow this if follow links is false. */
2938 if (!lp_symlinks(SNUM(conn)))
2939 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2941 /* Disallow if already exists. */
2942 if (VALID_STAT(sbuf))
2943 return(ERROR_DOS(ERRDOS,ERRbadpath));
2945 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2947 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2948 return(UNIXERROR(ERRDOS,ERRnoaccess));
2950 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2951 fname, link_dest ));
2953 if (SMB_VFS_SYMLINK(conn,link_dest,fname) != 0)
2954 return(UNIXERROR(ERRDOS,ERRnoaccess));
2955 SSVAL(params,0,0);
2956 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2957 return(-1);
2960 case SMB_SET_FILE_UNIX_HLINK:
2962 pstring link_dest;
2964 /* Set a hard link. */
2966 /* Disallow if already exists. */
2967 if (VALID_STAT(sbuf))
2968 return(ERROR_DOS(ERRDOS,ERRbadpath));
2970 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2972 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2973 return(UNIXERROR(ERRDOS,ERRnoaccess));
2975 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2976 fname, link_dest ));
2978 if (SMB_VFS_LINK(conn,link_dest,fname) != 0)
2979 return(UNIXERROR(ERRDOS,ERRnoaccess));
2980 SSVAL(params,0,0);
2981 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2982 return(-1);
2985 case SMB_FILE_RENAME_INFORMATION:
2987 BOOL overwrite;
2988 uint32 root_fid;
2989 uint32 len;
2990 pstring newname;
2991 pstring base_name;
2992 char *p;
2993 NTSTATUS status;
2995 if (total_data < 12)
2996 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2998 overwrite = (CVAL(pdata,0) ? True : False);
2999 root_fid = IVAL(pdata,4);
3000 len = IVAL(pdata,8);
3001 srvstr_pull(inbuf, newname, &pdata[12], sizeof(newname), len, 0);
3003 /* Check the new name has no '\' characters. */
3004 if (strchr_m(newname, '\\') || strchr_m(newname, '/'))
3005 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3007 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3009 /* Create the base directory. */
3010 pstrcpy(base_name, fname);
3011 p = strrchr_m(base_name, '/');
3012 if (p)
3013 *p = '\0';
3014 /* Append the new name. */
3015 pstrcat(base_name, "/");
3016 pstrcat(base_name, newname);
3018 if (fsp) {
3019 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3020 fsp->fnum, fsp->fsp_name, base_name ));
3021 status = rename_internals_fsp(conn, fsp, base_name, overwrite);
3022 } else {
3023 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3024 fname, newname ));
3025 status = rename_internals(conn, fname, base_name, overwrite);
3027 if (!NT_STATUS_IS_OK(status))
3028 return ERROR_NT(status);
3029 process_pending_change_notify_queue((time_t)0);
3030 SSVAL(params,0,0);
3031 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3032 return(-1);
3034 default:
3035 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3038 /* get some defaults (no modifications) if any info is zero or -1. */
3039 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
3040 tvs.actime = sbuf.st_atime;
3042 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3043 tvs.modtime = sbuf.st_mtime;
3045 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3046 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3047 DEBUG(6,("size: %.0f ", (double)size));
3049 if (dosmode) {
3050 if (S_ISDIR(sbuf.st_mode))
3051 dosmode |= aDIR;
3052 else
3053 dosmode &= ~aDIR;
3056 DEBUG(6,("dosmode: %x\n" , dosmode));
3058 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3059 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3060 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3061 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3064 * Only do this test if we are not explicitly
3065 * changing the size of a file.
3067 if (!size)
3068 size = get_file_size(sbuf);
3072 * Try and set the times, size and mode of this file -
3073 * if they are different from the current values
3075 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3076 if(fsp != NULL) {
3078 * This was a setfileinfo on an open file.
3079 * NT does this a lot. It's actually pointless
3080 * setting the time here, as it will be overwritten
3081 * on the next write, so we save the request
3082 * away and will set it on file close. JRA.
3085 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3086 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3087 fsp->pending_modtime = tvs.modtime;
3090 } else {
3092 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3094 if(file_utime(conn, fname, &tvs)!=0)
3095 return(UNIXERROR(ERRDOS,ERRnoaccess));
3099 /* check the mode isn't different, before changing it */
3100 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3102 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3104 if(file_chmod(conn, fname, dosmode, NULL)) {
3105 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
3106 return(UNIXERROR(ERRDOS,ERRnoaccess));
3110 if (size != get_file_size(sbuf)) {
3112 int ret;
3114 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3115 fname, (double)size ));
3117 if (fd == -1) {
3118 files_struct *new_fsp = NULL;
3119 int access_mode = 0;
3120 int action = 0;
3122 if(global_oplock_break) {
3123 /* Queue this file modify as we are the process of an oplock break. */
3125 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3126 DEBUGADD(2,( "in oplock break state.\n"));
3128 push_oplock_pending_smb_message(inbuf, length);
3129 return -1;
3132 new_fsp = open_file_shared(conn, fname, &sbuf,
3133 SET_OPEN_MODE(DOS_OPEN_RDWR),
3134 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3135 0, 0, &access_mode, &action);
3137 if (new_fsp == NULL)
3138 return(UNIXERROR(ERRDOS,ERRbadpath));
3139 ret = vfs_set_filelen(new_fsp, size);
3140 close_file(new_fsp,True);
3141 } else {
3142 ret = vfs_set_filelen(fsp, size);
3145 if (ret == -1)
3146 return (UNIXERROR(ERRHRD,ERRdiskfull));
3149 SSVAL(params,0,0);
3150 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3152 return(-1);
3155 /****************************************************************************
3156 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3157 ****************************************************************************/
3159 static int call_trans2mkdir(connection_struct *conn,
3160 char *inbuf, char *outbuf, int length, int bufsize,
3161 char **pparams, int total_params, char **ppdata, int total_data)
3163 char *params = *pparams;
3164 pstring directory;
3165 int ret = -1;
3166 SMB_STRUCT_STAT sbuf;
3167 BOOL bad_path = False;
3169 if (!CAN_WRITE(conn))
3170 return ERROR_DOS(ERRSRV,ERRaccess);
3172 if (total_params < 4)
3173 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3175 srvstr_pull(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE);
3177 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3179 unix_convert(directory,conn,0,&bad_path,&sbuf);
3180 if (check_name(directory,conn))
3181 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3183 if(ret < 0) {
3184 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3185 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
3188 /* Realloc the parameter and data sizes */
3189 params = Realloc(*pparams,2);
3190 if(params == NULL)
3191 return ERROR_DOS(ERRDOS,ERRnomem);
3192 *pparams = params;
3194 SSVAL(params,0,0);
3196 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3198 return(-1);
3201 /****************************************************************************
3202 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3203 We don't actually do this - we just send a null response.
3204 ****************************************************************************/
3206 static int call_trans2findnotifyfirst(connection_struct *conn,
3207 char *inbuf, char *outbuf, int length, int bufsize,
3208 char **pparams, int total_params, char **ppdata, int total_data)
3210 static uint16 fnf_handle = 257;
3211 char *params = *pparams;
3212 uint16 info_level;
3214 if (total_params < 6)
3215 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3217 info_level = SVAL(params,4);
3218 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3220 switch (info_level) {
3221 case 1:
3222 case 2:
3223 break;
3224 default:
3225 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3228 /* Realloc the parameter and data sizes */
3229 params = Realloc(*pparams,6);
3230 if(params == NULL)
3231 return ERROR_DOS(ERRDOS,ERRnomem);
3232 *pparams = params;
3234 SSVAL(params,0,fnf_handle);
3235 SSVAL(params,2,0); /* No changes */
3236 SSVAL(params,4,0); /* No EA errors */
3238 fnf_handle++;
3240 if(fnf_handle == 0)
3241 fnf_handle = 257;
3243 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3245 return(-1);
3248 /****************************************************************************
3249 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3250 changes). Currently this does nothing.
3251 ****************************************************************************/
3253 static int call_trans2findnotifynext(connection_struct *conn,
3254 char *inbuf, char *outbuf, int length, int bufsize,
3255 char **pparams, int total_params, char **ppdata, int total_data)
3257 char *params = *pparams;
3259 DEBUG(3,("call_trans2findnotifynext\n"));
3261 /* Realloc the parameter and data sizes */
3262 params = Realloc(*pparams,4);
3263 if(params == NULL)
3264 return ERROR_DOS(ERRDOS,ERRnomem);
3265 *pparams = params;
3267 SSVAL(params,0,0); /* No changes */
3268 SSVAL(params,2,0); /* No EA errors */
3270 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3272 return(-1);
3275 /****************************************************************************
3276 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3277 ****************************************************************************/
3279 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3280 char* outbuf, int length, int bufsize,
3281 char **pparams, int total_params, char **ppdata, int total_data)
3283 char *params = *pparams;
3284 pstring pathname;
3285 int reply_size = 0;
3286 int max_referral_level;
3288 DEBUG(10,("call_trans2getdfsreferral\n"));
3290 if (total_params < 2)
3291 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3293 max_referral_level = SVAL(params,0);
3295 if(!lp_host_msdfs())
3296 return ERROR_DOS(ERRDOS,ERRbadfunc);
3298 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
3300 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
3301 return UNIXERROR(ERRDOS,ERRbadfile);
3303 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3304 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3306 return(-1);
3309 #define LMCAT_SPL 0x53
3310 #define LMFUNC_GETJOBID 0x60
3312 /****************************************************************************
3313 Reply to a TRANS2_IOCTL - used for OS/2 printing.
3314 ****************************************************************************/
3316 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3317 char* outbuf, int length, int bufsize,
3318 char **pparams, int total_params, char **ppdata, int total_data)
3320 char *pdata = *ppdata;
3321 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3323 /* check for an invalid fid before proceeding */
3325 if (!fsp)
3326 return(ERROR_DOS(ERRDOS,ERRbadfid));
3328 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3329 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3330 pdata = Realloc(*ppdata, 32);
3331 if(pdata == NULL)
3332 return ERROR_DOS(ERRDOS,ERRnomem);
3333 *ppdata = pdata;
3335 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3336 CAN ACCEPT THIS IN UNICODE. JRA. */
3338 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
3339 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3340 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3341 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3342 return(-1);
3343 } else {
3344 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3345 return ERROR_DOS(ERRSRV,ERRerror);
3349 /****************************************************************************
3350 Reply to a SMBfindclose (stop trans2 directory search).
3351 ****************************************************************************/
3353 int reply_findclose(connection_struct *conn,
3354 char *inbuf,char *outbuf,int length,int bufsize)
3356 int outsize = 0;
3357 int dptr_num=SVALS(inbuf,smb_vwv0);
3358 START_PROFILE(SMBfindclose);
3360 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3362 dptr_close(&dptr_num);
3364 outsize = set_message(outbuf,0,0,True);
3366 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3368 END_PROFILE(SMBfindclose);
3369 return(outsize);
3372 /****************************************************************************
3373 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3374 ****************************************************************************/
3376 int reply_findnclose(connection_struct *conn,
3377 char *inbuf,char *outbuf,int length,int bufsize)
3379 int outsize = 0;
3380 int dptr_num= -1;
3381 START_PROFILE(SMBfindnclose);
3383 dptr_num = SVAL(inbuf,smb_vwv0);
3385 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3387 /* We never give out valid handles for a
3388 findnotifyfirst - so any dptr_num is ok here.
3389 Just ignore it. */
3391 outsize = set_message(outbuf,0,0,True);
3393 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3395 END_PROFILE(SMBfindnclose);
3396 return(outsize);
3399 /****************************************************************************
3400 Reply to a SMBtranss2 - just ignore it!
3401 ****************************************************************************/
3403 int reply_transs2(connection_struct *conn,
3404 char *inbuf,char *outbuf,int length,int bufsize)
3406 START_PROFILE(SMBtranss2);
3407 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3408 END_PROFILE(SMBtranss2);
3409 return(-1);
3412 /****************************************************************************
3413 Reply to a SMBtrans2.
3414 ****************************************************************************/
3416 int reply_trans2(connection_struct *conn,
3417 char *inbuf,char *outbuf,int length,int bufsize)
3419 int outsize = 0;
3420 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3421 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3422 #if 0
3423 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3424 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3425 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3426 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3427 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3428 int32 timeout = IVALS(inbuf,smb_timeout);
3429 #endif
3430 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3431 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3432 char *params = NULL, *data = NULL;
3433 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
3434 START_PROFILE(SMBtrans2);
3436 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3437 /* Queue this open message as we are the process of an
3438 * oplock break. */
3440 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3441 DEBUGADD(2,( "in oplock break state.\n"));
3443 push_oplock_pending_smb_message(inbuf, length);
3444 END_PROFILE(SMBtrans2);
3445 return -1;
3448 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3449 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3450 END_PROFILE(SMBtrans2);
3451 return ERROR_DOS(ERRSRV,ERRaccess);
3454 outsize = set_message(outbuf,0,0,True);
3456 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3457 is so as a sanity check */
3458 if (suwcnt != 1) {
3460 * Need to have rc=0 for ioctl to get job id for OS/2.
3461 * Network printing will fail if function is not successful.
3462 * Similar function in reply.c will be used if protocol
3463 * is LANMAN1.0 instead of LM1.2X002.
3464 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3465 * outbuf doesn't have to be set(only job id is used).
3467 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3468 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3469 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3470 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3471 } else {
3472 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
3473 DEBUG(2,("Transaction is %d\n",tran_call));
3474 END_PROFILE(SMBtrans2);
3475 ERROR_DOS(ERRDOS,ERRinvalidparam);
3479 /* Allocate the space for the maximum needed parameters and data */
3480 if (total_params > 0)
3481 params = (char *)malloc(total_params);
3482 if (total_data > 0)
3483 data = (char *)malloc(total_data);
3485 if ((total_params && !params) || (total_data && !data)) {
3486 DEBUG(2,("Out of memory in reply_trans2\n"));
3487 SAFE_FREE(params);
3488 SAFE_FREE(data);
3489 END_PROFILE(SMBtrans2);
3490 return ERROR_DOS(ERRDOS,ERRnomem);
3493 /* Copy the param and data bytes sent with this request into
3494 the params buffer */
3495 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3496 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3498 if (num_params > total_params || num_data > total_data)
3499 exit_server("invalid params in reply_trans2");
3501 if(params) {
3502 unsigned int psoff = SVAL(inbuf, smb_psoff);
3503 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
3504 goto bad_param;
3505 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
3506 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
3507 goto bad_param;
3508 memcpy( params, smb_base(inbuf) + psoff, num_params);
3510 if(data) {
3511 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
3512 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
3513 goto bad_param;
3514 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
3515 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
3516 goto bad_param;
3517 memcpy( data, smb_base(inbuf) + dsoff, num_data);
3520 srv_signing_trans_start(SVAL(inbuf,smb_mid));
3522 if(num_data_sofar < total_data || num_params_sofar < total_params) {
3523 /* We need to send an interim response then receive the rest
3524 of the parameter/data bytes */
3525 outsize = set_message(outbuf,0,0,True);
3526 if (!send_smb(smbd_server_fd(),outbuf))
3527 exit_server("reply_trans2: send_smb failed.");
3529 while (num_data_sofar < total_data ||
3530 num_params_sofar < total_params) {
3531 BOOL ret;
3532 unsigned int param_disp;
3533 unsigned int param_off;
3534 unsigned int data_disp;
3535 unsigned int data_off;
3537 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3539 if ((ret &&
3540 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3541 outsize = set_message(outbuf,0,0,True);
3542 if(ret)
3543 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3544 else
3545 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3546 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3547 goto bad_param;
3550 /* Revise total_params and total_data in case
3551 they have changed downwards */
3552 if (SVAL(inbuf, smb_tpscnt) < total_params)
3553 total_params = SVAL(inbuf, smb_tpscnt);
3554 if (SVAL(inbuf, smb_tdscnt) < total_data)
3555 total_data = SVAL(inbuf, smb_tdscnt);
3557 num_params = SVAL(inbuf,smb_spscnt);
3558 param_off = SVAL(inbuf, smb_spsoff);
3559 param_disp = SVAL(inbuf, smb_spsdisp);
3560 num_params_sofar += num_params;
3562 num_data = SVAL(inbuf, smb_sdscnt);
3563 data_off = SVAL(inbuf, smb_sdsoff);
3564 data_disp = SVAL(inbuf, smb_sdsdisp);
3565 num_data_sofar += num_data;
3567 if (num_params_sofar > total_params || num_data_sofar > total_data)
3568 goto bad_param;
3570 if (num_params) {
3571 if (param_disp + num_params >= total_params)
3572 goto bad_param;
3573 if ((param_disp + num_params < param_disp) ||
3574 (param_disp + num_params < num_params))
3575 goto bad_param;
3576 if (param_disp > total_params)
3577 goto bad_param;
3578 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
3579 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
3580 goto bad_param;
3581 if (params + param_disp < params)
3582 goto bad_param;
3584 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
3586 if (num_data) {
3587 if (data_disp + num_data >= total_data)
3588 goto bad_param;
3589 if ((data_disp + num_data < data_disp) ||
3590 (data_disp + num_data < num_data))
3591 goto bad_param;
3592 if (data_disp > total_data)
3593 goto bad_param;
3594 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
3595 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
3596 goto bad_param;
3597 if (data + data_disp < data)
3598 goto bad_param;
3600 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
3605 if (Protocol >= PROTOCOL_NT1) {
3606 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
3609 /* Now we must call the relevant TRANS2 function */
3610 switch(tran_call) {
3611 case TRANSACT2_OPEN:
3612 START_PROFILE_NESTED(Trans2_open);
3613 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
3614 &params, total_params, &data, total_data);
3615 END_PROFILE_NESTED(Trans2_open);
3616 break;
3618 case TRANSACT2_FINDFIRST:
3619 START_PROFILE_NESTED(Trans2_findfirst);
3620 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3621 &params, total_params, &data, total_data);
3622 END_PROFILE_NESTED(Trans2_findfirst);
3623 break;
3625 case TRANSACT2_FINDNEXT:
3626 START_PROFILE_NESTED(Trans2_findnext);
3627 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
3628 &params, total_params, &data, total_data);
3629 END_PROFILE_NESTED(Trans2_findnext);
3630 break;
3632 case TRANSACT2_QFSINFO:
3633 START_PROFILE_NESTED(Trans2_qfsinfo);
3634 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3635 &params, total_params, &data, total_data);
3636 END_PROFILE_NESTED(Trans2_qfsinfo);
3637 break;
3639 #ifdef HAVE_SYS_QUOTAS
3640 case TRANSACT2_SETFSINFO:
3641 START_PROFILE_NESTED(Trans2_setfsinfo);
3642 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
3643 &params, total_params, &data, total_data);
3644 END_PROFILE_NESTED(Trans2_setfsinfo);
3645 break;
3646 #endif
3647 case TRANSACT2_QPATHINFO:
3648 case TRANSACT2_QFILEINFO:
3649 START_PROFILE_NESTED(Trans2_qpathinfo);
3650 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3651 &params, total_params, &data, total_data);
3652 END_PROFILE_NESTED(Trans2_qpathinfo);
3653 break;
3654 case TRANSACT2_SETPATHINFO:
3655 case TRANSACT2_SETFILEINFO:
3656 START_PROFILE_NESTED(Trans2_setpathinfo);
3657 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3658 &params, total_params, &data, total_data);
3659 END_PROFILE_NESTED(Trans2_setpathinfo);
3660 break;
3662 case TRANSACT2_FINDNOTIFYFIRST:
3663 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3664 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
3665 &params, total_params, &data, total_data);
3666 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3667 break;
3669 case TRANSACT2_FINDNOTIFYNEXT:
3670 START_PROFILE_NESTED(Trans2_findnotifynext);
3671 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
3672 &params, total_params, &data, total_data);
3673 END_PROFILE_NESTED(Trans2_findnotifynext);
3674 break;
3675 case TRANSACT2_MKDIR:
3676 START_PROFILE_NESTED(Trans2_mkdir);
3677 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3678 &params, total_params, &data, total_data);
3679 END_PROFILE_NESTED(Trans2_mkdir);
3680 break;
3682 case TRANSACT2_GET_DFS_REFERRAL:
3683 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3684 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3685 &params, total_params, &data, total_data);
3686 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3687 break;
3688 case TRANSACT2_IOCTL:
3689 START_PROFILE_NESTED(Trans2_ioctl);
3690 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3691 &params, total_params, &data, total_data);
3692 END_PROFILE_NESTED(Trans2_ioctl);
3693 break;
3694 default:
3695 /* Error in request */
3696 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3697 SAFE_FREE(params);
3698 SAFE_FREE(data);
3699 END_PROFILE(SMBtrans2);
3700 srv_signing_trans_stop();
3701 return ERROR_DOS(ERRSRV,ERRerror);
3704 /* As we do not know how many data packets will need to be
3705 returned here the various call_trans2xxxx calls
3706 must send their own. Thus a call_trans2xxx routine only
3707 returns a value other than -1 when it wants to send
3708 an error packet.
3711 srv_signing_trans_stop();
3713 SAFE_FREE(params);
3714 SAFE_FREE(data);
3715 END_PROFILE(SMBtrans2);
3716 return outsize; /* If a correct response was needed the
3717 call_trans2xxx calls have already sent
3718 it. If outsize != -1 then it is returning */
3720 bad_param:
3722 srv_signing_trans_stop();
3723 SAFE_FREE(params);
3724 SAFE_FREE(data);
3725 END_PROFILE(SMBtrans2);
3726 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);