added the COMPRESSION_INFO trans2 QFILEINFO level and fixed the
[Samba.git] / source / smbd / trans2.c
blob8364c4b5095949a79ad5c72799266f368a370ac9
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 p += align_string(outbuf, p, 0);
653 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
654 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS)
655 SCVAL(nameptr, -1, len-2);
656 else
657 SCVAL(nameptr, -1, len-1);
658 p += len;
659 break;
661 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
662 was_8_3 = mangle_is_8_3(fname, True);
663 p += 4;
664 SIVAL(p,0,reskey); p += 4;
665 put_long_date(p,cdate); p += 8;
666 put_long_date(p,adate); p += 8;
667 put_long_date(p,mdate); p += 8;
668 put_long_date(p,mdate); p += 8;
669 SOFF_T(p,0,file_size);
670 SOFF_T(p,8,allocation_size);
671 p += 16;
672 SIVAL(p,0,nt_extmode); p += 4;
673 q = p; p += 4;
674 SIVAL(p,0,0); p += 4;
675 /* Clear the short name buffer. This is
676 * IMPORTANT as not doing so will trigger
677 * a Win2k client bug. JRA.
679 memset(p,'\0',26);
680 if (!was_8_3) {
681 pstring mangled_name;
682 pstrcpy(mangled_name, fname);
683 mangle_map(mangled_name,True,True,SNUM(conn));
684 mangled_name[12] = 0;
685 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER);
686 #ifdef DEVELOPER
687 /* valgrind fixer... */
689 size_t sl = strlen(p+2);
690 if (24-sl)
691 memset(&p[sl+2], '\0', 24-sl);
693 #endif
694 SSVAL(p, 0, len);
695 } else {
696 SSVAL(p,0,0);
697 *(p+2) = 0;
699 p += 2 + 24;
700 len = srvstr_push(outbuf, p, fname, -1, 0);
701 SIVAL(q,0,len);
702 p += len;
703 len = PTR_DIFF(p, pdata);
704 len = (len + 3) & ~3;
705 SIVAL(pdata,0,len);
706 p = pdata + len;
707 break;
709 case SMB_FIND_FILE_DIRECTORY_INFO:
710 p += 4;
711 SIVAL(p,0,reskey); p += 4;
712 put_long_date(p,cdate); p += 8;
713 put_long_date(p,adate); p += 8;
714 put_long_date(p,mdate); p += 8;
715 put_long_date(p,mdate); p += 8;
716 SOFF_T(p,0,file_size);
717 SOFF_T(p,8,allocation_size);
718 p += 16;
719 SIVAL(p,0,nt_extmode); p += 4;
720 p += 4;
721 len = srvstr_push(outbuf, p, fname, -1, 0);
722 SIVAL(p, -4, len);
723 p += len;
724 len = PTR_DIFF(p, pdata);
725 len = (len + 3) & ~3;
726 SIVAL(pdata,0,len);
727 p = pdata + len;
728 break;
730 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
731 p += 4;
732 SIVAL(p,0,reskey); p += 4;
733 put_long_date(p,cdate); p += 8;
734 put_long_date(p,adate); p += 8;
735 put_long_date(p,mdate); p += 8;
736 put_long_date(p,mdate); p += 8;
737 SOFF_T(p,0,file_size);
738 SOFF_T(p,8,allocation_size);
739 p += 16;
740 SIVAL(p,0,nt_extmode); p += 4;
741 p += 4;
742 SIVAL(p,0,0); p += 4;
744 len = srvstr_push(outbuf, p, fname, -1, 0);
745 SIVAL(p, -4, len);
746 p += len;
748 len = PTR_DIFF(p, pdata);
749 len = (len + 3) & ~3;
750 SIVAL(pdata,0,len);
751 p = pdata + len;
752 break;
754 case SMB_FIND_FILE_NAMES_INFO:
755 p += 4;
756 SIVAL(p,0,reskey); p += 4;
757 p += 4;
758 /* this must *not* be null terminated or w2k gets in a loop trying to set an
759 acl on a dir (tridge) */
760 len = srvstr_push(outbuf, p, fname, -1, 0);
761 SIVAL(p, -4, len);
762 p += len;
763 len = PTR_DIFF(p, pdata);
764 len = (len + 3) & ~3;
765 SIVAL(pdata,0,len);
766 p = pdata + len;
767 break;
769 /* CIFS UNIX Extension. */
771 case SMB_FIND_FILE_UNIX:
772 p+= 4;
773 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
775 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
776 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
777 p+= 8;
779 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
780 p+= 8;
782 put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */
783 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
784 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
785 p+= 24;
787 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
788 SIVAL(p,4,0);
789 p+= 8;
791 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
792 SIVAL(p,4,0);
793 p+= 8;
795 SIVAL(p,0,unix_filetype(sbuf.st_mode));
796 p+= 4;
798 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
799 SIVAL(p,4,0);
800 p+= 8;
802 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
803 SIVAL(p,4,0);
804 p+= 8;
806 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
807 p+= 8;
809 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
810 SIVAL(p,4,0);
811 p+= 8;
813 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
814 SIVAL(p,4,0);
815 p+= 8;
817 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
818 p += len;
820 len = PTR_DIFF(p, pdata);
821 len = (len + 3) & ~3;
822 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
823 p = pdata + len;
824 /* End of SMB_QUERY_FILE_UNIX_BASIC */
826 break;
828 default:
829 return(False);
833 if (PTR_DIFF(p,pdata) > space_remaining) {
834 /* Move the dirptr back to prev_dirpos */
835 SeekDir(conn->dirptr, prev_dirpos);
836 *out_of_space = True;
837 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
838 return False; /* Not finished - just out of space */
841 /* Setup the last_filename pointer, as an offset from base_data */
842 *last_name_off = PTR_DIFF(nameptr,base_data);
843 /* Advance the data pointer to the next slot */
844 *ppdata = p;
846 return(found);
849 /****************************************************************************
850 Reply to a TRANS2_FINDFIRST.
851 ****************************************************************************/
853 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
854 char **pparams, int total_params, char **ppdata, int total_data)
856 /* We must be careful here that we don't return more than the
857 allowed number of data bytes. If this means returning fewer than
858 maxentries then so be it. We assume that the redirector has
859 enough room for the fixed number of parameter bytes it has
860 requested. */
861 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
862 char *params = *pparams;
863 char *pdata = *ppdata;
864 int dirtype = SVAL(params,0);
865 int maxentries = SVAL(params,2);
866 BOOL close_after_first = BITSETW(params+4,0);
867 BOOL close_if_end = BITSETW(params+4,1);
868 BOOL requires_resume_key = BITSETW(params+4,2);
869 int info_level = SVAL(params,6);
870 pstring directory;
871 pstring mask;
872 char *p, *wcard;
873 int last_name_off=0;
874 int dptr_num = -1;
875 int numentries = 0;
876 int i;
877 BOOL finished = False;
878 BOOL dont_descend = False;
879 BOOL out_of_space = False;
880 int space_remaining;
881 BOOL bad_path = False;
882 SMB_STRUCT_STAT sbuf;
884 if (total_params < 12)
885 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
887 *directory = *mask = 0;
889 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
890 close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
891 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
892 info_level, max_data_bytes));
894 switch (info_level) {
895 case SMB_INFO_STANDARD:
896 case SMB_INFO_QUERY_EA_SIZE:
897 case SMB_FIND_FILE_DIRECTORY_INFO:
898 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
899 case SMB_FIND_FILE_NAMES_INFO:
900 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
901 break;
902 case SMB_FIND_FILE_UNIX:
903 if (!lp_unix_extensions())
904 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
905 break;
906 default:
907 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
910 srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE);
912 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
914 unix_convert(directory,conn,0,&bad_path,&sbuf);
915 if(!check_name(directory,conn)) {
916 set_bad_path_error(errno, bad_path);
917 return(UNIXERROR(ERRDOS,ERRbadpath));
920 p = strrchr_m(directory,'/');
921 if(p == NULL) {
922 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
923 if((directory[0] == '.') && (directory[1] == '\0'))
924 pstrcpy(mask,"*");
925 else
926 pstrcpy(mask,directory);
927 pstrcpy(directory,"./");
928 } else {
929 pstrcpy(mask,p+1);
930 *p = 0;
933 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
935 pdata = Realloc(*ppdata, max_data_bytes + 1024);
936 if( pdata == NULL )
937 return(ERROR_DOS(ERRDOS,ERRnomem));
939 *ppdata = pdata;
940 memset((char *)pdata,'\0',max_data_bytes + 1024);
942 /* Realloc the params space */
943 params = Realloc(*pparams, 10);
944 if (params == NULL)
945 return ERROR_DOS(ERRDOS,ERRnomem);
946 *pparams = params;
948 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
949 if (dptr_num < 0)
950 return(UNIXERROR(ERRDOS,ERRbadfile));
952 /* Save the wildcard match and attribs we are using on this directory -
953 needed as lanman2 assumes these are being saved between calls */
955 if(!(wcard = strdup(mask))) {
956 dptr_close(&dptr_num);
957 return ERROR_DOS(ERRDOS,ERRnomem);
960 dptr_set_wcard(dptr_num, wcard);
961 dptr_set_attr(dptr_num, dirtype);
963 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
965 /* We don't need to check for VOL here as this is returned by
966 a different TRANS2 call. */
968 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
969 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
970 dont_descend = True;
972 p = pdata;
973 space_remaining = max_data_bytes;
974 out_of_space = False;
976 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
977 BOOL got_exact_match = False;
979 /* this is a heuristic to avoid seeking the dirptr except when
980 absolutely necessary. It allows for a filename of about 40 chars */
981 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
982 out_of_space = True;
983 finished = False;
984 } else {
985 finished = !get_lanman2_dir_entry(conn,
986 inbuf, outbuf,
987 mask,dirtype,info_level,
988 requires_resume_key,dont_descend,
989 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
990 &last_name_off);
993 if (finished && out_of_space)
994 finished = False;
996 if (!finished && !out_of_space)
997 numentries++;
1000 * As an optimisation if we know we aren't looking
1001 * for a wildcard name (ie. the name matches the wildcard exactly)
1002 * then we can finish on any (first) match.
1003 * This speeds up large directory searches. JRA.
1006 if(got_exact_match)
1007 finished = True;
1009 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1012 /* Check if we can close the dirptr */
1013 if(close_after_first || (finished && close_if_end)) {
1014 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1015 dptr_close(&dptr_num);
1019 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1020 * from observation of NT.
1023 if(numentries == 0) {
1024 dptr_close(&dptr_num);
1025 return ERROR_DOS(ERRDOS,ERRbadfile);
1028 /* At this point pdata points to numentries directory entries. */
1030 /* Set up the return parameter block */
1031 SSVAL(params,0,dptr_num);
1032 SSVAL(params,2,numentries);
1033 SSVAL(params,4,finished);
1034 SSVAL(params,6,0); /* Never an EA error */
1035 SSVAL(params,8,last_name_off);
1037 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1039 if ((! *directory) && dptr_path(dptr_num))
1040 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1042 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1043 smb_fn_name(CVAL(inbuf,smb_com)),
1044 mask, directory, dirtype, numentries ) );
1047 * Force a name mangle here to ensure that the
1048 * mask as an 8.3 name is top of the mangled cache.
1049 * The reasons for this are subtle. Don't remove
1050 * this code unless you know what you are doing
1051 * (see PR#13758). JRA.
1054 if(!mangle_is_8_3_wildcards( mask, False))
1055 mangle_map(mask, True, True, SNUM(conn));
1057 return(-1);
1060 /****************************************************************************
1061 Reply to a TRANS2_FINDNEXT.
1062 ****************************************************************************/
1064 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1065 char **pparams, int total_params, char **ppdata, int total_data)
1067 /* We must be careful here that we don't return more than the
1068 allowed number of data bytes. If this means returning fewer than
1069 maxentries then so be it. We assume that the redirector has
1070 enough room for the fixed number of parameter bytes it has
1071 requested. */
1072 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1073 char *params = *pparams;
1074 char *pdata = *ppdata;
1075 int dptr_num = SVAL(params,0);
1076 int maxentries = SVAL(params,2);
1077 uint16 info_level = SVAL(params,4);
1078 uint32 resume_key = IVAL(params,6);
1079 BOOL close_after_request = BITSETW(params+10,0);
1080 BOOL close_if_end = BITSETW(params+10,1);
1081 BOOL requires_resume_key = BITSETW(params+10,2);
1082 BOOL continue_bit = BITSETW(params+10,3);
1083 pstring resume_name;
1084 pstring mask;
1085 pstring directory;
1086 char *p;
1087 uint16 dirtype;
1088 int numentries = 0;
1089 int i, last_name_off=0;
1090 BOOL finished = False;
1091 BOOL dont_descend = False;
1092 BOOL out_of_space = False;
1093 int space_remaining;
1095 if (total_params < 12)
1096 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1098 *mask = *directory = *resume_name = 0;
1100 srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE);
1102 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1103 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1104 resume_key = %d resume name = %s continue=%d level = %d\n",
1105 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1106 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1108 switch (info_level) {
1109 case SMB_INFO_STANDARD:
1110 case SMB_INFO_QUERY_EA_SIZE:
1111 case SMB_FIND_FILE_DIRECTORY_INFO:
1112 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1113 case SMB_FIND_FILE_NAMES_INFO:
1114 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1115 break;
1116 case SMB_FIND_FILE_UNIX:
1117 if (!lp_unix_extensions())
1118 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1119 break;
1120 default:
1121 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1124 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1125 if(pdata == NULL)
1126 return ERROR_DOS(ERRDOS,ERRnomem);
1128 *ppdata = pdata;
1129 memset((char *)pdata,'\0',max_data_bytes + 1024);
1131 /* Realloc the params space */
1132 params = Realloc(*pparams, 6*SIZEOFWORD);
1133 if( params == NULL )
1134 return ERROR_DOS(ERRDOS,ERRnomem);
1136 *pparams = params;
1138 /* Check that the dptr is valid */
1139 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1140 return ERROR_DOS(ERRDOS,ERRnofiles);
1142 string_set(&conn->dirpath,dptr_path(dptr_num));
1144 /* Get the wildcard mask from the dptr */
1145 if((p = dptr_wcard(dptr_num))== NULL) {
1146 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1147 return ERROR_DOS(ERRDOS,ERRnofiles);
1150 pstrcpy(mask, p);
1151 pstrcpy(directory,conn->dirpath);
1153 /* Get the attr mask from the dptr */
1154 dirtype = dptr_attr(dptr_num);
1156 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1157 dptr_num, mask, dirtype,
1158 (long)conn->dirptr,
1159 TellDir(conn->dirptr)));
1161 /* We don't need to check for VOL here as this is returned by
1162 a different TRANS2 call. */
1164 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1165 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1166 dont_descend = True;
1168 p = pdata;
1169 space_remaining = max_data_bytes;
1170 out_of_space = False;
1173 * Seek to the correct position. We no longer use the resume key but
1174 * depend on the last file name instead.
1177 if(requires_resume_key && *resume_name && !continue_bit) {
1180 * Fix for NT redirector problem triggered by resume key indexes
1181 * changing between directory scans. We now return a resume key of 0
1182 * and instead look for the filename to continue from (also given
1183 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1184 * findfirst/findnext (as is usual) then the directory pointer
1185 * should already be at the correct place. Check this by scanning
1186 * backwards looking for an exact (ie. case sensitive) filename match.
1187 * If we get to the beginning of the directory and haven't found it then scan
1188 * forwards again looking for a match. JRA.
1191 int current_pos, start_pos;
1192 const char *dname = NULL;
1193 pstring dname_pstring;
1194 void *dirptr = conn->dirptr;
1195 start_pos = TellDir(dirptr);
1196 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1197 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1199 SeekDir(dirptr, current_pos);
1200 dname = ReadDirName(dirptr);
1201 if (dname) {
1203 * Remember, mangle_map is called by
1204 * get_lanman2_dir_entry(), so the resume name
1205 * could be mangled. Ensure we do the same
1206 * here.
1209 /* make sure we get a copy that mangle_map can modify */
1211 pstrcpy(dname_pstring, dname);
1212 mangle_map( dname_pstring, False, True, SNUM(conn));
1214 if(strcsequal( resume_name, dname_pstring)) {
1215 SeekDir(dirptr, current_pos+1);
1216 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1217 break;
1223 * Scan forward from start if not found going backwards.
1226 if(current_pos < 0) {
1227 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1228 SeekDir(dirptr, start_pos);
1229 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1232 * Remember, mangle_map is called by
1233 * get_lanman2_dir_entry(), so the resume name
1234 * could be mangled. Ensure we do the same
1235 * here.
1238 if(dname) {
1239 /* make sure we get a copy that mangle_map can modify */
1241 pstrcpy(dname_pstring, dname);
1242 mangle_map(dname_pstring, False, True, SNUM(conn));
1244 if(strcsequal( resume_name, dname_pstring)) {
1245 SeekDir(dirptr, current_pos+1);
1246 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1247 break;
1250 } /* end for */
1251 } /* end if current_pos */
1252 } /* end if requires_resume_key && !continue_bit */
1254 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1255 BOOL got_exact_match = False;
1257 /* this is a heuristic to avoid seeking the dirptr except when
1258 absolutely necessary. It allows for a filename of about 40 chars */
1259 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1260 out_of_space = True;
1261 finished = False;
1262 } else {
1263 finished = !get_lanman2_dir_entry(conn,
1264 inbuf, outbuf,
1265 mask,dirtype,info_level,
1266 requires_resume_key,dont_descend,
1267 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1268 &last_name_off);
1271 if (finished && out_of_space)
1272 finished = False;
1274 if (!finished && !out_of_space)
1275 numentries++;
1278 * As an optimisation if we know we aren't looking
1279 * for a wildcard name (ie. the name matches the wildcard exactly)
1280 * then we can finish on any (first) match.
1281 * This speeds up large directory searches. JRA.
1284 if(got_exact_match)
1285 finished = True;
1287 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1290 /* Check if we can close the dirptr */
1291 if(close_after_request || (finished && close_if_end)) {
1292 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1293 dptr_close(&dptr_num); /* This frees up the saved mask */
1296 /* Set up the return parameter block */
1297 SSVAL(params,0,numentries);
1298 SSVAL(params,2,finished);
1299 SSVAL(params,4,0); /* Never an EA error */
1300 SSVAL(params,6,last_name_off);
1302 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1304 if ((! *directory) && dptr_path(dptr_num))
1305 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1307 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1308 smb_fn_name(CVAL(inbuf,smb_com)),
1309 mask, directory, dirtype, numentries ) );
1311 return(-1);
1314 /****************************************************************************
1315 Reply to a TRANS2_QFSINFO (query filesystem info).
1316 ****************************************************************************/
1318 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1319 int length, int bufsize,
1320 char **pparams, int total_params, char **ppdata, int total_data)
1322 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1323 char *pdata = *ppdata;
1324 char *params = *pparams;
1325 uint16 info_level = SVAL(params,0);
1326 int data_len, len;
1327 SMB_STRUCT_STAT st;
1328 char *vname = volume_label(SNUM(conn));
1329 int snum = SNUM(conn);
1330 char *fstype = lp_fstype(SNUM(conn));
1331 int quota_flag = 0;
1333 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1335 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1336 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1337 return ERROR_DOS(ERRSRV,ERRinvdevice);
1340 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1341 if ( pdata == NULL )
1342 return ERROR_DOS(ERRDOS,ERRnomem);
1344 *ppdata = pdata;
1345 memset((char *)pdata,'\0',max_data_bytes + 1024);
1347 switch (info_level) {
1348 case SMB_INFO_ALLOCATION:
1350 SMB_BIG_UINT dfree,dsize,bsize;
1351 data_len = 18;
1352 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1353 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1354 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1355 SIVAL(pdata,l1_cUnit,dsize);
1356 SIVAL(pdata,l1_cUnitAvail,dfree);
1357 SSVAL(pdata,l1_cbSector,512);
1358 DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1359 (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1360 (unsigned int)dfree, 512));
1361 break;
1364 case SMB_INFO_VOLUME:
1365 /* Return volume name */
1367 * Add volume serial number - hash of a combination of
1368 * the called hostname and the service name.
1370 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1371 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_TERMINATE);
1372 SCVAL(pdata,l2_vol_cch,len);
1373 data_len = l2_vol_szVolLabel + len;
1374 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1375 (unsigned)st.st_ctime, len, vname));
1376 break;
1378 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1379 case SMB_FS_ATTRIBUTE_INFORMATION:
1382 #if defined(HAVE_SYS_QUOTAS)
1383 quota_flag = FILE_VOLUME_QUOTAS;
1384 #endif
1386 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1387 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1388 quota_flag); /* FS ATTRIBUTES */
1390 SIVAL(pdata,4,255); /* Max filename component length */
1391 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1392 and will think we can't do long filenames */
1393 len = srvstr_push(outbuf, pdata+12, fstype, -1, 0);
1394 SIVAL(pdata,8,len);
1395 data_len = 12 + len;
1396 break;
1398 case SMB_QUERY_FS_LABEL_INFO:
1399 case SMB_FS_LABEL_INFORMATION:
1400 len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE);
1401 data_len = 4 + len;
1402 SIVAL(pdata,0,len);
1403 break;
1405 case SMB_QUERY_FS_VOLUME_INFO:
1406 case SMB_FS_VOLUME_INFORMATION:
1409 * Add volume serial number - hash of a combination of
1410 * the called hostname and the service name.
1412 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1413 (str_checksum(local_machine)<<16));
1415 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE);
1416 SIVAL(pdata,12,len);
1417 data_len = 18+len;
1418 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1419 (int)strlen(vname),vname, lp_servicename(snum)));
1420 break;
1422 case SMB_QUERY_FS_SIZE_INFO:
1423 case SMB_FS_SIZE_INFORMATION:
1425 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1426 data_len = 24;
1427 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1428 block_size = lp_block_size(snum);
1429 if (bsize < block_size) {
1430 SMB_BIG_UINT factor = block_size/bsize;
1431 bsize = block_size;
1432 dsize /= factor;
1433 dfree /= factor;
1435 if (bsize > block_size) {
1436 SMB_BIG_UINT factor = bsize/block_size;
1437 bsize = block_size;
1438 dsize *= factor;
1439 dfree *= factor;
1441 bytes_per_sector = 512;
1442 sectors_per_unit = bsize/bytes_per_sector;
1443 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1444 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1445 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1446 SBIG_UINT(pdata,0,dsize);
1447 SBIG_UINT(pdata,8,dfree);
1448 SIVAL(pdata,16,sectors_per_unit);
1449 SIVAL(pdata,20,bytes_per_sector);
1450 break;
1453 case SMB_FS_FULL_SIZE_INFORMATION:
1455 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1456 data_len = 32;
1457 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1458 block_size = lp_block_size(snum);
1459 if (bsize < block_size) {
1460 SMB_BIG_UINT factor = block_size/bsize;
1461 bsize = block_size;
1462 dsize /= factor;
1463 dfree /= factor;
1465 if (bsize > block_size) {
1466 SMB_BIG_UINT factor = bsize/block_size;
1467 bsize = block_size;
1468 dsize *= factor;
1469 dfree *= factor;
1471 bytes_per_sector = 512;
1472 sectors_per_unit = bsize/bytes_per_sector;
1473 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1474 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1475 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1476 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1477 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1478 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1479 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1480 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1481 break;
1484 case SMB_QUERY_FS_DEVICE_INFO:
1485 case SMB_FS_DEVICE_INFORMATION:
1486 data_len = 8;
1487 SIVAL(pdata,0,0); /* dev type */
1488 SIVAL(pdata,4,0); /* characteristics */
1489 break;
1491 #ifdef HAVE_SYS_QUOTAS
1492 case SMB_FS_QUOTA_INFORMATION:
1494 * what we have to send --metze:
1496 * Unknown1: 24 NULL bytes
1497 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1498 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
1499 * Quota Flags: 2 byte :
1500 * Unknown3: 6 NULL bytes
1502 * 48 bytes total
1504 * details for Quota Flags:
1506 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1507 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
1508 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1509 * 0x0001 Enable Quotas: enable quota for this fs
1513 /* we need to fake up a fsp here,
1514 * because its not send in this call
1516 files_struct fsp;
1517 SMB_NTQUOTA_STRUCT quotas;
1519 ZERO_STRUCT(fsp);
1520 ZERO_STRUCT(quotas);
1522 fsp.conn = conn;
1523 fsp.fnum = -1;
1524 fsp.fd = -1;
1526 /* access check */
1527 if (conn->admin_user != True) {
1528 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1529 lp_servicename(SNUM(conn)),conn->user));
1530 return ERROR_DOS(ERRDOS,ERRnoaccess);
1533 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
1534 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
1535 return ERROR_DOS(ERRSRV,ERRerror);
1538 data_len = 48;
1540 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
1542 /* Unknown1 24 NULL bytes*/
1543 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
1544 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
1545 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
1547 /* Default Soft Quota 8 bytes */
1548 SBIG_UINT(pdata,24,quotas.softlim);
1550 /* Default Hard Quota 8 bytes */
1551 SBIG_UINT(pdata,32,quotas.hardlim);
1553 /* Quota flag 2 bytes */
1554 SSVAL(pdata,40,quotas.qflags);
1556 /* Unknown3 6 NULL bytes */
1557 SSVAL(pdata,42,0);
1558 SIVAL(pdata,44,0);
1560 break;
1562 #endif /* HAVE_SYS_QUOTAS */
1563 case SMB_FS_OBJECTID_INFORMATION:
1564 data_len = 64;
1565 break;
1568 * Query the version and capabilities of the CIFS UNIX extensions
1569 * in use.
1572 case SMB_QUERY_CIFS_UNIX_INFO:
1573 if (!lp_unix_extensions())
1574 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1575 data_len = 12;
1576 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
1577 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
1578 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
1579 break;
1581 case SMB_MAC_QUERY_FS_INFO:
1583 * Thursby MAC extension... ONLY on NTFS filesystems
1584 * once we do streams then we don't need this
1586 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1587 data_len = 88;
1588 SIVAL(pdata,84,0x100); /* Don't support mac... */
1589 break;
1591 /* drop through */
1592 default:
1593 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1597 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1599 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1601 return -1;
1604 #ifdef HAVE_SYS_QUOTAS
1605 /****************************************************************************
1606 Reply to a TRANS2_SETFSINFO (set filesystem info).
1607 ****************************************************************************/
1609 static int call_trans2setfsinfo(connection_struct *conn,
1610 char *inbuf, char *outbuf, int length, int bufsize,
1611 char **pparams, int total_params, char **ppdata, int total_data)
1613 char *pdata = *ppdata;
1614 char *params = *pparams;
1615 files_struct *fsp = NULL;
1616 uint16 info_level;
1617 int outsize;
1618 SMB_NTQUOTA_STRUCT quotas;
1620 ZERO_STRUCT(quotas);
1622 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
1624 /* access check */
1625 if ((conn->admin_user != True)||!CAN_WRITE(conn)) {
1626 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1627 lp_servicename(SNUM(conn)),conn->user));
1628 return ERROR_DOS(ERRSRV,ERRaccess);
1631 /* */
1632 if (total_params < 4) {
1633 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
1634 total_params));
1635 return ERROR_DOS(ERRDOS,ERRinvalidparam);
1638 fsp = file_fsp(params,0);
1640 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
1641 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
1642 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
1645 info_level = SVAL(params,2);
1647 switch(info_level) {
1648 case SMB_FS_QUOTA_INFORMATION:
1649 /* note: normaly there're 48 bytes,
1650 * but we didn't use the last 6 bytes for now
1651 * --metze
1653 if (total_data < 42) {
1654 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
1655 total_data));
1656 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1659 /* unknown_1 24 NULL bytes in pdata*/
1661 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
1662 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
1663 #ifdef LARGE_SMB_OFF_T
1664 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
1665 #else /* LARGE_SMB_OFF_T */
1666 if ((IVAL(pdata,28) != 0)&&
1667 ((quotas.softlim != 0xFFFFFFFF)||
1668 (IVAL(pdata,28)!=0xFFFFFFFF))) {
1669 /* more than 32 bits? */
1670 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1672 #endif /* LARGE_SMB_OFF_T */
1674 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
1675 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
1676 #ifdef LARGE_SMB_OFF_T
1677 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
1678 #else /* LARGE_SMB_OFF_T */
1679 if ((IVAL(pdata,36) != 0)&&
1680 ((quotas.hardlim != 0xFFFFFFFF)||
1681 (IVAL(pdata,36)!=0xFFFFFFFF))) {
1682 /* more than 32 bits? */
1683 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1685 #endif /* LARGE_SMB_OFF_T */
1687 /* quota_flags 2 bytes **/
1688 quotas.qflags = SVAL(pdata,40);
1690 /* unknown_2 6 NULL bytes follow*/
1692 /* now set the quotas */
1693 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
1694 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
1695 return ERROR_DOS(ERRSRV,ERRerror);
1698 break;
1699 default:
1700 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
1701 info_level));
1702 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1703 break;
1707 * sending this reply works fine,
1708 * but I'm not sure it's the same
1709 * like windows do...
1710 * --metze
1712 outsize = set_message(outbuf,10,0,True);
1714 return outsize;
1716 #endif /* HAVE_SYS_QUOTAS */
1718 /****************************************************************************
1719 * Utility function to set bad path error.
1720 ****************************************************************************/
1722 NTSTATUS set_bad_path_error(int err, BOOL bad_path)
1724 if((err == ENOENT) && bad_path) {
1725 unix_ERR_class = ERRDOS;
1726 unix_ERR_code = ERRbadpath;
1727 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1729 return NT_STATUS_OK;
1732 /****************************************************************************
1733 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1734 file name or file id).
1735 ****************************************************************************/
1737 static int call_trans2qfilepathinfo(connection_struct *conn,
1738 char *inbuf, char *outbuf, int length,
1739 int bufsize,
1740 char **pparams, int total_params, char **ppdata, int total_data)
1742 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1743 char *params = *pparams;
1744 char *pdata = *ppdata;
1745 uint16 tran_call = SVAL(inbuf, smb_setup0);
1746 uint16 info_level;
1747 int mode=0;
1748 SMB_OFF_T file_size=0;
1749 SMB_BIG_UINT allocation_size=0;
1750 unsigned int data_size;
1751 SMB_STRUCT_STAT sbuf;
1752 pstring fname, dos_fname;
1753 char *fullpathname;
1754 char *base_name;
1755 char *p;
1756 SMB_OFF_T pos = 0;
1757 BOOL bad_path = False;
1758 BOOL delete_pending = False;
1759 int len;
1760 time_t c_time;
1761 files_struct *fsp = NULL;
1763 if (!params)
1764 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1766 if (tran_call == TRANSACT2_QFILEINFO) {
1767 if (total_params < 4)
1768 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1770 fsp = file_fsp(params,0);
1771 info_level = SVAL(params,2);
1773 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1775 if(fsp && (fsp->fake_file_handle)) {
1777 * This is actually for the QUOTA_FAKE_FILE --metze
1780 pstrcpy(fname, fsp->fsp_name);
1781 unix_convert(fname,conn,0,&bad_path,&sbuf);
1782 if (!check_name(fname,conn)) {
1783 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno)));
1784 set_bad_path_error(errno, bad_path);
1785 return(UNIXERROR(ERRDOS,ERRbadpath));
1788 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1790 * This is actually a QFILEINFO on a directory
1791 * handle (returned from an NT SMB). NT5.0 seems
1792 * to do this call. JRA.
1794 pstrcpy(fname, fsp->fsp_name);
1795 unix_convert(fname,conn,0,&bad_path,&sbuf);
1796 if (!check_name(fname,conn)) {
1797 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1798 set_bad_path_error(errno, bad_path);
1799 return(UNIXERROR(ERRDOS,ERRbadpath));
1802 if (INFO_LEVEL_IS_UNIX(info_level)) {
1803 /* Always do lstat for UNIX calls. */
1804 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
1805 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
1806 set_bad_path_error(errno, bad_path);
1807 return(UNIXERROR(ERRDOS,ERRbadpath));
1809 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
1810 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
1811 set_bad_path_error(errno, bad_path);
1812 return(UNIXERROR(ERRDOS,ERRbadpath));
1815 delete_pending = fsp->directory_delete_on_close;
1816 } else {
1818 * Original code - this is an open file.
1820 CHECK_FSP(fsp,conn);
1822 pstrcpy(fname, fsp->fsp_name);
1823 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
1824 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
1825 return(UNIXERROR(ERRDOS,ERRbadfid));
1827 if((pos = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1828 return(UNIXERROR(ERRDOS,ERRnoaccess));
1830 delete_pending = fsp->delete_on_close;
1832 } else {
1833 /* qpathinfo */
1834 if (total_params < 6)
1835 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1837 info_level = SVAL(params,0);
1839 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1841 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
1843 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1845 unix_convert(fname,conn,0,&bad_path,&sbuf);
1846 if (!check_name(fname,conn)) {
1847 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1848 set_bad_path_error(errno, bad_path);
1849 return(UNIXERROR(ERRDOS,ERRbadpath));
1852 if (INFO_LEVEL_IS_UNIX(info_level)) {
1853 /* Always do lstat for UNIX calls. */
1854 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
1855 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
1856 set_bad_path_error(errno, bad_path);
1857 return(UNIXERROR(ERRDOS,ERRbadpath));
1859 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
1860 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
1861 set_bad_path_error(errno, bad_path);
1862 return(UNIXERROR(ERRDOS,ERRbadpath));
1866 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
1867 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1869 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1870 fname,info_level,tran_call,total_data));
1872 p = strrchr_m(fname,'/');
1873 if (!p)
1874 base_name = fname;
1875 else
1876 base_name = p+1;
1878 mode = dos_mode(conn,fname,&sbuf);
1879 fullpathname = fname;
1880 file_size = get_file_size(sbuf);
1881 allocation_size = get_allocation_size(fsp,&sbuf);
1882 if (mode & aDIR)
1883 file_size = 0;
1885 params = Realloc(*pparams,2);
1886 if (params == NULL)
1887 return ERROR_DOS(ERRDOS,ERRnomem);
1888 *pparams = params;
1889 memset((char *)params,'\0',2);
1890 data_size = max_data_bytes + 1024;
1891 pdata = Realloc(*ppdata, data_size);
1892 if ( pdata == NULL )
1893 return ERROR_DOS(ERRDOS,ERRnomem);
1894 *ppdata = pdata;
1896 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1897 /* uggh, EAs for OS2 */
1898 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1899 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1902 memset((char *)pdata,'\0',data_size);
1904 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1906 if (lp_dos_filetime_resolution(SNUM(conn))) {
1907 c_time &= ~1;
1908 sbuf.st_atime &= ~1;
1909 sbuf.st_mtime &= ~1;
1910 sbuf.st_mtime &= ~1;
1913 /* NT expects the name to be in an exact form of the *full*
1914 filename. See the trans2 torture test */
1915 if (strequal(base_name,".")) {
1916 pstrcpy(dos_fname, "\\");
1917 } else {
1918 snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname);
1919 string_replace(dos_fname, '/', '\\');
1922 switch (info_level) {
1923 case SMB_INFO_STANDARD:
1924 case SMB_INFO_QUERY_EA_SIZE:
1925 data_size = (info_level==1?22:26);
1926 put_dos_date2(pdata,l1_fdateCreation,c_time);
1927 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1928 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1929 SIVAL(pdata,l1_cbFile,(uint32)file_size);
1930 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
1931 SSVAL(pdata,l1_attrFile,mode);
1932 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1933 break;
1935 case SMB_INFO_IS_NAME_VALID:
1936 if (tran_call == TRANSACT2_QFILEINFO) {
1937 /* os/2 needs this ? really ?*/
1938 return ERROR_DOS(ERRDOS,ERRbadfunc);
1940 data_size = 0;
1941 break;
1943 case SMB_INFO_QUERY_EAS_FROM_LIST:
1944 data_size = 24;
1945 put_dos_date2(pdata,0,c_time);
1946 put_dos_date2(pdata,4,sbuf.st_atime);
1947 put_dos_date2(pdata,8,sbuf.st_mtime);
1948 SIVAL(pdata,12,(uint32)file_size);
1949 SIVAL(pdata,16,(uint32)allocation_size);
1950 SIVAL(pdata,20,mode);
1951 break;
1953 case SMB_INFO_QUERY_ALL_EAS:
1954 data_size = 4;
1955 SIVAL(pdata,0,data_size);
1956 break;
1958 case SMB_FILE_BASIC_INFORMATION:
1959 case SMB_QUERY_FILE_BASIC_INFO:
1961 if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1962 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1963 else {
1964 data_size = 40;
1965 SIVAL(pdata,36,0);
1967 put_long_date(pdata,c_time);
1968 put_long_date(pdata+8,sbuf.st_atime);
1969 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1970 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1971 SIVAL(pdata,32,mode);
1973 DEBUG(5,("SMB_QFBI - "));
1975 time_t create_time = c_time;
1976 DEBUG(5,("create: %s ", ctime(&create_time)));
1978 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1979 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1980 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1981 DEBUG(5,("mode: %x\n", mode));
1983 break;
1985 case SMB_FILE_STANDARD_INFORMATION:
1986 case SMB_QUERY_FILE_STANDARD_INFO:
1988 data_size = 24;
1989 SOFF_T(pdata,0,allocation_size);
1990 SOFF_T(pdata,8,file_size);
1991 SIVAL(pdata,16,sbuf.st_nlink);
1992 SCVAL(pdata,20,0);
1993 SCVAL(pdata,21,(mode&aDIR)?1:0);
1994 break;
1996 case SMB_FILE_EA_INFORMATION:
1997 case SMB_QUERY_FILE_EA_INFO:
1998 data_size = 4;
1999 break;
2001 /* Get the 8.3 name - used if NT SMB was negotiated. */
2002 case SMB_QUERY_FILE_ALT_NAME_INFO:
2003 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2005 pstring short_name;
2007 pstrcpy(short_name,base_name);
2008 /* Mangle if not already 8.3 */
2009 if(!mangle_is_8_3(short_name, True)) {
2010 mangle_map(short_name,True,True,SNUM(conn));
2012 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2013 data_size = 4 + len;
2014 SIVAL(pdata,0,len);
2015 break;
2018 case SMB_QUERY_FILE_NAME_INFO:
2020 this must be *exactly* right for ACLs on mapped drives to work
2022 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2023 data_size = 4 + len;
2024 SIVAL(pdata,0,len);
2025 break;
2027 case SMB_FILE_ALLOCATION_INFORMATION:
2028 case SMB_QUERY_FILE_ALLOCATION_INFO:
2029 data_size = 8;
2030 SOFF_T(pdata,0,allocation_size);
2031 break;
2033 case SMB_FILE_END_OF_FILE_INFORMATION:
2034 case SMB_QUERY_FILE_END_OF_FILEINFO:
2035 data_size = 8;
2036 SOFF_T(pdata,0,file_size);
2037 break;
2039 case SMB_QUERY_FILE_ALL_INFO:
2040 case SMB_FILE_ALL_INFORMATION:
2041 put_long_date(pdata,c_time);
2042 put_long_date(pdata+8,sbuf.st_atime);
2043 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2044 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2045 SIVAL(pdata,32,mode);
2046 pdata += 40;
2047 SOFF_T(pdata,0,allocation_size);
2048 SOFF_T(pdata,8,file_size);
2049 SIVAL(pdata,16,sbuf.st_nlink);
2050 SCVAL(pdata,20,delete_pending);
2051 SCVAL(pdata,21,(mode&aDIR)?1:0);
2052 pdata += 24;
2053 pdata += 4; /* EA info */
2054 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_TERMINATE);
2055 SIVAL(pdata,0,len);
2056 pdata += 4 + len;
2057 data_size = PTR_DIFF(pdata,(*ppdata));
2058 break;
2060 case SMB_FILE_INTERNAL_INFORMATION:
2061 /* This should be an index number - looks like
2062 dev/ino to me :-)
2064 I think this causes us to fail the IFSKIT
2065 BasicFileInformationTest. -tpot */
2067 SIVAL(pdata,0,sbuf.st_dev);
2068 SIVAL(pdata,4,sbuf.st_ino);
2069 data_size = 8;
2070 break;
2072 case SMB_FILE_ACCESS_INFORMATION:
2073 SIVAL(pdata,0,0x12019F); /* ??? */
2074 data_size = 4;
2075 break;
2077 case SMB_FILE_NAME_INFORMATION:
2078 /* Pathname with leading '\'. */
2080 size_t byte_len;
2081 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2082 SIVAL(pdata,0,byte_len);
2083 data_size = 4 + byte_len;
2084 break;
2087 case SMB_FILE_DISPOSITION_INFORMATION:
2088 data_size = 1;
2089 SCVAL(pdata,0,delete_pending);
2090 break;
2092 case SMB_FILE_POSITION_INFORMATION:
2093 data_size = 8;
2094 SOFF_T(pdata,0,pos);
2095 break;
2097 case SMB_FILE_MODE_INFORMATION:
2098 SIVAL(pdata,0,mode);
2099 data_size = 4;
2100 break;
2102 case SMB_FILE_ALIGNMENT_INFORMATION:
2103 SIVAL(pdata,0,0); /* No alignment needed. */
2104 data_size = 4;
2105 break;
2107 #if 0
2109 * NT4 server just returns "invalid query" to this - if we try to answer
2110 * it then NTws gets a BSOD! (tridge).
2111 * W2K seems to want this. JRA.
2113 case SMB_QUERY_FILE_STREAM_INFO:
2114 #endif
2115 case SMB_FILE_STREAM_INFORMATION:
2116 if (mode & aDIR) {
2117 data_size = 0;
2118 } else {
2119 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2120 SIVAL(pdata,0,0); /* ??? */
2121 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2122 SOFF_T(pdata,8,file_size);
2123 SIVAL(pdata,16,allocation_size);
2124 SIVAL(pdata,20,0); /* ??? */
2125 data_size = 24 + byte_len;
2127 break;
2129 case SMB_QUERY_COMPRESSION_INFO:
2130 case SMB_FILE_COMPRESSION_INFORMATION:
2131 SOFF_T(pdata,0,file_size);
2132 SIVAL(pdata,8,0); /* ??? */
2133 SIVAL(pdata,12,0); /* ??? */
2134 data_size = 16;
2135 break;
2137 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2138 put_long_date(pdata,c_time);
2139 put_long_date(pdata+8,sbuf.st_atime);
2140 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2141 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2142 SIVAL(pdata,32,allocation_size);
2143 SOFF_T(pdata,40,file_size);
2144 SIVAL(pdata,48,mode);
2145 SIVAL(pdata,52,0); /* ??? */
2146 data_size = 56;
2147 break;
2149 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2150 SIVAL(pdata,0,mode);
2151 SIVAL(pdata,4,0);
2152 data_size = 8;
2153 break;
2156 * CIFS UNIX Extensions.
2159 case SMB_QUERY_FILE_UNIX_BASIC:
2161 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2163 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2164 pdata += 8;
2166 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2167 pdata += 8;
2169 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2170 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2171 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2172 pdata += 24;
2174 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2175 SIVAL(pdata,4,0);
2176 pdata += 8;
2178 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2179 SIVAL(pdata,4,0);
2180 pdata += 8;
2182 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2183 pdata += 4;
2185 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2186 SIVAL(pdata,4,0);
2187 pdata += 8;
2189 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2190 SIVAL(pdata,4,0);
2191 pdata += 8;
2193 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2194 pdata += 8;
2196 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2197 SIVAL(pdata,4,0);
2198 pdata += 8;
2200 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2201 SIVAL(pdata,4,0);
2202 pdata += 8+1;
2203 data_size = PTR_DIFF(pdata,(*ppdata));
2206 int i;
2207 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2209 for (i=0; i<100; i++)
2210 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2211 DEBUG(4,("\n"));
2214 break;
2216 case SMB_QUERY_FILE_UNIX_LINK:
2218 pstring buffer;
2220 #ifdef S_ISLNK
2221 if(!S_ISLNK(sbuf.st_mode))
2222 return(UNIXERROR(ERRSRV,ERRbadlink));
2223 #else
2224 return(UNIXERROR(ERRDOS,ERRbadlink));
2225 #endif
2226 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2227 if (len == -1)
2228 return(UNIXERROR(ERRDOS,ERRnoaccess));
2229 buffer[len] = 0;
2230 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2231 pdata += len;
2232 data_size = PTR_DIFF(pdata,(*ppdata));
2234 break;
2237 default:
2238 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2241 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size);
2243 return(-1);
2246 /****************************************************************************
2247 Deal with the internal needs of setting the delete on close flag. Note that
2248 as the tdb locking is recursive, it is safe to call this from within
2249 open_file_shared. JRA.
2250 ****************************************************************************/
2252 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2255 * Only allow delete on close for writable shares.
2258 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2259 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2260 fsp->fsp_name ));
2261 return NT_STATUS_ACCESS_DENIED;
2264 * Only allow delete on close for files/directories opened with delete intent.
2267 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2268 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2269 fsp->fsp_name ));
2270 return NT_STATUS_ACCESS_DENIED;
2273 if(fsp->is_directory) {
2274 fsp->directory_delete_on_close = delete_on_close;
2275 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2276 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2277 } else {
2278 fsp->delete_on_close = delete_on_close;
2279 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2280 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2283 return NT_STATUS_OK;
2286 /****************************************************************************
2287 Sets the delete on close flag over all share modes on this file.
2288 Modify the share mode entry for all files open
2289 on this device and inode to tell other smbds we have
2290 changed the delete on close flag. This will be noticed
2291 in the close code, the last closer will delete the file
2292 if flag is set.
2293 ****************************************************************************/
2295 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2297 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2298 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2300 if (fsp->is_directory || fsp->is_stat)
2301 return NT_STATUS_OK;
2303 if (lock_share_entry_fsp(fsp) == False)
2304 return NT_STATUS_ACCESS_DENIED;
2306 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2307 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2308 fsp->fsp_name ));
2309 unlock_share_entry_fsp(fsp);
2310 return NT_STATUS_ACCESS_DENIED;
2313 unlock_share_entry_fsp(fsp);
2314 return NT_STATUS_OK;
2317 /****************************************************************************
2318 Returns true if this pathname is within the share, and thus safe.
2319 ****************************************************************************/
2321 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2323 #ifdef PATH_MAX
2324 char resolved_name[PATH_MAX+1];
2325 #else
2326 pstring resolved_name;
2327 #endif
2328 fstring last_component;
2329 pstring link_dest;
2330 pstring link_test;
2331 char *p;
2332 BOOL bad_path = False;
2333 SMB_STRUCT_STAT sbuf;
2335 pstrcpy(link_dest, link_dest_in);
2336 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2338 /* Store the UNIX converted path. */
2339 pstrcpy(link_dest_out, link_dest);
2341 p = strrchr(link_dest, '/');
2342 if (p) {
2343 fstrcpy(last_component, p+1);
2344 *p = '\0';
2345 } else {
2346 fstrcpy(last_component, link_dest);
2347 pstrcpy(link_dest, "./");
2350 if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL)
2351 return -1;
2353 pstrcpy(link_dest, resolved_name);
2354 pstrcat(link_dest, "/");
2355 pstrcat(link_dest, last_component);
2357 if (*link_dest != '/') {
2358 /* Relative path. */
2359 pstrcpy(link_test, conn->connectpath);
2360 pstrcat(link_test, "/");
2361 pstrcat(link_test, link_dest);
2362 } else {
2363 pstrcpy(link_test, link_dest);
2367 * Check if the link is within the share.
2370 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2371 errno = EACCES;
2372 return -1;
2374 return 0;
2377 /****************************************************************************
2378 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2379 ****************************************************************************/
2381 static int call_trans2setfilepathinfo(connection_struct *conn,
2382 char *inbuf, char *outbuf, int length, int bufsize,
2383 char **pparams, int total_params, char **ppdata, int total_data)
2385 char *params = *pparams;
2386 char *pdata = *ppdata;
2387 uint16 tran_call = SVAL(inbuf, smb_setup0);
2388 uint16 info_level;
2389 int dosmode=0;
2390 SMB_OFF_T size=0;
2391 struct utimbuf tvs;
2392 SMB_STRUCT_STAT sbuf;
2393 pstring fname;
2394 int fd = -1;
2395 BOOL bad_path = False;
2396 files_struct *fsp = NULL;
2397 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2398 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2399 mode_t unixmode = 0;
2401 if (!params)
2402 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2404 if (tran_call == TRANSACT2_SETFILEINFO) {
2405 if (total_params < 4)
2406 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2408 fsp = file_fsp(params,0);
2409 info_level = SVAL(params,2);
2411 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2413 * This is actually a SETFILEINFO on a directory
2414 * handle (returned from an NT SMB). NT5.0 seems
2415 * to do this call. JRA.
2417 pstrcpy(fname, fsp->fsp_name);
2418 unix_convert(fname,conn,0,&bad_path,&sbuf);
2419 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2420 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2421 set_bad_path_error(errno, bad_path);
2422 return(UNIXERROR(ERRDOS,ERRbadpath));
2424 } else if (fsp && fsp->print_file) {
2426 * Doing a DELETE_ON_CLOSE should cancel a print job.
2428 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
2429 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2431 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
2433 SSVAL(params,0,0);
2434 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2435 return(-1);
2436 } else
2437 return (UNIXERROR(ERRDOS,ERRbadpath));
2438 } else {
2440 * Original code - this is an open file.
2442 CHECK_FSP(fsp,conn);
2444 pstrcpy(fname, fsp->fsp_name);
2445 fd = fsp->fd;
2447 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
2448 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2449 return(UNIXERROR(ERRDOS,ERRbadfid));
2452 } else {
2453 /* set path info */
2454 if (total_params < 6)
2455 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2457 info_level = SVAL(params,0);
2458 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
2459 unix_convert(fname,conn,0,&bad_path,&sbuf);
2460 if(!check_name(fname, conn)) {
2461 set_bad_path_error(errno, bad_path);
2462 return(UNIXERROR(ERRDOS,ERRbadpath));
2466 * For CIFS UNIX extensions the target name may not exist.
2469 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2470 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
2471 set_bad_path_error(errno, bad_path);
2472 return(UNIXERROR(ERRDOS,ERRbadpath));
2476 if (!CAN_WRITE(conn))
2477 return ERROR_DOS(ERRSRV,ERRaccess);
2479 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2480 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2482 if (VALID_STAT(sbuf))
2483 unixmode = sbuf.st_mode;
2485 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
2486 tran_call,fname,info_level,total_data));
2488 /* Realloc the parameter and data sizes */
2489 params = Realloc(*pparams,2);
2490 if(params == NULL)
2491 return ERROR_DOS(ERRDOS,ERRnomem);
2492 *pparams = params;
2494 SSVAL(params,0,0);
2496 if (fsp) {
2497 /* the pending modtime overrides the current modtime */
2498 sbuf.st_mtime = fsp->pending_modtime;
2501 size = get_file_size(sbuf);
2502 tvs.modtime = sbuf.st_mtime;
2503 tvs.actime = sbuf.st_atime;
2504 dosmode = dos_mode(conn,fname,&sbuf);
2505 unixmode = sbuf.st_mode;
2507 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2508 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2510 switch (info_level) {
2511 case SMB_INFO_STANDARD:
2513 if (total_data < l1_cbFile+4)
2514 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2516 /* access time */
2517 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2519 /* write time */
2520 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2522 dosmode = SVAL(pdata,l1_attrFile);
2523 size = IVAL(pdata,l1_cbFile);
2525 break;
2528 case SMB_INFO_SET_EA:
2529 return(ERROR_DOS(ERRDOS,ERReasnotsupported));
2531 /* XXXX um, i don't think this is right.
2532 it's also not in the cifs6.txt spec.
2534 case SMB_INFO_QUERY_EAS_FROM_LIST:
2535 if (total_data < 28)
2536 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2538 tvs.actime = make_unix_date2(pdata+8);
2539 tvs.modtime = make_unix_date2(pdata+12);
2540 size = IVAL(pdata,16);
2541 dosmode = IVAL(pdata,24);
2542 break;
2544 /* XXXX nor this. not in cifs6.txt, either. */
2545 case SMB_INFO_QUERY_ALL_EAS:
2546 if (total_data < 28)
2547 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2549 tvs.actime = make_unix_date2(pdata+8);
2550 tvs.modtime = make_unix_date2(pdata+12);
2551 size = IVAL(pdata,16);
2552 dosmode = IVAL(pdata,24);
2553 break;
2555 case SMB_SET_FILE_BASIC_INFO:
2556 case SMB_FILE_BASIC_INFORMATION:
2558 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2559 time_t write_time;
2560 time_t changed_time;
2562 if (total_data < 36)
2563 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2565 /* Ignore create time at offset pdata. */
2567 /* access time */
2568 tvs.actime = interpret_long_date(pdata+8);
2570 write_time = interpret_long_date(pdata+16);
2571 changed_time = interpret_long_date(pdata+24);
2573 tvs.modtime = MIN(write_time, changed_time);
2575 if (write_time > tvs.modtime && write_time != 0xffffffff) {
2576 tvs.modtime = write_time;
2578 /* Prefer a defined time to an undefined one. */
2579 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2580 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2581 ? changed_time : write_time);
2583 /* attributes */
2584 dosmode = IVAL(pdata,32);
2585 break;
2588 case SMB_FILE_ALLOCATION_INFORMATION:
2589 case SMB_SET_FILE_ALLOCATION_INFO:
2591 int ret = -1;
2592 SMB_BIG_UINT allocation_size;
2594 if (total_data < 8)
2595 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2597 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
2598 #ifdef LARGE_SMB_OFF_T
2599 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
2600 #else /* LARGE_SMB_OFF_T */
2601 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2602 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2603 #endif /* LARGE_SMB_OFF_T */
2604 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2605 fname, (double)allocation_size ));
2607 if (allocation_size)
2608 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
2610 if(allocation_size != get_file_size(sbuf)) {
2611 SMB_STRUCT_STAT new_sbuf;
2613 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2614 fname, (double)allocation_size ));
2616 if (fd == -1) {
2617 files_struct *new_fsp = NULL;
2618 int access_mode = 0;
2619 int action = 0;
2621 if(global_oplock_break) {
2622 /* Queue this file modify as we are the process of an oplock break. */
2624 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2625 DEBUGADD(2,( "in oplock break state.\n"));
2627 push_oplock_pending_smb_message(inbuf, length);
2628 return -1;
2631 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2632 SET_OPEN_MODE(DOS_OPEN_RDWR),
2633 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2634 0, 0, &access_mode, &action);
2636 if (new_fsp == NULL)
2637 return(UNIXERROR(ERRDOS,ERRbadpath));
2638 ret = vfs_allocate_file_space(new_fsp, allocation_size);
2639 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2640 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2641 new_fsp->fnum, strerror(errno)));
2642 ret = -1;
2644 close_file(new_fsp,True);
2645 } else {
2646 ret = vfs_allocate_file_space(fsp, allocation_size);
2647 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
2648 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2649 fsp->fnum, strerror(errno)));
2650 ret = -1;
2653 if (ret == -1)
2654 return ERROR_NT(NT_STATUS_DISK_FULL);
2656 /* Allocate can truncate size... */
2657 size = get_file_size(new_sbuf);
2660 break;
2663 case SMB_FILE_END_OF_FILE_INFORMATION:
2664 case SMB_SET_FILE_END_OF_FILE_INFO:
2666 if (total_data < 8)
2667 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2669 size = IVAL(pdata,0);
2670 #ifdef LARGE_SMB_OFF_T
2671 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2672 #else /* LARGE_SMB_OFF_T */
2673 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2674 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2675 #endif /* LARGE_SMB_OFF_T */
2676 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2677 break;
2680 case SMB_FILE_DISPOSITION_INFORMATION:
2681 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2683 BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
2684 NTSTATUS status;
2686 if (total_data < 1)
2687 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2689 if (tran_call != TRANSACT2_SETFILEINFO)
2690 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2692 if (fsp == NULL)
2693 return(UNIXERROR(ERRDOS,ERRbadfid));
2695 status = set_delete_on_close_internal(fsp, delete_on_close);
2697 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2698 return ERROR_NT(status);
2700 /* The set is across all open files on this dev/inode pair. */
2701 status =set_delete_on_close_over_all(fsp, delete_on_close);
2702 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2703 return ERROR_NT(status);
2705 break;
2709 * CIFS UNIX extensions.
2712 case SMB_SET_FILE_UNIX_BASIC:
2714 uint32 raw_unixmode;
2716 if (total_data < 100)
2717 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2719 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
2720 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
2721 size=IVAL(pdata,0); /* first 8 Bytes are size */
2722 #ifdef LARGE_SMB_OFF_T
2723 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2724 #else /* LARGE_SMB_OFF_T */
2725 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2726 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2727 #endif /* LARGE_SMB_OFF_T */
2729 pdata+=24; /* ctime & st_blocks are not changed */
2730 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
2731 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
2732 pdata+=16;
2733 set_owner = (uid_t)IVAL(pdata,0);
2734 pdata += 8;
2735 set_grp = (gid_t)IVAL(pdata,0);
2736 pdata += 8;
2737 raw_unixmode = IVAL(pdata,28);
2738 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2739 dosmode = 0; /* Ensure dos mode change doesn't override this. */
2741 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2742 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2743 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2745 if (!VALID_STAT(sbuf)) {
2748 * The only valid use of this is to create character and block
2749 * devices, and named pipes. This is deprecated (IMHO) and
2750 * a new info level should be used for mknod. JRA.
2753 #if !defined(HAVE_MAKEDEV_FN)
2754 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2755 #else /* HAVE_MAKEDEV_FN */
2756 uint32 file_type = IVAL(pdata,0);
2757 uint32 dev_major = IVAL(pdata,4);
2758 uint32 dev_minor = IVAL(pdata,12);
2760 uid_t myuid = geteuid();
2761 gid_t mygid = getegid();
2762 SMB_DEV_T dev;
2764 if (tran_call == TRANSACT2_SETFILEINFO)
2765 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2767 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2768 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2770 dev = makedev(dev_major, dev_minor);
2772 /* We can only create as the owner/group we are. */
2774 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2775 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2776 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2777 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2779 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2780 file_type != UNIX_TYPE_FIFO)
2781 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2783 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2784 0%o for file %s\n", (double)dev, unixmode, fname ));
2786 /* Ok - do the mknod. */
2787 if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
2788 return(UNIXERROR(ERRDOS,ERRnoaccess));
2790 inherit_access_acl(conn, fname, unixmode);
2792 SSVAL(params,0,0);
2793 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2794 return(-1);
2795 #endif /* HAVE_MAKEDEV_FN */
2800 * Deal with the UNIX specific mode set.
2803 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
2804 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2805 (unsigned int)unixmode, fname ));
2806 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
2807 return(UNIXERROR(ERRDOS,ERRnoaccess));
2811 * Deal with the UNIX specific uid set.
2814 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
2815 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2816 (unsigned int)set_owner, fname ));
2817 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
2818 return(UNIXERROR(ERRDOS,ERRnoaccess));
2822 * Deal with the UNIX specific gid set.
2825 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
2826 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2827 (unsigned int)set_owner, fname ));
2828 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
2829 return(UNIXERROR(ERRDOS,ERRnoaccess));
2831 break;
2834 case SMB_SET_FILE_UNIX_LINK:
2836 pstring link_dest;
2837 /* Set a symbolic link. */
2838 /* Don't allow this if follow links is false. */
2840 if (!lp_symlinks(SNUM(conn)))
2841 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2843 /* Disallow if already exists. */
2844 if (VALID_STAT(sbuf))
2845 return(ERROR_DOS(ERRDOS,ERRbadpath));
2847 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2849 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2850 return(UNIXERROR(ERRDOS,ERRnoaccess));
2852 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2853 fname, link_dest ));
2855 if (SMB_VFS_SYMLINK(conn,link_dest,fname) != 0)
2856 return(UNIXERROR(ERRDOS,ERRnoaccess));
2857 SSVAL(params,0,0);
2858 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2859 return(-1);
2862 case SMB_SET_FILE_UNIX_HLINK:
2864 pstring link_dest;
2866 /* Set a hard link. */
2868 /* Disallow if already exists. */
2869 if (VALID_STAT(sbuf))
2870 return(ERROR_DOS(ERRDOS,ERRbadpath));
2872 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2874 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2875 return(UNIXERROR(ERRDOS,ERRnoaccess));
2877 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2878 fname, link_dest ));
2880 if (SMB_VFS_LINK(conn,link_dest,fname) != 0)
2881 return(UNIXERROR(ERRDOS,ERRnoaccess));
2882 SSVAL(params,0,0);
2883 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2884 return(-1);
2887 default:
2888 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2891 /* get some defaults (no modifications) if any info is zero or -1. */
2892 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2893 tvs.actime = sbuf.st_atime;
2895 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2896 tvs.modtime = sbuf.st_mtime;
2898 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2899 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2900 DEBUG(6,("size: %.0f ", (double)size));
2902 if (S_ISDIR(sbuf.st_mode))
2903 dosmode |= aDIR;
2904 else
2905 dosmode &= ~aDIR;
2907 DEBUG(6,("dosmode: %x\n" , dosmode));
2909 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2910 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2911 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2912 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2915 * Only do this test if we are not explicitly
2916 * changing the size of a file.
2918 if (!size)
2919 size = get_file_size(sbuf);
2923 * Try and set the times, size and mode of this file -
2924 * if they are different from the current values
2926 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2927 if(fsp != NULL) {
2929 * This was a setfileinfo on an open file.
2930 * NT does this a lot. It's actually pointless
2931 * setting the time here, as it will be overwritten
2932 * on the next write, so we save the request
2933 * away and will set it on file close. JRA.
2936 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2937 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
2938 fsp->pending_modtime = tvs.modtime;
2941 } else {
2943 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2945 if(file_utime(conn, fname, &tvs)!=0)
2946 return(UNIXERROR(ERRDOS,ERRnoaccess));
2950 /* check the mode isn't different, before changing it */
2951 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
2953 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
2955 if(file_chmod(conn, fname, dosmode, NULL)) {
2956 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2957 return(UNIXERROR(ERRDOS,ERRnoaccess));
2961 if (size != get_file_size(sbuf)) {
2963 int ret;
2965 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2966 fname, (double)size ));
2968 if (fd == -1) {
2969 files_struct *new_fsp = NULL;
2970 int access_mode = 0;
2971 int action = 0;
2973 if(global_oplock_break) {
2974 /* Queue this file modify as we are the process of an oplock break. */
2976 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2977 DEBUGADD(2,( "in oplock break state.\n"));
2979 push_oplock_pending_smb_message(inbuf, length);
2980 return -1;
2983 new_fsp = open_file_shared(conn, fname, &sbuf,
2984 SET_OPEN_MODE(DOS_OPEN_RDWR),
2985 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2986 0, 0, &access_mode, &action);
2988 if (new_fsp == NULL)
2989 return(UNIXERROR(ERRDOS,ERRbadpath));
2990 ret = vfs_set_filelen(new_fsp, size);
2991 close_file(new_fsp,True);
2992 } else {
2993 ret = vfs_set_filelen(fsp, size);
2996 if (ret == -1)
2997 return (UNIXERROR(ERRHRD,ERRdiskfull));
3000 SSVAL(params,0,0);
3001 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3003 return(-1);
3006 /****************************************************************************
3007 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3008 ****************************************************************************/
3010 static int call_trans2mkdir(connection_struct *conn,
3011 char *inbuf, char *outbuf, int length, int bufsize,
3012 char **pparams, int total_params, char **ppdata, int total_data)
3014 char *params = *pparams;
3015 pstring directory;
3016 int ret = -1;
3017 SMB_STRUCT_STAT sbuf;
3018 BOOL bad_path = False;
3020 if (!CAN_WRITE(conn))
3021 return ERROR_DOS(ERRSRV,ERRaccess);
3023 if (total_params < 4)
3024 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3026 srvstr_pull(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE);
3028 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3030 unix_convert(directory,conn,0,&bad_path,&sbuf);
3031 if (check_name(directory,conn))
3032 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3034 if(ret < 0) {
3035 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3036 set_bad_path_error(errno, bad_path);
3037 return(UNIXERROR(ERRDOS,ERRnoaccess));
3040 /* Realloc the parameter and data sizes */
3041 params = Realloc(*pparams,2);
3042 if(params == NULL)
3043 return ERROR_DOS(ERRDOS,ERRnomem);
3044 *pparams = params;
3046 SSVAL(params,0,0);
3048 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3050 return(-1);
3053 /****************************************************************************
3054 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3055 We don't actually do this - we just send a null response.
3056 ****************************************************************************/
3058 static int call_trans2findnotifyfirst(connection_struct *conn,
3059 char *inbuf, char *outbuf, int length, int bufsize,
3060 char **pparams, int total_params, char **ppdata, int total_data)
3062 static uint16 fnf_handle = 257;
3063 char *params = *pparams;
3064 uint16 info_level;
3066 if (total_params < 6)
3067 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3069 info_level = SVAL(params,4);
3070 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3072 switch (info_level) {
3073 case 1:
3074 case 2:
3075 break;
3076 default:
3077 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3080 /* Realloc the parameter and data sizes */
3081 params = Realloc(*pparams,6);
3082 if(params == NULL)
3083 return ERROR_DOS(ERRDOS,ERRnomem);
3084 *pparams = params;
3086 SSVAL(params,0,fnf_handle);
3087 SSVAL(params,2,0); /* No changes */
3088 SSVAL(params,4,0); /* No EA errors */
3090 fnf_handle++;
3092 if(fnf_handle == 0)
3093 fnf_handle = 257;
3095 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3097 return(-1);
3100 /****************************************************************************
3101 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3102 changes). Currently this does nothing.
3103 ****************************************************************************/
3105 static int call_trans2findnotifynext(connection_struct *conn,
3106 char *inbuf, char *outbuf, int length, int bufsize,
3107 char **pparams, int total_params, char **ppdata, int total_data)
3109 char *params = *pparams;
3111 DEBUG(3,("call_trans2findnotifynext\n"));
3113 /* Realloc the parameter and data sizes */
3114 params = Realloc(*pparams,4);
3115 if(params == NULL)
3116 return ERROR_DOS(ERRDOS,ERRnomem);
3117 *pparams = params;
3119 SSVAL(params,0,0); /* No changes */
3120 SSVAL(params,2,0); /* No EA errors */
3122 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3124 return(-1);
3127 /****************************************************************************
3128 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3129 ****************************************************************************/
3131 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3132 char* outbuf, int length, int bufsize,
3133 char **pparams, int total_params, char **ppdata, int total_data)
3135 char *params = *pparams;
3136 pstring pathname;
3137 int reply_size = 0;
3138 int max_referral_level;
3140 DEBUG(10,("call_trans2getdfsreferral\n"));
3142 if (total_params < 2)
3143 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3145 max_referral_level = SVAL(params,0);
3147 if(!lp_host_msdfs())
3148 return ERROR_DOS(ERRDOS,ERRbadfunc);
3150 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
3152 if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
3153 return ERROR_DOS(ERRDOS,ERRbadfile);
3155 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3156 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3158 return(-1);
3161 #define LMCAT_SPL 0x53
3162 #define LMFUNC_GETJOBID 0x60
3164 /****************************************************************************
3165 Reply to a TRANS2_IOCTL - used for OS/2 printing.
3166 ****************************************************************************/
3168 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3169 char* outbuf, int length, int bufsize,
3170 char **pparams, int total_params, char **ppdata, int total_data)
3172 char *pdata = *ppdata;
3173 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3175 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3176 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3177 pdata = Realloc(*ppdata, 32);
3178 if(pdata == NULL)
3179 return ERROR_DOS(ERRDOS,ERRnomem);
3180 *ppdata = pdata;
3182 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3183 CAN ACCEPT THIS IN UNICODE. JRA. */
3185 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
3186 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3187 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3188 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3189 return(-1);
3190 } else {
3191 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3192 return ERROR_DOS(ERRSRV,ERRerror);
3196 /****************************************************************************
3197 Reply to a SMBfindclose (stop trans2 directory search).
3198 ****************************************************************************/
3200 int reply_findclose(connection_struct *conn,
3201 char *inbuf,char *outbuf,int length,int bufsize)
3203 int outsize = 0;
3204 int dptr_num=SVALS(inbuf,smb_vwv0);
3205 START_PROFILE(SMBfindclose);
3207 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3209 dptr_close(&dptr_num);
3211 outsize = set_message(outbuf,0,0,True);
3213 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3215 END_PROFILE(SMBfindclose);
3216 return(outsize);
3219 /****************************************************************************
3220 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3221 ****************************************************************************/
3223 int reply_findnclose(connection_struct *conn,
3224 char *inbuf,char *outbuf,int length,int bufsize)
3226 int outsize = 0;
3227 int dptr_num= -1;
3228 START_PROFILE(SMBfindnclose);
3230 dptr_num = SVAL(inbuf,smb_vwv0);
3232 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3234 /* We never give out valid handles for a
3235 findnotifyfirst - so any dptr_num is ok here.
3236 Just ignore it. */
3238 outsize = set_message(outbuf,0,0,True);
3240 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3242 END_PROFILE(SMBfindnclose);
3243 return(outsize);
3246 /****************************************************************************
3247 Reply to a SMBtranss2 - just ignore it!
3248 ****************************************************************************/
3250 int reply_transs2(connection_struct *conn,
3251 char *inbuf,char *outbuf,int length,int bufsize)
3253 START_PROFILE(SMBtranss2);
3254 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3255 END_PROFILE(SMBtranss2);
3256 return(-1);
3259 /****************************************************************************
3260 Reply to a SMBtrans2.
3261 ****************************************************************************/
3263 int reply_trans2(connection_struct *conn,
3264 char *inbuf,char *outbuf,int length,int bufsize)
3266 int outsize = 0;
3267 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3268 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3269 #if 0
3270 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3271 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3272 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3273 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3274 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3275 int32 timeout = IVALS(inbuf,smb_timeout);
3276 #endif
3277 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3278 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3279 char *params = NULL, *data = NULL;
3280 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
3281 START_PROFILE(SMBtrans2);
3283 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3284 /* Queue this open message as we are the process of an
3285 * oplock break. */
3287 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3288 DEBUGADD(2,( "in oplock break state.\n"));
3290 push_oplock_pending_smb_message(inbuf, length);
3291 END_PROFILE(SMBtrans2);
3292 return -1;
3295 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3296 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3297 END_PROFILE(SMBtrans2);
3298 return ERROR_DOS(ERRSRV,ERRaccess);
3301 outsize = set_message(outbuf,0,0,True);
3303 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3304 is so as a sanity check */
3305 if (suwcnt != 1) {
3307 * Need to have rc=0 for ioctl to get job id for OS/2.
3308 * Network printing will fail if function is not successful.
3309 * Similar function in reply.c will be used if protocol
3310 * is LANMAN1.0 instead of LM1.2X002.
3311 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3312 * outbuf doesn't have to be set(only job id is used).
3314 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3315 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3316 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3317 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3318 } else {
3319 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
3320 DEBUG(2,("Transaction is %d\n",tran_call));
3321 END_PROFILE(SMBtrans2);
3322 ERROR_DOS(ERRDOS,ERRinvalidparam);
3326 /* Allocate the space for the maximum needed parameters and data */
3327 if (total_params > 0)
3328 params = (char *)malloc(total_params);
3329 if (total_data > 0)
3330 data = (char *)malloc(total_data);
3332 if ((total_params && !params) || (total_data && !data)) {
3333 DEBUG(2,("Out of memory in reply_trans2\n"));
3334 SAFE_FREE(params);
3335 SAFE_FREE(data);
3336 END_PROFILE(SMBtrans2);
3337 return ERROR_DOS(ERRDOS,ERRnomem);
3340 /* Copy the param and data bytes sent with this request into
3341 the params buffer */
3342 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3343 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3345 if (num_params > total_params || num_data > total_data)
3346 exit_server("invalid params in reply_trans2");
3348 if(params) {
3349 unsigned int psoff = SVAL(inbuf, smb_psoff);
3350 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
3351 goto bad_param;
3352 if (smb_base(inbuf) + psoff + num_params > inbuf + length)
3353 goto bad_param;
3354 memcpy( params, smb_base(inbuf) + psoff, num_params);
3356 if(data) {
3357 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
3358 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
3359 goto bad_param;
3360 if (smb_base(inbuf) + dsoff + num_data > inbuf + length)
3361 goto bad_param;
3362 memcpy( data, smb_base(inbuf) + dsoff, num_data);
3365 if(num_data_sofar < total_data || num_params_sofar < total_params) {
3366 /* We need to send an interim response then receive the rest
3367 of the parameter/data bytes */
3368 outsize = set_message(outbuf,0,0,True);
3369 if (!send_smb(smbd_server_fd(),outbuf))
3370 exit_server("reply_trans2: send_smb failed.");
3372 while (num_data_sofar < total_data ||
3373 num_params_sofar < total_params) {
3374 BOOL ret;
3375 unsigned int param_disp;
3376 unsigned int param_off;
3377 unsigned int data_disp;
3378 unsigned int data_off;
3380 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3382 if ((ret &&
3383 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3384 outsize = set_message(outbuf,0,0,True);
3385 if(ret)
3386 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3387 else
3388 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3389 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3390 goto bad_param;
3393 /* Revise total_params and total_data in case
3394 they have changed downwards */
3395 if (SVAL(inbuf, smb_tpscnt) < total_params)
3396 total_params = SVAL(inbuf, smb_tpscnt);
3397 if (SVAL(inbuf, smb_tdscnt) < total_data)
3398 total_data = SVAL(inbuf, smb_tdscnt);
3400 num_params = SVAL(inbuf,smb_spscnt);
3401 param_off = SVAL(inbuf, smb_spsoff);
3402 param_disp = SVAL(inbuf, smb_spsdisp);
3403 num_params_sofar += num_params;
3405 num_data = SVAL(inbuf, smb_sdscnt);
3406 data_off = SVAL(inbuf, smb_sdsoff);
3407 data_disp = SVAL(inbuf, smb_sdsdisp);
3408 num_data_sofar += num_data;
3410 if (num_params_sofar > total_params || num_data_sofar > total_data)
3411 goto bad_param;
3413 if (num_params) {
3414 if (param_disp + num_params >= total_params)
3415 goto bad_param;
3416 if ((param_disp + num_params < param_disp) ||
3417 (param_disp + num_params < num_params))
3418 goto bad_param;
3419 if (smb_base(inbuf) + param_off + num_params >= inbuf + bufsize)
3420 goto bad_param;
3421 if (params + param_disp < params)
3422 goto bad_param;
3424 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
3426 if (num_data) {
3427 if (data_disp + num_data >= total_data)
3428 goto bad_param;
3429 if ((data_disp + num_data < data_disp) ||
3430 (data_disp + num_data < num_data))
3431 goto bad_param;
3432 if (smb_base(inbuf) + data_off + num_data >= inbuf + bufsize)
3433 goto bad_param;
3434 if (data + data_disp < data)
3435 goto bad_param;
3437 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
3442 if (Protocol >= PROTOCOL_NT1) {
3443 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
3446 /* Now we must call the relevant TRANS2 function */
3447 switch(tran_call) {
3448 case TRANSACT2_OPEN:
3449 START_PROFILE_NESTED(Trans2_open);
3450 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
3451 &params, total_params, &data, total_data);
3452 END_PROFILE_NESTED(Trans2_open);
3453 break;
3455 case TRANSACT2_FINDFIRST:
3456 START_PROFILE_NESTED(Trans2_findfirst);
3457 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3458 &params, total_params, &data, total_data);
3459 END_PROFILE_NESTED(Trans2_findfirst);
3460 break;
3462 case TRANSACT2_FINDNEXT:
3463 START_PROFILE_NESTED(Trans2_findnext);
3464 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
3465 &params, total_params, &data, total_data);
3466 END_PROFILE_NESTED(Trans2_findnext);
3467 break;
3469 case TRANSACT2_QFSINFO:
3470 START_PROFILE_NESTED(Trans2_qfsinfo);
3471 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3472 &params, total_params, &data, total_data);
3473 END_PROFILE_NESTED(Trans2_qfsinfo);
3474 break;
3476 #ifdef HAVE_SYS_QUOTAS
3477 case TRANSACT2_SETFSINFO:
3478 START_PROFILE_NESTED(Trans2_setfsinfo);
3479 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
3480 &params, total_params, &data, total_data);
3481 END_PROFILE_NESTED(Trans2_setfsinfo);
3482 break;
3483 #endif
3484 case TRANSACT2_QPATHINFO:
3485 case TRANSACT2_QFILEINFO:
3486 START_PROFILE_NESTED(Trans2_qpathinfo);
3487 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3488 &params, total_params, &data, total_data);
3489 END_PROFILE_NESTED(Trans2_qpathinfo);
3490 break;
3491 case TRANSACT2_SETPATHINFO:
3492 case TRANSACT2_SETFILEINFO:
3493 START_PROFILE_NESTED(Trans2_setpathinfo);
3494 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3495 &params, total_params, &data, total_data);
3496 END_PROFILE_NESTED(Trans2_setpathinfo);
3497 break;
3499 case TRANSACT2_FINDNOTIFYFIRST:
3500 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3501 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
3502 &params, total_params, &data, total_data);
3503 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3504 break;
3506 case TRANSACT2_FINDNOTIFYNEXT:
3507 START_PROFILE_NESTED(Trans2_findnotifynext);
3508 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
3509 &params, total_params, &data, total_data);
3510 END_PROFILE_NESTED(Trans2_findnotifynext);
3511 break;
3512 case TRANSACT2_MKDIR:
3513 START_PROFILE_NESTED(Trans2_mkdir);
3514 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3515 &params, total_params, &data, total_data);
3516 END_PROFILE_NESTED(Trans2_mkdir);
3517 break;
3519 case TRANSACT2_GET_DFS_REFERRAL:
3520 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3521 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3522 &params, total_params, &data, total_data);
3523 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3524 break;
3525 case TRANSACT2_IOCTL:
3526 START_PROFILE_NESTED(Trans2_ioctl);
3527 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3528 &params, total_params, &data, total_data);
3529 END_PROFILE_NESTED(Trans2_ioctl);
3530 break;
3531 default:
3532 /* Error in request */
3533 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3534 SAFE_FREE(params);
3535 SAFE_FREE(data);
3536 END_PROFILE(SMBtrans2);
3537 return ERROR_DOS(ERRSRV,ERRerror);
3540 /* As we do not know how many data packets will need to be
3541 returned here the various call_trans2xxxx calls
3542 must send their own. Thus a call_trans2xxx routine only
3543 returns a value other than -1 when it wants to send
3544 an error packet.
3547 SAFE_FREE(params);
3548 SAFE_FREE(data);
3549 END_PROFILE(SMBtrans2);
3550 return outsize; /* If a correct response was needed the
3551 call_trans2xxx calls have already sent
3552 it. If outsize != -1 then it is returning */
3554 bad_param:
3556 SAFE_FREE(params);
3557 SAFE_FREE(data);
3558 END_PROFILE(SMBtrans2);
3559 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);