trying to get HEAD building again. If you want the code
[Samba.git] / source / smbd / trans2.c
blobbdcd04443e972c70f29de7e11badff2fe54652c0
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2001
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 set_bad_path_error(errno, bad_path);
265 return(UNIXERROR(ERRDOS,ERRnoaccess));
268 unixmode = unix_mode(conn,open_attr | aARCH, fname);
270 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode,
271 oplock_request, &rmode,&smb_action);
273 if (!fsp) {
274 set_bad_path_error(errno, bad_path);
275 return(UNIXERROR(ERRDOS,ERRnoaccess));
278 size = get_file_size(sbuf);
279 fmode = dos_mode(conn,fname,&sbuf);
280 mtime = sbuf.st_mtime;
281 inode = sbuf.st_ino;
282 if (fmode & aDIR) {
283 close_file(fsp,False);
284 return(ERROR_DOS(ERRDOS,ERRnoaccess));
287 /* Realloc the size of parameters and data we will return */
288 params = Realloc(*pparams, 28);
289 if( params == NULL )
290 return(ERROR_DOS(ERRDOS,ERRnomem));
291 *pparams = params;
293 memset((char *)params,'\0',28);
294 SSVAL(params,0,fsp->fnum);
295 SSVAL(params,2,fmode);
296 put_dos_date2(params,4, mtime);
297 SIVAL(params,8, (uint32)size);
298 SSVAL(params,12,rmode);
300 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
301 smb_action |= EXTENDED_OPLOCK_GRANTED;
303 SSVAL(params,18,smb_action);
306 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
308 SIVAL(params,20,inode);
310 /* Send the required number of replies */
311 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
313 return -1;
316 /*********************************************************
317 Routine to check if a given string matches exactly.
318 as a special case a mask of "." does NOT match. That
319 is required for correct wildcard semantics
320 Case can be significant or not.
321 **********************************************************/
323 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
325 if (mask[0] == '.' && mask[1] == 0)
326 return False;
327 if (case_sig)
328 return strcmp(str,mask)==0;
329 return StrCaseCmp(str,mask) == 0;
332 /****************************************************************************
333 Return the filetype for UNIX extensions.
334 ****************************************************************************/
336 static uint32 unix_filetype(mode_t mode)
338 if(S_ISREG(mode))
339 return UNIX_TYPE_FILE;
340 else if(S_ISDIR(mode))
341 return UNIX_TYPE_DIR;
342 #ifdef S_ISLNK
343 else if(S_ISLNK(mode))
344 return UNIX_TYPE_SYMLINK;
345 #endif
346 #ifdef S_ISCHR
347 else if(S_ISCHR(mode))
348 return UNIX_TYPE_CHARDEV;
349 #endif
350 #ifdef S_ISBLK
351 else if(S_ISBLK(mode))
352 return UNIX_TYPE_BLKDEV;
353 #endif
354 #ifdef S_ISFIFO
355 else if(S_ISFIFO(mode))
356 return UNIX_TYPE_FIFO;
357 #endif
358 #ifdef S_ISSOCK
359 else if(S_ISSOCK(mode))
360 return UNIX_TYPE_SOCKET;
361 #endif
363 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
364 return UNIX_TYPE_UNKNOWN;
367 /****************************************************************************
368 Return the major devicenumber for UNIX extensions.
369 ****************************************************************************/
371 static uint32 unix_dev_major(SMB_DEV_T dev)
373 #if defined(HAVE_DEVICE_MAJOR_FN)
374 return (uint32)major(dev);
375 #else
376 return (uint32)(dev >> 8);
377 #endif
380 /****************************************************************************
381 Return the minor devicenumber for UNIX extensions.
382 ****************************************************************************/
384 static uint32 unix_dev_minor(SMB_DEV_T dev)
386 #if defined(HAVE_DEVICE_MINOR_FN)
387 return (uint32)minor(dev);
388 #else
389 return (uint32)(dev & 0xff);
390 #endif
393 /****************************************************************************
394 Map wire perms onto standard UNIX permissions. Obey share restrictions.
395 ****************************************************************************/
397 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
399 mode_t ret = 0;
401 if (perms == SMB_MODE_NO_CHANGE)
402 return pst->st_mode;
404 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
405 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
406 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
407 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
408 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
409 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
410 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
411 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
412 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
413 #ifdef S_ISVTX
414 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
415 #endif
416 #ifdef S_ISGID
417 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
418 #endif
419 #ifdef S_ISUID
420 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
421 #endif
423 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
424 ret &= lp_dir_mask(SNUM(conn));
425 /* Add in force bits */
426 ret |= lp_force_dir_mode(SNUM(conn));
427 } else {
428 /* Apply mode mask */
429 ret &= lp_create_mask(SNUM(conn));
430 /* Add in force bits */
431 ret |= lp_force_create_mode(SNUM(conn));
434 return ret;
437 /****************************************************************************
438 checks for SMB_TIME_NO_CHANGE and if not found
439 calls interpret_long_date
440 ****************************************************************************/
441 time_t interpret_long_unix_date(char *p)
443 DEBUG(1,("interpret_long_unix_date\n"));
444 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
445 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
446 return -1;
447 } else {
448 return interpret_long_date(p);
452 /****************************************************************************
453 Get a level dependent lanman2 dir entry.
454 ****************************************************************************/
456 static BOOL get_lanman2_dir_entry(connection_struct *conn,
457 void *inbuf, void *outbuf,
458 char *path_mask,int dirtype,int info_level,
459 int requires_resume_key,
460 BOOL dont_descend,char **ppdata,
461 char *base_data, int space_remaining,
462 BOOL *out_of_space, BOOL *got_exact_match,
463 int *last_name_off)
465 const char *dname;
466 BOOL found = False;
467 SMB_STRUCT_STAT sbuf;
468 pstring mask;
469 pstring pathreal;
470 pstring fname;
471 char *p, *q, *pdata = *ppdata;
472 uint32 reskey=0;
473 int prev_dirpos=0;
474 int mode=0;
475 SMB_OFF_T file_size = 0;
476 SMB_BIG_UINT allocation_size = 0;
477 uint32 len;
478 time_t mdate=0, adate=0, cdate=0;
479 char *nameptr;
480 BOOL was_8_3;
481 int nt_extmode; /* Used for NT connections instead of mode */
482 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
484 *fname = 0;
485 *out_of_space = False;
486 *got_exact_match = False;
488 if (!conn->dirptr)
489 return(False);
491 p = strrchr_m(path_mask,'/');
492 if(p != NULL) {
493 if(p[1] == '\0')
494 pstrcpy(mask,"*.*");
495 else
496 pstrcpy(mask, p+1);
497 } else
498 pstrcpy(mask, path_mask);
500 while (!found) {
501 BOOL got_match;
503 /* Needed if we run out of space */
504 prev_dirpos = TellDir(conn->dirptr);
505 dname = ReadDirName(conn->dirptr);
508 * Due to bugs in NT client redirectors we are not using
509 * resume keys any more - set them to zero.
510 * Check out the related comments in findfirst/findnext.
511 * JRA.
514 reskey = 0;
516 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
517 (long)conn->dirptr,TellDir(conn->dirptr)));
519 if (!dname)
520 return(False);
522 pstrcpy(fname,dname);
524 if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
525 got_match = mask_match(fname, mask, case_sensitive);
527 if(!got_match && !mangle_is_8_3(fname, False)) {
530 * It turns out that NT matches wildcards against
531 * both long *and* short names. This may explain some
532 * of the wildcard wierdness from old DOS clients
533 * that some people have been seeing.... JRA.
536 pstring newname;
537 pstrcpy( newname, fname);
538 mangle_map( newname, True, False, SNUM(conn));
539 if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
540 got_match = mask_match(newname, mask, case_sensitive);
543 if(got_match) {
544 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
545 if (dont_descend && !isdots)
546 continue;
548 pstrcpy(pathreal,conn->dirpath);
549 if(needslash)
550 pstrcat(pathreal,"/");
551 pstrcat(pathreal,dname);
553 if (INFO_LEVEL_IS_UNIX(info_level)) {
554 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
555 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
556 pathreal,strerror(errno)));
557 continue;
559 } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
561 /* Needed to show the msdfs symlinks as
562 * directories */
564 if(lp_host_msdfs() &&
565 lp_msdfs_root(SNUM(conn)) &&
566 is_msdfs_link(conn, pathreal, NULL, NULL,
567 &sbuf)) {
569 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
570 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
572 } else {
574 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
575 pathreal,strerror(errno)));
576 continue;
580 mode = dos_mode(conn,pathreal,&sbuf);
582 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
583 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
584 continue;
587 file_size = get_file_size(sbuf);
588 allocation_size = get_allocation_size(NULL,&sbuf);
589 mdate = sbuf.st_mtime;
590 adate = sbuf.st_atime;
591 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
593 if (lp_dos_filetime_resolution(SNUM(conn))) {
594 cdate &= ~1;
595 mdate &= ~1;
596 adate &= ~1;
599 if(mode & aDIR)
600 file_size = 0;
602 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
604 found = True;
608 mangle_map(fname,False,True,SNUM(conn));
610 p = pdata;
611 nameptr = p;
613 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
615 switch (info_level) {
616 case SMB_INFO_STANDARD:
617 if(requires_resume_key) {
618 SIVAL(p,0,reskey);
619 p += 4;
621 put_dos_date2(p,l1_fdateCreation,cdate);
622 put_dos_date2(p,l1_fdateLastAccess,adate);
623 put_dos_date2(p,l1_fdateLastWrite,mdate);
624 SIVAL(p,l1_cbFile,(uint32)file_size);
625 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
626 SSVAL(p,l1_attrFile,mode);
627 p += l1_achName;
628 nameptr = p;
629 p += align_string(outbuf, p, 0);
630 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
631 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS)
632 SCVAL(nameptr, -1, len-2);
633 else
634 SCVAL(nameptr, -1, len-1);
635 p += len;
636 break;
638 case SMB_INFO_QUERY_EA_SIZE:
639 if(requires_resume_key) {
640 SIVAL(p,0,reskey);
641 p += 4;
643 put_dos_date2(p,l2_fdateCreation,cdate);
644 put_dos_date2(p,l2_fdateLastAccess,adate);
645 put_dos_date2(p,l2_fdateLastWrite,mdate);
646 SIVAL(p,l2_cbFile,(uint32)file_size);
647 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
648 SSVAL(p,l2_attrFile,mode);
649 SIVAL(p,l2_cbList,0); /* No extended attributes */
650 p += l2_achName;
651 nameptr = p;
652 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
653 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS)
654 SCVAL(nameptr, -1, len-2);
655 else
656 SCVAL(nameptr, -1, len-1);
657 p += len;
658 break;
660 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
661 was_8_3 = mangle_is_8_3(fname, True);
662 p += 4;
663 SIVAL(p,0,reskey); p += 4;
664 put_long_date(p,cdate); p += 8;
665 put_long_date(p,adate); p += 8;
666 put_long_date(p,mdate); p += 8;
667 put_long_date(p,mdate); p += 8;
668 SOFF_T(p,0,file_size);
669 SOFF_T(p,8,allocation_size);
670 p += 16;
671 SIVAL(p,0,nt_extmode); p += 4;
672 q = p; p += 4;
673 SIVAL(p,0,0); p += 4;
674 /* Clear the short name buffer. This is
675 * IMPORTANT as not doing so will trigger
676 * a Win2k client bug. JRA.
678 memset(p,'\0',26);
679 if (!was_8_3) {
680 pstring mangled_name;
681 pstrcpy(mangled_name, fname);
682 mangle_map(mangled_name,True,True,SNUM(conn));
683 mangled_name[12] = 0;
684 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
685 SSVAL(p, 0, len);
686 } else {
687 SSVAL(p,0,0);
688 *(p+2) = 0;
690 p += 2 + 24;
691 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
692 SIVAL(q,0,len);
693 p += len;
694 len = PTR_DIFF(p, pdata);
695 len = (len + 3) & ~3;
696 SIVAL(pdata,0,len);
697 p = pdata + len;
698 break;
700 case SMB_FIND_FILE_DIRECTORY_INFO:
701 p += 4;
702 SIVAL(p,0,reskey); p += 4;
703 put_long_date(p,cdate); p += 8;
704 put_long_date(p,adate); p += 8;
705 put_long_date(p,mdate); p += 8;
706 put_long_date(p,mdate); p += 8;
707 SOFF_T(p,0,file_size);
708 SOFF_T(p,8,allocation_size);
709 p += 16;
710 SIVAL(p,0,nt_extmode); p += 4;
711 p += 4;
712 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
713 SIVAL(p, -4, len);
714 p += len;
715 len = PTR_DIFF(p, pdata);
716 len = (len + 3) & ~3;
717 SIVAL(pdata,0,len);
718 p = pdata + len;
719 break;
721 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
722 p += 4;
723 SIVAL(p,0,reskey); p += 4;
724 put_long_date(p,cdate); p += 8;
725 put_long_date(p,adate); p += 8;
726 put_long_date(p,mdate); p += 8;
727 put_long_date(p,mdate); p += 8;
728 SOFF_T(p,0,file_size);
729 SOFF_T(p,8,allocation_size);
730 p += 16;
731 SIVAL(p,0,nt_extmode);
732 p += 4;
734 SIVAL(p,4,0); /* ea size */
735 len = srvstr_push(outbuf, p+8, fname, -1, STR_TERMINATE_ASCII);
736 SIVAL(p, 0, len);
737 p += 8 + len;
739 len = PTR_DIFF(p, pdata);
740 len = (len + 3) & ~3;
741 SIVAL(pdata,0,len);
742 p = pdata + len;
743 break;
745 case SMB_FIND_FILE_NAMES_INFO:
746 p += 4;
747 SIVAL(p,0,reskey); p += 4;
748 p += 4;
749 /* this must *not* be null terminated or w2k gets in a loop trying to set an
750 acl on a dir (tridge) */
751 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
752 SIVAL(p, -4, len);
753 p += len;
754 len = PTR_DIFF(p, pdata);
755 len = (len + 3) & ~3;
756 SIVAL(pdata,0,len);
757 p = pdata + len;
758 break;
760 /* CIFS UNIX Extension. */
762 case SMB_FIND_FILE_UNIX:
763 p+= 4;
764 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
766 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
767 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
768 p+= 8;
770 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
771 p+= 8;
773 put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */
774 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
775 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
776 p+= 24;
778 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
779 SIVAL(p,4,0);
780 p+= 8;
782 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
783 SIVAL(p,4,0);
784 p+= 8;
786 SIVAL(p,0,unix_filetype(sbuf.st_mode));
787 p+= 4;
789 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
790 SIVAL(p,4,0);
791 p+= 8;
793 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
794 SIVAL(p,4,0);
795 p+= 8;
797 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
798 p+= 8;
800 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
801 SIVAL(p,4,0);
802 p+= 8;
804 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
805 SIVAL(p,4,0);
806 p+= 8;
808 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
809 p += len;
811 len = PTR_DIFF(p, pdata);
812 len = (len + 3) & ~3;
813 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
814 p = pdata + len;
815 /* End of SMB_QUERY_FILE_UNIX_BASIC */
817 break;
819 default:
820 return(False);
824 if (PTR_DIFF(p,pdata) > space_remaining) {
825 /* Move the dirptr back to prev_dirpos */
826 SeekDir(conn->dirptr, prev_dirpos);
827 *out_of_space = True;
828 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
829 return False; /* Not finished - just out of space */
832 /* Setup the last_filename pointer, as an offset from base_data */
833 *last_name_off = PTR_DIFF(nameptr,base_data);
834 /* Advance the data pointer to the next slot */
835 *ppdata = p;
837 return(found);
840 /****************************************************************************
841 Reply to a TRANS2_FINDFIRST.
842 ****************************************************************************/
844 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
845 char **pparams, int total_params, char **ppdata, int total_data)
847 /* We must be careful here that we don't return more than the
848 allowed number of data bytes. If this means returning fewer than
849 maxentries then so be it. We assume that the redirector has
850 enough room for the fixed number of parameter bytes it has
851 requested. */
852 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
853 char *params = *pparams;
854 char *pdata = *ppdata;
855 int dirtype = SVAL(params,0);
856 int maxentries = SVAL(params,2);
857 BOOL close_after_first = BITSETW(params+4,0);
858 BOOL close_if_end = BITSETW(params+4,1);
859 BOOL requires_resume_key = BITSETW(params+4,2);
860 int info_level = SVAL(params,6);
861 pstring directory;
862 pstring mask;
863 char *p, *wcard;
864 int last_name_off=0;
865 int dptr_num = -1;
866 int numentries = 0;
867 int i;
868 BOOL finished = False;
869 BOOL dont_descend = False;
870 BOOL out_of_space = False;
871 int space_remaining;
872 BOOL bad_path = False;
873 SMB_STRUCT_STAT sbuf;
875 if (total_params < 12)
876 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
878 *directory = *mask = 0;
880 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
881 close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
882 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
883 info_level, max_data_bytes));
885 switch (info_level) {
886 case SMB_INFO_STANDARD:
887 case SMB_INFO_QUERY_EA_SIZE:
888 case SMB_FIND_FILE_DIRECTORY_INFO:
889 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
890 case SMB_FIND_FILE_NAMES_INFO:
891 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
892 break;
893 case SMB_FIND_FILE_UNIX:
894 if (!lp_unix_extensions())
895 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
896 break;
897 default:
898 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
901 srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE);
903 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
905 unix_convert(directory,conn,0,&bad_path,&sbuf);
906 if(!check_name(directory,conn)) {
907 set_bad_path_error(errno, bad_path);
908 return(UNIXERROR(ERRDOS,ERRbadpath));
911 p = strrchr_m(directory,'/');
912 if(p == NULL) {
913 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
914 if((directory[0] == '.') && (directory[1] == '\0'))
915 pstrcpy(mask,"*");
916 else
917 pstrcpy(mask,directory);
918 pstrcpy(directory,"./");
919 } else {
920 pstrcpy(mask,p+1);
921 *p = 0;
924 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
926 pdata = Realloc(*ppdata, max_data_bytes + 1024);
927 if( pdata == NULL )
928 return(ERROR_DOS(ERRDOS,ERRnomem));
930 *ppdata = pdata;
931 memset((char *)pdata,'\0',max_data_bytes + 1024);
933 /* Realloc the params space */
934 params = Realloc(*pparams, 10);
935 if (params == NULL)
936 return ERROR_DOS(ERRDOS,ERRnomem);
937 *pparams = params;
939 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
940 if (dptr_num < 0)
941 return(UNIXERROR(ERRDOS,ERRbadfile));
943 /* Save the wildcard match and attribs we are using on this directory -
944 needed as lanman2 assumes these are being saved between calls */
946 if(!(wcard = strdup(mask))) {
947 dptr_close(&dptr_num);
948 return ERROR_DOS(ERRDOS,ERRnomem);
951 dptr_set_wcard(dptr_num, wcard);
952 dptr_set_attr(dptr_num, dirtype);
954 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
956 /* We don't need to check for VOL here as this is returned by
957 a different TRANS2 call. */
959 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
960 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
961 dont_descend = True;
963 p = pdata;
964 space_remaining = max_data_bytes;
965 out_of_space = False;
967 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
968 BOOL got_exact_match = False;
970 /* this is a heuristic to avoid seeking the dirptr except when
971 absolutely necessary. It allows for a filename of about 40 chars */
972 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
973 out_of_space = True;
974 finished = False;
975 } else {
976 finished = !get_lanman2_dir_entry(conn,
977 inbuf, outbuf,
978 mask,dirtype,info_level,
979 requires_resume_key,dont_descend,
980 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
981 &last_name_off);
984 if (finished && out_of_space)
985 finished = False;
987 if (!finished && !out_of_space)
988 numentries++;
991 * As an optimisation if we know we aren't looking
992 * for a wildcard name (ie. the name matches the wildcard exactly)
993 * then we can finish on any (first) match.
994 * This speeds up large directory searches. JRA.
997 if(got_exact_match)
998 finished = True;
1000 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1003 /* Check if we can close the dirptr */
1004 if(close_after_first || (finished && close_if_end)) {
1005 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1006 dptr_close(&dptr_num);
1010 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1011 * from observation of NT.
1014 if(numentries == 0) {
1015 dptr_close(&dptr_num);
1016 return ERROR_DOS(ERRDOS,ERRbadfile);
1019 /* At this point pdata points to numentries directory entries. */
1021 /* Set up the return parameter block */
1022 SSVAL(params,0,dptr_num);
1023 SSVAL(params,2,numentries);
1024 SSVAL(params,4,finished);
1025 SSVAL(params,6,0); /* Never an EA error */
1026 SSVAL(params,8,last_name_off);
1028 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1030 if ((! *directory) && dptr_path(dptr_num))
1031 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1033 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1034 smb_fn_name(CVAL(inbuf,smb_com)),
1035 mask, directory, dirtype, numentries ) );
1038 * Force a name mangle here to ensure that the
1039 * mask as an 8.3 name is top of the mangled cache.
1040 * The reasons for this are subtle. Don't remove
1041 * this code unless you know what you are doing
1042 * (see PR#13758). JRA.
1045 if(!mangle_is_8_3_wildcards( mask, False))
1046 mangle_map(mask, True, True, SNUM(conn));
1048 return(-1);
1051 /****************************************************************************
1052 Reply to a TRANS2_FINDNEXT.
1053 ****************************************************************************/
1055 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1056 char **pparams, int total_params, char **ppdata, int total_data)
1058 /* We must be careful here that we don't return more than the
1059 allowed number of data bytes. If this means returning fewer than
1060 maxentries then so be it. We assume that the redirector has
1061 enough room for the fixed number of parameter bytes it has
1062 requested. */
1063 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1064 char *params = *pparams;
1065 char *pdata = *ppdata;
1066 int dptr_num = SVAL(params,0);
1067 int maxentries = SVAL(params,2);
1068 uint16 info_level = SVAL(params,4);
1069 uint32 resume_key = IVAL(params,6);
1070 BOOL close_after_request = BITSETW(params+10,0);
1071 BOOL close_if_end = BITSETW(params+10,1);
1072 BOOL requires_resume_key = BITSETW(params+10,2);
1073 BOOL continue_bit = BITSETW(params+10,3);
1074 pstring resume_name;
1075 pstring mask;
1076 pstring directory;
1077 char *p;
1078 uint16 dirtype;
1079 int numentries = 0;
1080 int i, last_name_off=0;
1081 BOOL finished = False;
1082 BOOL dont_descend = False;
1083 BOOL out_of_space = False;
1084 int space_remaining;
1086 if (total_params < 12)
1087 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1089 *mask = *directory = *resume_name = 0;
1091 srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE);
1093 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1094 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1095 resume_key = %d resume name = %s continue=%d level = %d\n",
1096 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1097 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1099 switch (info_level) {
1100 case SMB_INFO_STANDARD:
1101 case SMB_INFO_QUERY_EA_SIZE:
1102 case SMB_FIND_FILE_DIRECTORY_INFO:
1103 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1104 case SMB_FIND_FILE_NAMES_INFO:
1105 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1106 break;
1107 case SMB_FIND_FILE_UNIX:
1108 if (!lp_unix_extensions())
1109 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1110 break;
1111 default:
1112 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1115 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1116 if(pdata == NULL)
1117 return ERROR_DOS(ERRDOS,ERRnomem);
1119 *ppdata = pdata;
1120 memset((char *)pdata,'\0',max_data_bytes + 1024);
1122 /* Realloc the params space */
1123 params = Realloc(*pparams, 6*SIZEOFWORD);
1124 if( params == NULL )
1125 return ERROR_DOS(ERRDOS,ERRnomem);
1127 *pparams = params;
1129 /* Check that the dptr is valid */
1130 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1131 return ERROR_DOS(ERRDOS,ERRnofiles);
1133 string_set(&conn->dirpath,dptr_path(dptr_num));
1135 /* Get the wildcard mask from the dptr */
1136 if((p = dptr_wcard(dptr_num))== NULL) {
1137 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1138 return ERROR_DOS(ERRDOS,ERRnofiles);
1141 pstrcpy(mask, p);
1142 pstrcpy(directory,conn->dirpath);
1144 /* Get the attr mask from the dptr */
1145 dirtype = dptr_attr(dptr_num);
1147 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1148 dptr_num, mask, dirtype,
1149 (long)conn->dirptr,
1150 TellDir(conn->dirptr)));
1152 /* We don't need to check for VOL here as this is returned by
1153 a different TRANS2 call. */
1155 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1156 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1157 dont_descend = True;
1159 p = pdata;
1160 space_remaining = max_data_bytes;
1161 out_of_space = False;
1164 * Seek to the correct position. We no longer use the resume key but
1165 * depend on the last file name instead.
1168 if(requires_resume_key && *resume_name && !continue_bit) {
1171 * Fix for NT redirector problem triggered by resume key indexes
1172 * changing between directory scans. We now return a resume key of 0
1173 * and instead look for the filename to continue from (also given
1174 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1175 * findfirst/findnext (as is usual) then the directory pointer
1176 * should already be at the correct place. Check this by scanning
1177 * backwards looking for an exact (ie. case sensitive) filename match.
1178 * If we get to the beginning of the directory and haven't found it then scan
1179 * forwards again looking for a match. JRA.
1182 int current_pos, start_pos;
1183 const char *dname = NULL;
1184 pstring dname_pstring;
1185 void *dirptr = conn->dirptr;
1186 start_pos = TellDir(dirptr);
1187 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1188 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1190 SeekDir(dirptr, current_pos);
1191 dname = ReadDirName(dirptr);
1192 if (dname) {
1194 * Remember, mangle_map is called by
1195 * get_lanman2_dir_entry(), so the resume name
1196 * could be mangled. Ensure we do the same
1197 * here.
1200 /* make sure we get a copy that mangle_map can modify */
1202 pstrcpy(dname_pstring, dname);
1203 mangle_map( dname_pstring, False, True, SNUM(conn));
1205 if(strcsequal( resume_name, dname_pstring)) {
1206 SeekDir(dirptr, current_pos+1);
1207 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1208 break;
1214 * Scan forward from start if not found going backwards.
1217 if(current_pos < 0) {
1218 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1219 SeekDir(dirptr, start_pos);
1220 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1223 * Remember, mangle_map is called by
1224 * get_lanman2_dir_entry(), so the resume name
1225 * could be mangled. Ensure we do the same
1226 * here.
1229 if(dname) {
1230 /* make sure we get a copy that mangle_map can modify */
1232 pstrcpy(dname_pstring, dname);
1233 mangle_map(dname_pstring, False, True, SNUM(conn));
1235 if(strcsequal( resume_name, dname_pstring)) {
1236 SeekDir(dirptr, current_pos+1);
1237 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1238 break;
1241 } /* end for */
1242 } /* end if current_pos */
1243 } /* end if requires_resume_key && !continue_bit */
1245 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1246 BOOL got_exact_match = False;
1248 /* this is a heuristic to avoid seeking the dirptr except when
1249 absolutely necessary. It allows for a filename of about 40 chars */
1250 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1251 out_of_space = True;
1252 finished = False;
1253 } else {
1254 finished = !get_lanman2_dir_entry(conn,
1255 inbuf, outbuf,
1256 mask,dirtype,info_level,
1257 requires_resume_key,dont_descend,
1258 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1259 &last_name_off);
1262 if (finished && out_of_space)
1263 finished = False;
1265 if (!finished && !out_of_space)
1266 numentries++;
1269 * As an optimisation if we know we aren't looking
1270 * for a wildcard name (ie. the name matches the wildcard exactly)
1271 * then we can finish on any (first) match.
1272 * This speeds up large directory searches. JRA.
1275 if(got_exact_match)
1276 finished = True;
1278 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1281 /* Check if we can close the dirptr */
1282 if(close_after_request || (finished && close_if_end)) {
1283 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1284 dptr_close(&dptr_num); /* This frees up the saved mask */
1287 /* Set up the return parameter block */
1288 SSVAL(params,0,numentries);
1289 SSVAL(params,2,finished);
1290 SSVAL(params,4,0); /* Never an EA error */
1291 SSVAL(params,6,last_name_off);
1293 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1295 if ((! *directory) && dptr_path(dptr_num))
1296 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1298 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1299 smb_fn_name(CVAL(inbuf,smb_com)),
1300 mask, directory, dirtype, numentries ) );
1302 return(-1);
1305 /****************************************************************************
1306 Reply to a TRANS2_QFSINFO (query filesystem info).
1307 ****************************************************************************/
1309 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1310 int length, int bufsize,
1311 char **pparams, int total_params, char **ppdata, int total_data)
1313 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1314 char *pdata = *ppdata;
1315 char *params = *pparams;
1316 uint16 info_level = SVAL(params,0);
1317 int data_len, len;
1318 SMB_STRUCT_STAT st;
1319 char *vname = volume_label(SNUM(conn));
1320 int snum = SNUM(conn);
1321 char *fstype = lp_fstype(SNUM(conn));
1322 int quota_flag = 0;
1324 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1326 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1327 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1328 return ERROR_DOS(ERRSRV,ERRinvdevice);
1331 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1332 if ( pdata == NULL )
1333 return ERROR_DOS(ERRDOS,ERRnomem);
1335 *ppdata = pdata;
1336 memset((char *)pdata,'\0',max_data_bytes + 1024);
1338 switch (info_level) {
1339 case SMB_INFO_ALLOCATION:
1341 SMB_BIG_UINT dfree,dsize,bsize;
1342 data_len = 18;
1343 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1344 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1345 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1346 SIVAL(pdata,l1_cUnit,dsize);
1347 SIVAL(pdata,l1_cUnitAvail,dfree);
1348 SSVAL(pdata,l1_cbSector,512);
1349 DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1350 (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1351 (unsigned int)dfree, 512));
1352 break;
1355 case SMB_INFO_VOLUME:
1356 /* Return volume name */
1358 * Add volume serial number - hash of a combination of
1359 * the called hostname and the service name.
1361 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1362 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, 0);
1363 SCVAL(pdata,l2_vol_cch,len);
1364 data_len = l2_vol_szVolLabel + len;
1365 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1366 (unsigned)st.st_ctime, len, vname));
1367 break;
1369 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1370 case SMB_FS_ATTRIBUTE_INFORMATION:
1373 #if defined(HAVE_SYS_QUOTAS)
1374 quota_flag = FILE_VOLUME_QUOTAS;
1375 #endif
1377 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1378 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1379 quota_flag); /* FS ATTRIBUTES */
1381 SIVAL(pdata,4,255); /* Max filename component length */
1382 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1383 and will think we can't do long filenames */
1384 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1385 SIVAL(pdata,8,len);
1386 data_len = 12 + len;
1387 break;
1389 case SMB_QUERY_FS_LABEL_INFO:
1390 case SMB_FS_LABEL_INFORMATION:
1391 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1392 data_len = 4 + len;
1393 SIVAL(pdata,0,len);
1394 break;
1396 case SMB_QUERY_FS_VOLUME_INFO:
1397 case SMB_FS_VOLUME_INFORMATION:
1400 * Add volume serial number - hash of a combination of
1401 * the called hostname and the service name.
1403 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1404 (str_checksum(local_machine)<<16));
1406 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1407 SIVAL(pdata,12,len);
1408 data_len = 18+len;
1409 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1410 (int)strlen(vname),vname, lp_servicename(snum)));
1411 break;
1413 case SMB_QUERY_FS_SIZE_INFO:
1414 case SMB_FS_SIZE_INFORMATION:
1416 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1417 data_len = 24;
1418 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1419 block_size = lp_block_size(snum);
1420 if (bsize < block_size) {
1421 SMB_BIG_UINT factor = block_size/bsize;
1422 bsize = block_size;
1423 dsize /= factor;
1424 dfree /= factor;
1426 if (bsize > block_size) {
1427 SMB_BIG_UINT factor = bsize/block_size;
1428 bsize = block_size;
1429 dsize *= factor;
1430 dfree *= factor;
1432 bytes_per_sector = 512;
1433 sectors_per_unit = bsize/bytes_per_sector;
1434 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1435 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1436 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1437 SBIG_UINT(pdata,0,dsize);
1438 SBIG_UINT(pdata,8,dfree);
1439 SIVAL(pdata,16,sectors_per_unit);
1440 SIVAL(pdata,20,bytes_per_sector);
1441 break;
1444 case SMB_FS_FULL_SIZE_INFORMATION:
1446 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1447 data_len = 32;
1448 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1449 block_size = lp_block_size(snum);
1450 if (bsize < block_size) {
1451 SMB_BIG_UINT factor = block_size/bsize;
1452 bsize = block_size;
1453 dsize /= factor;
1454 dfree /= factor;
1456 if (bsize > block_size) {
1457 SMB_BIG_UINT factor = bsize/block_size;
1458 bsize = block_size;
1459 dsize *= factor;
1460 dfree *= factor;
1462 bytes_per_sector = 512;
1463 sectors_per_unit = bsize/bytes_per_sector;
1464 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1465 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1466 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1467 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1468 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1469 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1470 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1471 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1472 break;
1475 case SMB_QUERY_FS_DEVICE_INFO:
1476 case SMB_FS_DEVICE_INFORMATION:
1477 data_len = 8;
1478 SIVAL(pdata,0,0); /* dev type */
1479 SIVAL(pdata,4,0); /* characteristics */
1480 break;
1482 #ifdef HAVE_SYS_QUOTAS
1483 case SMB_FS_QUOTA_INFORMATION:
1485 * what we have to send --metze:
1487 * Unknown1: 24 NULL bytes
1488 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1489 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
1490 * Quota Flags: 2 byte :
1491 * Unknown3: 6 NULL bytes
1493 * 48 bytes total
1495 * details for Quota Flags:
1497 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1498 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
1499 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1500 * 0x0001 Enable Quotas: enable quota for this fs
1504 /* we need to fake up a fsp here,
1505 * because its not send in this call
1507 files_struct fsp;
1508 SMB_NTQUOTA_STRUCT quotas;
1510 ZERO_STRUCT(fsp);
1511 ZERO_STRUCT(quotas);
1513 fsp.conn = conn;
1514 fsp.fnum = -1;
1515 fsp.fd = -1;
1517 /* access check */
1518 if (conn->admin_user != True) {
1519 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1520 lp_servicename(SNUM(conn)),conn->user));
1521 return ERROR_DOS(ERRDOS,ERRnoaccess);
1524 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
1525 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
1526 return ERROR_DOS(ERRSRV,ERRerror);
1529 data_len = 48;
1531 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
1533 /* Unknown1 24 NULL bytes*/
1534 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
1535 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
1536 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
1538 /* Default Soft Quota 8 bytes */
1539 SBIG_UINT(pdata,24,quotas.softlim);
1541 /* Default Hard Quota 8 bytes */
1542 SBIG_UINT(pdata,32,quotas.hardlim);
1544 /* Quota flag 2 bytes */
1545 SSVAL(pdata,40,quotas.qflags);
1547 /* Unknown3 6 NULL bytes */
1548 SSVAL(pdata,42,0);
1549 SIVAL(pdata,44,0);
1551 break;
1553 #endif /* HAVE_SYS_QUOTAS */
1554 case SMB_FS_OBJECTID_INFORMATION:
1555 data_len = 64;
1556 break;
1559 * Query the version and capabilities of the CIFS UNIX extensions
1560 * in use.
1563 case SMB_QUERY_CIFS_UNIX_INFO:
1564 if (!lp_unix_extensions())
1565 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1566 data_len = 12;
1567 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
1568 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
1569 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
1570 break;
1572 case SMB_MAC_QUERY_FS_INFO:
1574 * Thursby MAC extension... ONLY on NTFS filesystems
1575 * once we do streams then we don't need this
1577 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1578 data_len = 88;
1579 SIVAL(pdata,84,0x100); /* Don't support mac... */
1580 break;
1582 /* drop through */
1583 default:
1584 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1588 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1590 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1592 return -1;
1595 #ifdef HAVE_SYS_QUOTAS
1596 /****************************************************************************
1597 Reply to a TRANS2_SETFSINFO (set filesystem info).
1598 ****************************************************************************/
1600 static int call_trans2setfsinfo(connection_struct *conn,
1601 char *inbuf, char *outbuf, int length, int bufsize,
1602 char **pparams, int total_params, char **ppdata, int total_data)
1604 char *pdata = *ppdata;
1605 char *params = *pparams;
1606 files_struct *fsp = NULL;
1607 uint16 info_level;
1608 int outsize;
1609 SMB_NTQUOTA_STRUCT quotas;
1611 ZERO_STRUCT(quotas);
1613 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
1615 /* access check */
1616 if ((conn->admin_user != True)||!CAN_WRITE(conn)) {
1617 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1618 lp_servicename(SNUM(conn)),conn->user));
1619 return ERROR_DOS(ERRSRV,ERRaccess);
1622 /* */
1623 if (total_params < 4) {
1624 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
1625 total_params));
1626 return ERROR_DOS(ERRDOS,ERRinvalidparam);
1629 fsp = file_fsp(params,0);
1631 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
1632 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
1633 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
1636 info_level = SVAL(params,2);
1638 switch(info_level) {
1639 case SMB_FS_QUOTA_INFORMATION:
1640 /* note: normaly there're 48 bytes,
1641 * but we didn't use the last 6 bytes for now
1642 * --metze
1644 if (total_data < 42) {
1645 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
1646 total_data));
1647 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1650 /* unknown_1 24 NULL bytes in pdata*/
1652 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
1653 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
1654 #ifdef LARGE_SMB_OFF_T
1655 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
1656 #else /* LARGE_SMB_OFF_T */
1657 if ((IVAL(pdata,28) != 0)&&
1658 ((quotas.softlim != 0xFFFFFFFF)||
1659 (IVAL(pdata,28)!=0xFFFFFFFF))) {
1660 /* more than 32 bits? */
1661 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1663 #endif /* LARGE_SMB_OFF_T */
1665 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
1666 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
1667 #ifdef LARGE_SMB_OFF_T
1668 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
1669 #else /* LARGE_SMB_OFF_T */
1670 if ((IVAL(pdata,36) != 0)&&
1671 ((quotas.hardlim != 0xFFFFFFFF)||
1672 (IVAL(pdata,36)!=0xFFFFFFFF))) {
1673 /* more than 32 bits? */
1674 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1676 #endif /* LARGE_SMB_OFF_T */
1678 /* quota_flags 2 bytes **/
1679 quotas.qflags = SVAL(pdata,40);
1681 /* unknown_2 6 NULL bytes follow*/
1683 /* now set the quotas */
1684 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
1685 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
1686 return ERROR_DOS(ERRSRV,ERRerror);
1689 break;
1690 default:
1691 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
1692 info_level));
1693 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1694 break;
1698 * sending this reply works fine,
1699 * but I'm not sure it's the same
1700 * like windows do...
1701 * --metze
1703 outsize = set_message(outbuf,10,0,True);
1705 return outsize;
1707 #endif /* HAVE_SYS_QUOTAS */
1709 /****************************************************************************
1710 * Utility function to set bad path error.
1711 ****************************************************************************/
1713 NTSTATUS set_bad_path_error(int err, BOOL bad_path)
1715 if((err == ENOENT) && bad_path) {
1716 unix_ERR_class = ERRDOS;
1717 unix_ERR_code = ERRbadpath;
1718 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1720 return NT_STATUS_OK;
1723 /****************************************************************************
1724 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1725 file name or file id).
1726 ****************************************************************************/
1728 static int call_trans2qfilepathinfo(connection_struct *conn,
1729 char *inbuf, char *outbuf, int length,
1730 int bufsize,
1731 char **pparams, int total_params, char **ppdata, int total_data)
1733 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1734 char *params = *pparams;
1735 char *pdata = *ppdata;
1736 uint16 tran_call = SVAL(inbuf, smb_setup0);
1737 uint16 info_level;
1738 int mode=0;
1739 SMB_OFF_T file_size=0;
1740 SMB_BIG_UINT allocation_size=0;
1741 unsigned int data_size;
1742 SMB_STRUCT_STAT sbuf;
1743 pstring fname, dos_fname;
1744 char *fullpathname;
1745 char *base_name;
1746 char *p;
1747 SMB_OFF_T pos = 0;
1748 BOOL bad_path = False;
1749 BOOL delete_pending = False;
1750 int len;
1751 time_t c_time;
1752 files_struct *fsp = NULL;
1754 if (!params)
1755 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1757 if (tran_call == TRANSACT2_QFILEINFO) {
1758 if (total_params < 4)
1759 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1761 fsp = file_fsp(params,0);
1762 info_level = SVAL(params,2);
1764 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1766 if(fsp && (fsp->fake_file_handle)) {
1768 * This is actually for the QUOTA_FAKE_FILE --metze
1771 pstrcpy(fname, fsp->fsp_name);
1772 unix_convert(fname,conn,0,&bad_path,&sbuf);
1773 if (!check_name(fname,conn)) {
1774 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno)));
1775 set_bad_path_error(errno, bad_path);
1776 return(UNIXERROR(ERRDOS,ERRbadpath));
1779 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1781 * This is actually a QFILEINFO on a directory
1782 * handle (returned from an NT SMB). NT5.0 seems
1783 * to do this call. JRA.
1785 pstrcpy(fname, fsp->fsp_name);
1786 unix_convert(fname,conn,0,&bad_path,&sbuf);
1787 if (!check_name(fname,conn)) {
1788 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1789 set_bad_path_error(errno, bad_path);
1790 return(UNIXERROR(ERRDOS,ERRbadpath));
1793 if (INFO_LEVEL_IS_UNIX(info_level)) {
1794 /* Always do lstat for UNIX calls. */
1795 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
1796 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
1797 set_bad_path_error(errno, bad_path);
1798 return(UNIXERROR(ERRDOS,ERRbadpath));
1800 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
1801 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
1802 set_bad_path_error(errno, bad_path);
1803 return(UNIXERROR(ERRDOS,ERRbadpath));
1806 delete_pending = fsp->directory_delete_on_close;
1807 } else {
1809 * Original code - this is an open file.
1811 CHECK_FSP(fsp,conn);
1813 pstrcpy(fname, fsp->fsp_name);
1814 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
1815 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
1816 return(UNIXERROR(ERRDOS,ERRbadfid));
1818 if((pos = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1819 return(UNIXERROR(ERRDOS,ERRnoaccess));
1821 delete_pending = fsp->delete_on_close;
1823 } else {
1824 /* qpathinfo */
1825 if (total_params < 6)
1826 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1828 info_level = SVAL(params,0);
1830 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1832 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
1834 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1836 unix_convert(fname,conn,0,&bad_path,&sbuf);
1837 if (!check_name(fname,conn)) {
1838 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1839 set_bad_path_error(errno, bad_path);
1840 return(UNIXERROR(ERRDOS,ERRbadpath));
1843 if (INFO_LEVEL_IS_UNIX(info_level)) {
1844 /* Always do lstat for UNIX calls. */
1845 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
1846 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
1847 set_bad_path_error(errno, bad_path);
1848 return(UNIXERROR(ERRDOS,ERRbadpath));
1850 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
1851 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
1852 set_bad_path_error(errno, bad_path);
1853 return(UNIXERROR(ERRDOS,ERRbadpath));
1857 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
1858 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1860 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1861 fname,info_level,tran_call,total_data));
1863 p = strrchr_m(fname,'/');
1864 if (!p)
1865 base_name = fname;
1866 else
1867 base_name = p+1;
1869 mode = dos_mode(conn,fname,&sbuf);
1870 fullpathname = fname;
1871 file_size = get_file_size(sbuf);
1872 allocation_size = get_allocation_size(fsp,&sbuf);
1873 if (mode & aDIR)
1874 file_size = 0;
1876 params = Realloc(*pparams,2);
1877 if (params == NULL)
1878 return ERROR_DOS(ERRDOS,ERRnomem);
1879 *pparams = params;
1880 memset((char *)params,'\0',2);
1881 data_size = max_data_bytes + 1024;
1882 pdata = Realloc(*ppdata, data_size);
1883 if ( pdata == NULL )
1884 return ERROR_DOS(ERRDOS,ERRnomem);
1885 *ppdata = pdata;
1887 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1888 /* uggh, EAs for OS2 */
1889 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1890 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1893 memset((char *)pdata,'\0',data_size);
1895 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1897 if (lp_dos_filetime_resolution(SNUM(conn))) {
1898 c_time &= ~1;
1899 sbuf.st_atime &= ~1;
1900 sbuf.st_mtime &= ~1;
1901 sbuf.st_mtime &= ~1;
1904 /* NT expects the name to be in an exact form of the *full*
1905 filename. See the trans2 torture test */
1906 if (strequal(base_name,".")) {
1907 pstrcpy(dos_fname, "\\");
1908 } else {
1909 snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname);
1910 string_replace(dos_fname, '/', '\\');
1913 switch (info_level) {
1914 case SMB_INFO_STANDARD:
1915 case SMB_INFO_QUERY_EA_SIZE:
1916 data_size = (info_level==1?22:26);
1917 put_dos_date2(pdata,l1_fdateCreation,c_time);
1918 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1919 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1920 SIVAL(pdata,l1_cbFile,(uint32)file_size);
1921 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
1922 SSVAL(pdata,l1_attrFile,mode);
1923 SIVAL(pdata,l1_attrFile+2,0); /* this is what win2003 does */
1924 break;
1926 case SMB_INFO_IS_NAME_VALID:
1927 if (tran_call == TRANSACT2_QFILEINFO) {
1928 /* os/2 needs this ? really ?*/
1929 return ERROR_DOS(ERRDOS,ERRbadfunc);
1931 data_size = 0;
1932 break;
1934 case SMB_INFO_QUERY_EAS_FROM_LIST:
1935 data_size = 24;
1936 put_dos_date2(pdata,0,c_time);
1937 put_dos_date2(pdata,4,sbuf.st_atime);
1938 put_dos_date2(pdata,8,sbuf.st_mtime);
1939 SIVAL(pdata,12,(uint32)file_size);
1940 SIVAL(pdata,16,(uint32)allocation_size);
1941 SIVAL(pdata,20,mode);
1942 break;
1944 case SMB_INFO_QUERY_ALL_EAS:
1945 data_size = 4;
1946 SIVAL(pdata,0,0); /* ea size */
1947 break;
1949 case SMB_FILE_BASIC_INFORMATION:
1950 case SMB_QUERY_FILE_BASIC_INFO:
1952 if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1953 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1954 else {
1955 data_size = 40;
1956 SIVAL(pdata,36,0);
1958 put_long_date(pdata,c_time);
1959 put_long_date(pdata+8,sbuf.st_atime);
1960 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1961 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1962 SIVAL(pdata,32,mode);
1964 DEBUG(5,("SMB_QFBI - "));
1966 time_t create_time = c_time;
1967 DEBUG(5,("create: %s ", ctime(&create_time)));
1969 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1970 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1971 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1972 DEBUG(5,("mode: %x\n", mode));
1974 break;
1976 case SMB_FILE_STANDARD_INFORMATION:
1977 case SMB_QUERY_FILE_STANDARD_INFO:
1979 data_size = 24;
1980 SOFF_T(pdata,0,allocation_size);
1981 SOFF_T(pdata,8,file_size);
1982 SIVAL(pdata,16,sbuf.st_nlink);
1983 SCVAL(pdata,20,0);
1984 SCVAL(pdata,21,(mode&aDIR)?1:0);
1985 break;
1987 case SMB_FILE_EA_INFORMATION:
1988 case SMB_QUERY_FILE_EA_INFO:
1989 data_size = 4;
1990 break;
1992 /* Get the 8.3 name - used if NT SMB was negotiated. */
1993 case SMB_QUERY_FILE_ALT_NAME_INFO:
1994 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
1996 pstring short_name;
1998 pstrcpy(short_name,base_name);
1999 /* Mangle if not already 8.3 */
2000 if(!mangle_is_8_3(short_name, True)) {
2001 mangle_map(short_name,True,True,SNUM(conn));
2003 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2004 data_size = 4 + len;
2005 SIVAL(pdata,0,len);
2006 break;
2009 case SMB_QUERY_FILE_NAME_INFO:
2011 this must be *exactly* right for ACLs on mapped drives to work
2013 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2014 data_size = 4 + len;
2015 SIVAL(pdata,0,len);
2016 break;
2018 case SMB_FILE_ALLOCATION_INFORMATION:
2019 case SMB_QUERY_FILE_ALLOCATION_INFO:
2020 data_size = 8;
2021 SOFF_T(pdata,0,allocation_size);
2022 break;
2024 case SMB_FILE_END_OF_FILE_INFORMATION:
2025 case SMB_QUERY_FILE_END_OF_FILEINFO:
2026 data_size = 8;
2027 SOFF_T(pdata,0,file_size);
2028 break;
2030 case SMB_QUERY_FILE_ALL_INFO:
2031 case SMB_FILE_ALL_INFORMATION:
2032 put_long_date(pdata,c_time);
2033 put_long_date(pdata+8,sbuf.st_atime);
2034 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2035 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2036 SIVAL(pdata,32,mode);
2037 pdata += 40;
2038 SOFF_T(pdata,0,allocation_size);
2039 SOFF_T(pdata,8,file_size);
2040 SIVAL(pdata,16,sbuf.st_nlink);
2041 SCVAL(pdata,20,delete_pending);
2042 SCVAL(pdata,21,(mode&aDIR)?1:0);
2043 pdata += 24;
2044 pdata += 4; /* EA info */
2045 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2046 SIVAL(pdata,0,len);
2047 pdata += 4 + len;
2048 data_size = PTR_DIFF(pdata,(*ppdata));
2049 break;
2051 case SMB_FILE_INTERNAL_INFORMATION:
2052 /* This should be an index number - looks like
2053 dev/ino to me :-)
2055 I think this causes us to fail the IFSKIT
2056 BasicFileInformationTest. -tpot */
2058 SIVAL(pdata,0,sbuf.st_dev);
2059 SIVAL(pdata,4,sbuf.st_ino);
2060 data_size = 8;
2061 break;
2063 case SMB_FILE_ACCESS_INFORMATION:
2064 SIVAL(pdata,0,0x12019F); /* ??? */
2065 data_size = 4;
2066 break;
2068 case SMB_FILE_NAME_INFORMATION:
2069 /* Pathname with leading '\'. */
2071 size_t byte_len;
2072 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2073 SIVAL(pdata,0,byte_len);
2074 data_size = 4 + byte_len;
2075 break;
2078 case SMB_FILE_DISPOSITION_INFORMATION:
2079 data_size = 1;
2080 SCVAL(pdata,0,delete_pending);
2081 break;
2083 case SMB_FILE_POSITION_INFORMATION:
2084 data_size = 8;
2085 SOFF_T(pdata,0,pos);
2086 break;
2088 case SMB_FILE_MODE_INFORMATION:
2089 SIVAL(pdata,0,mode);
2090 data_size = 4;
2091 break;
2093 case SMB_FILE_ALIGNMENT_INFORMATION:
2094 SIVAL(pdata,0,0); /* No alignment needed. */
2095 data_size = 4;
2096 break;
2098 #if 0
2100 * NT4 server just returns "invalid query" to this - if we try to answer
2101 * it then NTws gets a BSOD! (tridge).
2102 * W2K seems to want this. JRA.
2104 case SMB_QUERY_FILE_STREAM_INFO:
2105 #endif
2106 case SMB_FILE_STREAM_INFORMATION:
2107 if (mode & aDIR) {
2108 data_size = 0;
2109 } else {
2110 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2111 SIVAL(pdata,0,0); /* ??? */
2112 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2113 SOFF_T(pdata,8,file_size);
2114 SIVAL(pdata,16,allocation_size);
2115 SIVAL(pdata,20,0); /* ??? */
2116 data_size = 24 + byte_len;
2118 break;
2120 case SMB_QUERY_COMPRESSION_INFO:
2121 case SMB_FILE_COMPRESSION_INFORMATION:
2122 SOFF_T(pdata,0,file_size);
2123 SIVAL(pdata,8,0); /* ??? */
2124 SIVAL(pdata,12,0); /* ??? */
2125 data_size = 16;
2126 break;
2128 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2129 put_long_date(pdata,c_time);
2130 put_long_date(pdata+8,sbuf.st_atime);
2131 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2132 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2133 SIVAL(pdata,32,allocation_size);
2134 SOFF_T(pdata,40,file_size);
2135 SIVAL(pdata,48,mode);
2136 SIVAL(pdata,52,0); /* ??? */
2137 data_size = 56;
2138 break;
2140 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2141 SIVAL(pdata,0,mode);
2142 SIVAL(pdata,4,0);
2143 data_size = 8;
2144 break;
2147 * CIFS UNIX Extensions.
2150 case SMB_QUERY_FILE_UNIX_BASIC:
2152 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2154 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2155 pdata += 8;
2157 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2158 pdata += 8;
2160 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2161 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2162 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2163 pdata += 24;
2165 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2166 SIVAL(pdata,4,0);
2167 pdata += 8;
2169 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2170 SIVAL(pdata,4,0);
2171 pdata += 8;
2173 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2174 pdata += 4;
2176 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2177 SIVAL(pdata,4,0);
2178 pdata += 8;
2180 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2181 SIVAL(pdata,4,0);
2182 pdata += 8;
2184 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2185 pdata += 8;
2187 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2188 SIVAL(pdata,4,0);
2189 pdata += 8;
2191 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2192 SIVAL(pdata,4,0);
2193 pdata += 8+1;
2194 data_size = PTR_DIFF(pdata,(*ppdata));
2197 int i;
2198 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2200 for (i=0; i<100; i++)
2201 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2202 DEBUG(4,("\n"));
2205 break;
2207 case SMB_QUERY_FILE_UNIX_LINK:
2209 pstring buffer;
2211 #ifdef S_ISLNK
2212 if(!S_ISLNK(sbuf.st_mode))
2213 return(UNIXERROR(ERRSRV,ERRbadlink));
2214 #else
2215 return(UNIXERROR(ERRDOS,ERRbadlink));
2216 #endif
2217 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2218 if (len == -1)
2219 return(UNIXERROR(ERRDOS,ERRnoaccess));
2220 buffer[len] = 0;
2221 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2222 pdata += len;
2223 data_size = PTR_DIFF(pdata,(*ppdata));
2225 break;
2228 default:
2229 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2232 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size);
2234 return(-1);
2237 /****************************************************************************
2238 Deal with the internal needs of setting the delete on close flag. Note that
2239 as the tdb locking is recursive, it is safe to call this from within
2240 open_file_shared. JRA.
2241 ****************************************************************************/
2243 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2246 * Only allow delete on close for writable shares.
2249 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2250 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2251 fsp->fsp_name ));
2252 return NT_STATUS_ACCESS_DENIED;
2255 * Only allow delete on close for files/directories opened with delete intent.
2258 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2259 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2260 fsp->fsp_name ));
2261 return NT_STATUS_ACCESS_DENIED;
2264 if(fsp->is_directory) {
2265 fsp->directory_delete_on_close = delete_on_close;
2266 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2267 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2268 } else {
2269 fsp->delete_on_close = delete_on_close;
2270 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2271 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2274 return NT_STATUS_OK;
2277 /****************************************************************************
2278 Sets the delete on close flag over all share modes on this file.
2279 Modify the share mode entry for all files open
2280 on this device and inode to tell other smbds we have
2281 changed the delete on close flag. This will be noticed
2282 in the close code, the last closer will delete the file
2283 if flag is set.
2284 ****************************************************************************/
2286 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2288 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2289 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2291 if (fsp->is_directory || fsp->is_stat)
2292 return NT_STATUS_OK;
2294 if (lock_share_entry_fsp(fsp) == False)
2295 return NT_STATUS_ACCESS_DENIED;
2297 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2298 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2299 fsp->fsp_name ));
2300 unlock_share_entry_fsp(fsp);
2301 return NT_STATUS_ACCESS_DENIED;
2304 unlock_share_entry_fsp(fsp);
2305 return NT_STATUS_OK;
2308 /****************************************************************************
2309 Returns true if this pathname is within the share, and thus safe.
2310 ****************************************************************************/
2312 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2314 #ifdef PATH_MAX
2315 char resolved_name[PATH_MAX+1];
2316 #else
2317 pstring resolved_name;
2318 #endif
2319 fstring last_component;
2320 pstring link_dest;
2321 pstring link_test;
2322 char *p;
2323 BOOL bad_path = False;
2324 SMB_STRUCT_STAT sbuf;
2326 pstrcpy(link_dest, link_dest_in);
2327 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2329 /* Store the UNIX converted path. */
2330 pstrcpy(link_dest_out, link_dest);
2332 p = strrchr(link_dest, '/');
2333 if (p) {
2334 fstrcpy(last_component, p+1);
2335 *p = '\0';
2336 } else {
2337 fstrcpy(last_component, link_dest);
2338 pstrcpy(link_dest, "./");
2341 if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL)
2342 return -1;
2344 pstrcpy(link_dest, resolved_name);
2345 pstrcat(link_dest, "/");
2346 pstrcat(link_dest, last_component);
2348 if (*link_dest != '/') {
2349 /* Relative path. */
2350 pstrcpy(link_test, conn->connectpath);
2351 pstrcat(link_test, "/");
2352 pstrcat(link_test, link_dest);
2353 } else {
2354 pstrcpy(link_test, link_dest);
2358 * Check if the link is within the share.
2361 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2362 errno = EACCES;
2363 return -1;
2365 return 0;
2368 /****************************************************************************
2369 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2370 ****************************************************************************/
2372 static int call_trans2setfilepathinfo(connection_struct *conn,
2373 char *inbuf, char *outbuf, int length, int bufsize,
2374 char **pparams, int total_params, char **ppdata, int total_data)
2376 char *params = *pparams;
2377 char *pdata = *ppdata;
2378 uint16 tran_call = SVAL(inbuf, smb_setup0);
2379 uint16 info_level;
2380 int dosmode=0;
2381 SMB_OFF_T size=0;
2382 struct utimbuf tvs;
2383 SMB_STRUCT_STAT sbuf;
2384 pstring fname;
2385 int fd = -1;
2386 BOOL bad_path = False;
2387 files_struct *fsp = NULL;
2388 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2389 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2390 mode_t unixmode = 0;
2392 if (!params)
2393 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2395 if (tran_call == TRANSACT2_SETFILEINFO) {
2396 if (total_params < 4)
2397 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2399 fsp = file_fsp(params,0);
2400 info_level = SVAL(params,2);
2402 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2404 * This is actually a SETFILEINFO on a directory
2405 * handle (returned from an NT SMB). NT5.0 seems
2406 * to do this call. JRA.
2408 pstrcpy(fname, fsp->fsp_name);
2409 unix_convert(fname,conn,0,&bad_path,&sbuf);
2410 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2411 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2412 set_bad_path_error(errno, bad_path);
2413 return(UNIXERROR(ERRDOS,ERRbadpath));
2415 } else if (fsp && fsp->print_file) {
2417 * Doing a DELETE_ON_CLOSE should cancel a print job.
2419 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
2420 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2422 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
2424 SSVAL(params,0,0);
2425 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2426 return(-1);
2427 } else
2428 return (UNIXERROR(ERRDOS,ERRbadpath));
2429 } else {
2431 * Original code - this is an open file.
2433 CHECK_FSP(fsp,conn);
2435 pstrcpy(fname, fsp->fsp_name);
2436 fd = fsp->fd;
2438 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
2439 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2440 return(UNIXERROR(ERRDOS,ERRbadfid));
2443 } else {
2444 /* set path info */
2445 if (total_params < 6)
2446 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2448 info_level = SVAL(params,0);
2449 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
2450 unix_convert(fname,conn,0,&bad_path,&sbuf);
2451 if(!check_name(fname, conn)) {
2452 set_bad_path_error(errno, bad_path);
2453 return(UNIXERROR(ERRDOS,ERRbadpath));
2457 * For CIFS UNIX extensions the target name may not exist.
2460 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2461 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
2462 set_bad_path_error(errno, bad_path);
2463 return(UNIXERROR(ERRDOS,ERRbadpath));
2467 if (!CAN_WRITE(conn))
2468 return ERROR_DOS(ERRSRV,ERRaccess);
2470 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2471 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2473 if (VALID_STAT(sbuf))
2474 unixmode = sbuf.st_mode;
2476 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
2477 tran_call,fname,info_level,total_data));
2479 /* Realloc the parameter and data sizes */
2480 params = Realloc(*pparams,2);
2481 if(params == NULL)
2482 return ERROR_DOS(ERRDOS,ERRnomem);
2483 *pparams = params;
2485 SSVAL(params,0,0);
2487 if (fsp) {
2488 /* the pending modtime overrides the current modtime */
2489 sbuf.st_mtime = fsp->pending_modtime;
2492 size = get_file_size(sbuf);
2493 tvs.modtime = sbuf.st_mtime;
2494 tvs.actime = sbuf.st_atime;
2495 dosmode = dos_mode(conn,fname,&sbuf);
2496 unixmode = sbuf.st_mode;
2498 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2499 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2501 switch (info_level) {
2502 case SMB_INFO_STANDARD:
2504 if (total_data < l1_cbFile+4)
2505 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2507 /* access time */
2508 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2510 /* write time */
2511 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2513 dosmode = SVAL(pdata,l1_attrFile);
2514 size = IVAL(pdata,l1_cbFile);
2516 break;
2519 case SMB_INFO_SET_EA:
2520 return(ERROR_DOS(ERRDOS,ERReasnotsupported));
2522 /* XXXX um, i don't think this is right.
2523 it's also not in the cifs6.txt spec.
2525 case SMB_INFO_QUERY_EAS_FROM_LIST:
2526 if (total_data < 28)
2527 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2529 tvs.actime = make_unix_date2(pdata+8);
2530 tvs.modtime = make_unix_date2(pdata+12);
2531 size = IVAL(pdata,16);
2532 dosmode = IVAL(pdata,24);
2533 break;
2535 /* XXXX nor this. not in cifs6.txt, either. */
2536 case SMB_INFO_QUERY_ALL_EAS:
2537 if (total_data < 28)
2538 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2540 tvs.actime = make_unix_date2(pdata+8);
2541 tvs.modtime = make_unix_date2(pdata+12);
2542 size = IVAL(pdata,16);
2543 dosmode = IVAL(pdata,24);
2544 break;
2546 case SMB_SET_FILE_BASIC_INFO:
2547 case SMB_FILE_BASIC_INFORMATION:
2549 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2550 time_t write_time;
2551 time_t changed_time;
2553 if (total_data < 36)
2554 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2556 /* Ignore create time at offset pdata. */
2558 /* access time */
2559 tvs.actime = interpret_long_date(pdata+8);
2561 write_time = interpret_long_date(pdata+16);
2562 changed_time = interpret_long_date(pdata+24);
2564 tvs.modtime = MIN(write_time, changed_time);
2566 if (write_time > tvs.modtime && write_time != 0xffffffff) {
2567 tvs.modtime = write_time;
2569 /* Prefer a defined time to an undefined one. */
2570 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2571 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2572 ? changed_time : write_time);
2574 /* attributes */
2575 dosmode = IVAL(pdata,32);
2576 break;
2579 case SMB_FILE_ALLOCATION_INFORMATION:
2580 case SMB_SET_FILE_ALLOCATION_INFO:
2582 int ret = -1;
2583 SMB_BIG_UINT allocation_size;
2585 if (total_data < 8)
2586 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2588 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
2589 #ifdef LARGE_SMB_OFF_T
2590 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
2591 #else /* LARGE_SMB_OFF_T */
2592 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2593 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2594 #endif /* LARGE_SMB_OFF_T */
2595 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2596 fname, (double)allocation_size ));
2598 if (allocation_size)
2599 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
2601 if(allocation_size != get_file_size(sbuf)) {
2602 SMB_STRUCT_STAT new_sbuf;
2604 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2605 fname, (double)allocation_size ));
2607 if (fd == -1) {
2608 files_struct *new_fsp = NULL;
2609 int access_mode = 0;
2610 int action = 0;
2612 if(global_oplock_break) {
2613 /* Queue this file modify as we are the process of an oplock break. */
2615 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2616 DEBUGADD(2,( "in oplock break state.\n"));
2618 push_oplock_pending_smb_message(inbuf, length);
2619 return -1;
2622 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2623 SET_OPEN_MODE(DOS_OPEN_RDWR),
2624 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2625 0, 0, &access_mode, &action);
2627 if (new_fsp == NULL)
2628 return(UNIXERROR(ERRDOS,ERRbadpath));
2629 ret = vfs_allocate_file_space(new_fsp, allocation_size);
2630 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2631 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2632 new_fsp->fnum, strerror(errno)));
2633 ret = -1;
2635 close_file(new_fsp,True);
2636 } else {
2637 ret = vfs_allocate_file_space(fsp, allocation_size);
2638 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
2639 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2640 fsp->fnum, strerror(errno)));
2641 ret = -1;
2644 if (ret == -1)
2645 return ERROR_NT(NT_STATUS_DISK_FULL);
2647 /* Allocate can truncate size... */
2648 size = get_file_size(new_sbuf);
2651 break;
2654 case SMB_FILE_END_OF_FILE_INFORMATION:
2655 case SMB_SET_FILE_END_OF_FILE_INFO:
2657 if (total_data < 8)
2658 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2660 size = IVAL(pdata,0);
2661 #ifdef LARGE_SMB_OFF_T
2662 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2663 #else /* LARGE_SMB_OFF_T */
2664 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2665 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2666 #endif /* LARGE_SMB_OFF_T */
2667 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2668 break;
2671 case SMB_FILE_DISPOSITION_INFORMATION:
2672 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2674 BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
2675 NTSTATUS status;
2677 if (total_data < 1)
2678 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2680 if (tran_call != TRANSACT2_SETFILEINFO)
2681 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2683 if (fsp == NULL)
2684 return(UNIXERROR(ERRDOS,ERRbadfid));
2686 status = set_delete_on_close_internal(fsp, delete_on_close);
2688 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2689 return ERROR_NT(status);
2691 /* The set is across all open files on this dev/inode pair. */
2692 status =set_delete_on_close_over_all(fsp, delete_on_close);
2693 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2694 return ERROR_NT(status);
2696 break;
2700 * CIFS UNIX extensions.
2703 case SMB_SET_FILE_UNIX_BASIC:
2705 uint32 raw_unixmode;
2707 if (total_data < 100)
2708 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2710 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
2711 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
2712 size=IVAL(pdata,0); /* first 8 Bytes are size */
2713 #ifdef LARGE_SMB_OFF_T
2714 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2715 #else /* LARGE_SMB_OFF_T */
2716 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2717 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2718 #endif /* LARGE_SMB_OFF_T */
2720 pdata+=24; /* ctime & st_blocks are not changed */
2721 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
2722 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
2723 pdata+=16;
2724 set_owner = (uid_t)IVAL(pdata,0);
2725 pdata += 8;
2726 set_grp = (gid_t)IVAL(pdata,0);
2727 pdata += 8;
2728 raw_unixmode = IVAL(pdata,28);
2729 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2730 dosmode = 0; /* Ensure dos mode change doesn't override this. */
2732 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2733 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2734 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2736 if (!VALID_STAT(sbuf)) {
2739 * The only valid use of this is to create character and block
2740 * devices, and named pipes. This is deprecated (IMHO) and
2741 * a new info level should be used for mknod. JRA.
2744 #if !defined(HAVE_MAKEDEV_FN)
2745 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2746 #else /* HAVE_MAKEDEV_FN */
2747 uint32 file_type = IVAL(pdata,0);
2748 uint32 dev_major = IVAL(pdata,4);
2749 uint32 dev_minor = IVAL(pdata,12);
2751 uid_t myuid = geteuid();
2752 gid_t mygid = getegid();
2753 SMB_DEV_T dev;
2755 if (tran_call == TRANSACT2_SETFILEINFO)
2756 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2758 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2759 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2761 dev = makedev(dev_major, dev_minor);
2763 /* We can only create as the owner/group we are. */
2765 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2766 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2767 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2768 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2770 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2771 file_type != UNIX_TYPE_FIFO)
2772 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2774 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2775 0%o for file %s\n", (double)dev, unixmode, fname ));
2777 /* Ok - do the mknod. */
2778 if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
2779 return(UNIXERROR(ERRDOS,ERRnoaccess));
2781 inherit_access_acl(conn, fname, unixmode);
2783 SSVAL(params,0,0);
2784 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2785 return(-1);
2786 #endif /* HAVE_MAKEDEV_FN */
2791 * Deal with the UNIX specific mode set.
2794 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
2795 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2796 (unsigned int)unixmode, fname ));
2797 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
2798 return(UNIXERROR(ERRDOS,ERRnoaccess));
2802 * Deal with the UNIX specific uid set.
2805 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
2806 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2807 (unsigned int)set_owner, fname ));
2808 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
2809 return(UNIXERROR(ERRDOS,ERRnoaccess));
2813 * Deal with the UNIX specific gid set.
2816 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
2817 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2818 (unsigned int)set_owner, fname ));
2819 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
2820 return(UNIXERROR(ERRDOS,ERRnoaccess));
2822 break;
2825 case SMB_SET_FILE_UNIX_LINK:
2827 pstring link_dest;
2828 /* Set a symbolic link. */
2829 /* Don't allow this if follow links is false. */
2831 if (!lp_symlinks(SNUM(conn)))
2832 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2834 /* Disallow if already exists. */
2835 if (VALID_STAT(sbuf))
2836 return(ERROR_DOS(ERRDOS,ERRbadpath));
2838 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2840 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2841 return(UNIXERROR(ERRDOS,ERRnoaccess));
2843 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2844 fname, link_dest ));
2846 if (SMB_VFS_SYMLINK(conn,link_dest,fname) != 0)
2847 return(UNIXERROR(ERRDOS,ERRnoaccess));
2848 SSVAL(params,0,0);
2849 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2850 return(-1);
2853 case SMB_SET_FILE_UNIX_HLINK:
2855 pstring link_dest;
2857 /* Set a hard link. */
2859 /* Disallow if already exists. */
2860 if (VALID_STAT(sbuf))
2861 return(ERROR_DOS(ERRDOS,ERRbadpath));
2863 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2865 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2866 return(UNIXERROR(ERRDOS,ERRnoaccess));
2868 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2869 fname, link_dest ));
2871 if (SMB_VFS_LINK(conn,link_dest,fname) != 0)
2872 return(UNIXERROR(ERRDOS,ERRnoaccess));
2873 SSVAL(params,0,0);
2874 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2875 return(-1);
2878 default:
2879 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2882 /* get some defaults (no modifications) if any info is zero or -1. */
2883 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2884 tvs.actime = sbuf.st_atime;
2886 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2887 tvs.modtime = sbuf.st_mtime;
2889 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2890 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2891 DEBUG(6,("size: %.0f ", (double)size));
2893 if (S_ISDIR(sbuf.st_mode))
2894 dosmode |= aDIR;
2895 else
2896 dosmode &= ~aDIR;
2898 DEBUG(6,("dosmode: %x\n" , dosmode));
2900 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2901 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2902 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2903 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2906 * Only do this test if we are not explicitly
2907 * changing the size of a file.
2909 if (!size)
2910 size = get_file_size(sbuf);
2914 * Try and set the times, size and mode of this file -
2915 * if they are different from the current values
2917 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2918 if(fsp != NULL) {
2920 * This was a setfileinfo on an open file.
2921 * NT does this a lot. It's actually pointless
2922 * setting the time here, as it will be overwritten
2923 * on the next write, so we save the request
2924 * away and will set it on file close. JRA.
2927 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2928 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
2929 fsp->pending_modtime = tvs.modtime;
2932 } else {
2934 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2936 if(file_utime(conn, fname, &tvs)!=0)
2937 return(UNIXERROR(ERRDOS,ERRnoaccess));
2941 /* check the mode isn't different, before changing it */
2942 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
2944 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
2946 if(file_chmod(conn, fname, dosmode, NULL)) {
2947 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2948 return(UNIXERROR(ERRDOS,ERRnoaccess));
2952 if (size != get_file_size(sbuf)) {
2954 int ret;
2956 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2957 fname, (double)size ));
2959 if (fd == -1) {
2960 files_struct *new_fsp = NULL;
2961 int access_mode = 0;
2962 int action = 0;
2964 if(global_oplock_break) {
2965 /* Queue this file modify as we are the process of an oplock break. */
2967 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2968 DEBUGADD(2,( "in oplock break state.\n"));
2970 push_oplock_pending_smb_message(inbuf, length);
2971 return -1;
2974 new_fsp = open_file_shared(conn, fname, &sbuf,
2975 SET_OPEN_MODE(DOS_OPEN_RDWR),
2976 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2977 0, 0, &access_mode, &action);
2979 if (new_fsp == NULL)
2980 return(UNIXERROR(ERRDOS,ERRbadpath));
2981 ret = vfs_set_filelen(new_fsp, size);
2982 close_file(new_fsp,True);
2983 } else {
2984 ret = vfs_set_filelen(fsp, size);
2987 if (ret == -1)
2988 return (UNIXERROR(ERRHRD,ERRdiskfull));
2991 SSVAL(params,0,0);
2992 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2994 return(-1);
2997 /****************************************************************************
2998 Reply to a TRANS2_MKDIR (make directory with extended attributes).
2999 ****************************************************************************/
3001 static int call_trans2mkdir(connection_struct *conn,
3002 char *inbuf, char *outbuf, int length, int bufsize,
3003 char **pparams, int total_params, char **ppdata, int total_data)
3005 char *params = *pparams;
3006 pstring directory;
3007 int ret = -1;
3008 SMB_STRUCT_STAT sbuf;
3009 BOOL bad_path = False;
3011 if (!CAN_WRITE(conn))
3012 return ERROR_DOS(ERRSRV,ERRaccess);
3014 if (total_params < 4)
3015 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3017 srvstr_pull(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE);
3019 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3021 unix_convert(directory,conn,0,&bad_path,&sbuf);
3022 if (check_name(directory,conn))
3023 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3025 if(ret < 0) {
3026 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3027 set_bad_path_error(errno, bad_path);
3028 return(UNIXERROR(ERRDOS,ERRnoaccess));
3031 /* Realloc the parameter and data sizes */
3032 params = Realloc(*pparams,2);
3033 if(params == NULL)
3034 return ERROR_DOS(ERRDOS,ERRnomem);
3035 *pparams = params;
3037 SSVAL(params,0,0);
3039 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3041 return(-1);
3044 /****************************************************************************
3045 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3046 We don't actually do this - we just send a null response.
3047 ****************************************************************************/
3049 static int call_trans2findnotifyfirst(connection_struct *conn,
3050 char *inbuf, char *outbuf, int length, int bufsize,
3051 char **pparams, int total_params, char **ppdata, int total_data)
3053 static uint16 fnf_handle = 257;
3054 char *params = *pparams;
3055 uint16 info_level;
3057 if (total_params < 6)
3058 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3060 info_level = SVAL(params,4);
3061 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3063 switch (info_level) {
3064 case 1:
3065 case 2:
3066 break;
3067 default:
3068 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3071 /* Realloc the parameter and data sizes */
3072 params = Realloc(*pparams,6);
3073 if(params == NULL)
3074 return ERROR_DOS(ERRDOS,ERRnomem);
3075 *pparams = params;
3077 SSVAL(params,0,fnf_handle);
3078 SSVAL(params,2,0); /* No changes */
3079 SSVAL(params,4,0); /* No EA errors */
3081 fnf_handle++;
3083 if(fnf_handle == 0)
3084 fnf_handle = 257;
3086 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3088 return(-1);
3091 /****************************************************************************
3092 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3093 changes). Currently this does nothing.
3094 ****************************************************************************/
3096 static int call_trans2findnotifynext(connection_struct *conn,
3097 char *inbuf, char *outbuf, int length, int bufsize,
3098 char **pparams, int total_params, char **ppdata, int total_data)
3100 char *params = *pparams;
3102 DEBUG(3,("call_trans2findnotifynext\n"));
3104 /* Realloc the parameter and data sizes */
3105 params = Realloc(*pparams,4);
3106 if(params == NULL)
3107 return ERROR_DOS(ERRDOS,ERRnomem);
3108 *pparams = params;
3110 SSVAL(params,0,0); /* No changes */
3111 SSVAL(params,2,0); /* No EA errors */
3113 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3115 return(-1);
3118 /****************************************************************************
3119 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3120 ****************************************************************************/
3122 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3123 char* outbuf, int length, int bufsize,
3124 char **pparams, int total_params, char **ppdata, int total_data)
3126 char *params = *pparams;
3127 pstring pathname;
3128 int reply_size = 0;
3129 int max_referral_level;
3131 DEBUG(10,("call_trans2getdfsreferral\n"));
3133 if (total_params < 2)
3134 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3136 max_referral_level = SVAL(params,0);
3138 if(!lp_host_msdfs())
3139 return ERROR_DOS(ERRDOS,ERRbadfunc);
3141 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
3143 if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
3144 return ERROR_DOS(ERRDOS,ERRbadfile);
3146 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3147 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3149 return(-1);
3152 #define LMCAT_SPL 0x53
3153 #define LMFUNC_GETJOBID 0x60
3155 /****************************************************************************
3156 Reply to a TRANS2_IOCTL - used for OS/2 printing.
3157 ****************************************************************************/
3159 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3160 char* outbuf, int length, int bufsize,
3161 char **pparams, int total_params, char **ppdata, int total_data)
3163 char *pdata = *ppdata;
3164 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3166 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3167 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3168 pdata = Realloc(*ppdata, 32);
3169 if(pdata == NULL)
3170 return ERROR_DOS(ERRDOS,ERRnomem);
3171 *ppdata = pdata;
3173 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3174 CAN ACCEPT THIS IN UNICODE. JRA. */
3176 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
3177 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3178 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3179 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3180 return(-1);
3181 } else {
3182 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3183 return ERROR_DOS(ERRSRV,ERRerror);
3187 /****************************************************************************
3188 Reply to a SMBfindclose (stop trans2 directory search).
3189 ****************************************************************************/
3191 int reply_findclose(connection_struct *conn,
3192 char *inbuf,char *outbuf,int length,int bufsize)
3194 int outsize = 0;
3195 int dptr_num=SVALS(inbuf,smb_vwv0);
3196 START_PROFILE(SMBfindclose);
3198 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3200 dptr_close(&dptr_num);
3202 outsize = set_message(outbuf,0,0,True);
3204 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3206 END_PROFILE(SMBfindclose);
3207 return(outsize);
3210 /****************************************************************************
3211 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3212 ****************************************************************************/
3214 int reply_findnclose(connection_struct *conn,
3215 char *inbuf,char *outbuf,int length,int bufsize)
3217 int outsize = 0;
3218 int dptr_num= -1;
3219 START_PROFILE(SMBfindnclose);
3221 dptr_num = SVAL(inbuf,smb_vwv0);
3223 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3225 /* We never give out valid handles for a
3226 findnotifyfirst - so any dptr_num is ok here.
3227 Just ignore it. */
3229 outsize = set_message(outbuf,0,0,True);
3231 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3233 END_PROFILE(SMBfindnclose);
3234 return(outsize);
3237 /****************************************************************************
3238 Reply to a SMBtranss2 - just ignore it!
3239 ****************************************************************************/
3241 int reply_transs2(connection_struct *conn,
3242 char *inbuf,char *outbuf,int length,int bufsize)
3244 START_PROFILE(SMBtranss2);
3245 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3246 END_PROFILE(SMBtranss2);
3247 return(-1);
3250 /****************************************************************************
3251 Reply to a SMBtrans2.
3252 ****************************************************************************/
3254 int reply_trans2(connection_struct *conn,
3255 char *inbuf,char *outbuf,int length,int bufsize)
3257 int outsize = 0;
3258 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3259 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3260 #if 0
3261 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3262 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3263 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3264 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3265 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3266 int32 timeout = IVALS(inbuf,smb_timeout);
3267 #endif
3268 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3269 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3270 char *params = NULL, *data = NULL;
3271 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
3272 START_PROFILE(SMBtrans2);
3274 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3275 /* Queue this open message as we are the process of an
3276 * oplock break. */
3278 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3279 DEBUGADD(2,( "in oplock break state.\n"));
3281 push_oplock_pending_smb_message(inbuf, length);
3282 END_PROFILE(SMBtrans2);
3283 return -1;
3286 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3287 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3288 END_PROFILE(SMBtrans2);
3289 return ERROR_DOS(ERRSRV,ERRaccess);
3292 outsize = set_message(outbuf,0,0,True);
3294 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3295 is so as a sanity check */
3296 if (suwcnt != 1) {
3298 * Need to have rc=0 for ioctl to get job id for OS/2.
3299 * Network printing will fail if function is not successful.
3300 * Similar function in reply.c will be used if protocol
3301 * is LANMAN1.0 instead of LM1.2X002.
3302 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3303 * outbuf doesn't have to be set(only job id is used).
3305 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3306 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3307 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3308 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3309 } else {
3310 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
3311 DEBUG(2,("Transaction is %d\n",tran_call));
3312 END_PROFILE(SMBtrans2);
3313 ERROR_DOS(ERRDOS,ERRinvalidparam);
3317 /* Allocate the space for the maximum needed parameters and data */
3318 if (total_params > 0)
3319 params = (char *)malloc(total_params);
3320 if (total_data > 0)
3321 data = (char *)malloc(total_data);
3323 if ((total_params && !params) || (total_data && !data)) {
3324 DEBUG(2,("Out of memory in reply_trans2\n"));
3325 SAFE_FREE(params);
3326 SAFE_FREE(data);
3327 END_PROFILE(SMBtrans2);
3328 return ERROR_DOS(ERRDOS,ERRnomem);
3331 /* Copy the param and data bytes sent with this request into
3332 the params buffer */
3333 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3334 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3336 if (num_params > total_params || num_data > total_data)
3337 exit_server("invalid params in reply_trans2");
3339 if(params) {
3340 unsigned int psoff = SVAL(inbuf, smb_psoff);
3341 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
3342 goto bad_param;
3343 if (smb_base(inbuf) + psoff + num_params > inbuf + length)
3344 goto bad_param;
3345 memcpy( params, smb_base(inbuf) + psoff, num_params);
3347 if(data) {
3348 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
3349 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
3350 goto bad_param;
3351 if (smb_base(inbuf) + dsoff + num_data > inbuf + length)
3352 goto bad_param;
3353 memcpy( data, smb_base(inbuf) + dsoff, num_data);
3356 if(num_data_sofar < total_data || num_params_sofar < total_params) {
3357 /* We need to send an interim response then receive the rest
3358 of the parameter/data bytes */
3359 outsize = set_message(outbuf,0,0,True);
3360 if (!send_smb(smbd_server_fd(),outbuf))
3361 exit_server("reply_trans2: send_smb failed.");
3363 while (num_data_sofar < total_data ||
3364 num_params_sofar < total_params) {
3365 BOOL ret;
3366 unsigned int param_disp;
3367 unsigned int param_off;
3368 unsigned int data_disp;
3369 unsigned int data_off;
3371 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3373 if ((ret &&
3374 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3375 outsize = set_message(outbuf,0,0,True);
3376 if(ret)
3377 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3378 else
3379 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3380 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3381 goto bad_param;
3384 /* Revise total_params and total_data in case
3385 they have changed downwards */
3386 if (SVAL(inbuf, smb_tpscnt) < total_params)
3387 total_params = SVAL(inbuf, smb_tpscnt);
3388 if (SVAL(inbuf, smb_tdscnt) < total_data)
3389 total_data = SVAL(inbuf, smb_tdscnt);
3391 num_params = SVAL(inbuf,smb_spscnt);
3392 param_off = SVAL(inbuf, smb_spsoff);
3393 param_disp = SVAL(inbuf, smb_spsdisp);
3394 num_params_sofar += num_params;
3396 num_data = SVAL(inbuf, smb_sdscnt);
3397 data_off = SVAL(inbuf, smb_sdsoff);
3398 data_disp = SVAL(inbuf, smb_sdsdisp);
3399 num_data_sofar += num_data;
3401 if (num_params_sofar > total_params || num_data_sofar > total_data)
3402 goto bad_param;
3404 if (num_params) {
3405 if (param_disp + num_params >= total_params)
3406 goto bad_param;
3407 if ((param_disp + num_params < param_disp) ||
3408 (param_disp + num_params < num_params))
3409 goto bad_param;
3410 if (smb_base(inbuf) + param_off + num_params >= inbuf + bufsize)
3411 goto bad_param;
3412 if (params + param_disp < params)
3413 goto bad_param;
3415 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
3417 if (num_data) {
3418 if (data_disp + num_data >= total_data)
3419 goto bad_param;
3420 if ((data_disp + num_data < data_disp) ||
3421 (data_disp + num_data < num_data))
3422 goto bad_param;
3423 if (smb_base(inbuf) + data_off + num_data >= inbuf + bufsize)
3424 goto bad_param;
3425 if (data + data_disp < data)
3426 goto bad_param;
3428 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
3433 if (Protocol >= PROTOCOL_NT1) {
3434 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
3437 /* Now we must call the relevant TRANS2 function */
3438 switch(tran_call) {
3439 case TRANSACT2_OPEN:
3440 START_PROFILE_NESTED(Trans2_open);
3441 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
3442 &params, total_params, &data, total_data);
3443 END_PROFILE_NESTED(Trans2_open);
3444 break;
3446 case TRANSACT2_FINDFIRST:
3447 START_PROFILE_NESTED(Trans2_findfirst);
3448 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3449 &params, total_params, &data, total_data);
3450 END_PROFILE_NESTED(Trans2_findfirst);
3451 break;
3453 case TRANSACT2_FINDNEXT:
3454 START_PROFILE_NESTED(Trans2_findnext);
3455 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
3456 &params, total_params, &data, total_data);
3457 END_PROFILE_NESTED(Trans2_findnext);
3458 break;
3460 case TRANSACT2_QFSINFO:
3461 START_PROFILE_NESTED(Trans2_qfsinfo);
3462 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3463 &params, total_params, &data, total_data);
3464 END_PROFILE_NESTED(Trans2_qfsinfo);
3465 break;
3467 #ifdef HAVE_SYS_QUOTAS
3468 case TRANSACT2_SETFSINFO:
3469 START_PROFILE_NESTED(Trans2_setfsinfo);
3470 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
3471 &params, total_params, &data, total_data);
3472 END_PROFILE_NESTED(Trans2_setfsinfo);
3473 break;
3474 #endif
3475 case TRANSACT2_QPATHINFO:
3476 case TRANSACT2_QFILEINFO:
3477 START_PROFILE_NESTED(Trans2_qpathinfo);
3478 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3479 &params, total_params, &data, total_data);
3480 END_PROFILE_NESTED(Trans2_qpathinfo);
3481 break;
3482 case TRANSACT2_SETPATHINFO:
3483 case TRANSACT2_SETFILEINFO:
3484 START_PROFILE_NESTED(Trans2_setpathinfo);
3485 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3486 &params, total_params, &data, total_data);
3487 END_PROFILE_NESTED(Trans2_setpathinfo);
3488 break;
3490 case TRANSACT2_FINDNOTIFYFIRST:
3491 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3492 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
3493 &params, total_params, &data, total_data);
3494 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3495 break;
3497 case TRANSACT2_FINDNOTIFYNEXT:
3498 START_PROFILE_NESTED(Trans2_findnotifynext);
3499 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
3500 &params, total_params, &data, total_data);
3501 END_PROFILE_NESTED(Trans2_findnotifynext);
3502 break;
3503 case TRANSACT2_MKDIR:
3504 START_PROFILE_NESTED(Trans2_mkdir);
3505 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3506 &params, total_params, &data, total_data);
3507 END_PROFILE_NESTED(Trans2_mkdir);
3508 break;
3510 case TRANSACT2_GET_DFS_REFERRAL:
3511 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3512 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3513 &params, total_params, &data, total_data);
3514 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3515 break;
3516 case TRANSACT2_IOCTL:
3517 START_PROFILE_NESTED(Trans2_ioctl);
3518 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3519 &params, total_params, &data, total_data);
3520 END_PROFILE_NESTED(Trans2_ioctl);
3521 break;
3522 default:
3523 /* Error in request */
3524 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3525 SAFE_FREE(params);
3526 SAFE_FREE(data);
3527 END_PROFILE(SMBtrans2);
3528 return ERROR_DOS(ERRSRV,ERRerror);
3531 /* As we do not know how many data packets will need to be
3532 returned here the various call_trans2xxxx calls
3533 must send their own. Thus a call_trans2xxx routine only
3534 returns a value other than -1 when it wants to send
3535 an error packet.
3538 SAFE_FREE(params);
3539 SAFE_FREE(data);
3540 END_PROFILE(SMBtrans2);
3541 return outsize; /* If a correct response was needed the
3542 call_trans2xxx calls have already sent
3543 it. If outsize != -1 then it is returning */
3545 bad_param:
3547 SAFE_FREE(params);
3548 SAFE_FREE(data);
3549 END_PROFILE(SMBtrans2);
3550 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);