Prefix VFS API macros with SMB_ for consistency and to avoid problems with VFS_ macro...
[Samba/gebeck_regimport.git] / source / smbd / trans2.c
blob731fb9643bb9055a6e30f8745c7c8711ca1b755d
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 SSVAL(p, 0, len);
687 } else {
688 SSVAL(p,0,0);
689 *(p+2) = 0;
691 p += 2 + 24;
692 len = srvstr_push(outbuf, p, fname, -1, 0);
693 SIVAL(q,0,len);
694 p += len;
695 len = PTR_DIFF(p, pdata);
696 len = (len + 3) & ~3;
697 SIVAL(pdata,0,len);
698 p = pdata + len;
699 break;
701 case SMB_FIND_FILE_DIRECTORY_INFO:
702 p += 4;
703 SIVAL(p,0,reskey); p += 4;
704 put_long_date(p,cdate); p += 8;
705 put_long_date(p,adate); p += 8;
706 put_long_date(p,mdate); p += 8;
707 put_long_date(p,mdate); p += 8;
708 SOFF_T(p,0,file_size);
709 SOFF_T(p,8,allocation_size);
710 p += 16;
711 SIVAL(p,0,nt_extmode); p += 4;
712 p += 4;
713 len = srvstr_push(outbuf, p, fname, -1, 0);
714 SIVAL(p, -4, len);
715 p += len;
716 len = PTR_DIFF(p, pdata);
717 len = (len + 3) & ~3;
718 SIVAL(pdata,0,len);
719 p = pdata + len;
720 break;
722 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
723 p += 4;
724 SIVAL(p,0,reskey); p += 4;
725 put_long_date(p,cdate); p += 8;
726 put_long_date(p,adate); p += 8;
727 put_long_date(p,mdate); p += 8;
728 put_long_date(p,mdate); p += 8;
729 SOFF_T(p,0,file_size);
730 SOFF_T(p,8,allocation_size);
731 p += 16;
732 SIVAL(p,0,nt_extmode); p += 4;
733 p += 4;
734 SIVAL(p,0,0); p += 4;
736 len = srvstr_push(outbuf, p, fname, -1, 0);
737 SIVAL(p, -4, len);
738 p += len;
740 len = PTR_DIFF(p, pdata);
741 len = (len + 3) & ~3;
742 SIVAL(pdata,0,len);
743 p = pdata + len;
744 break;
746 case SMB_FIND_FILE_NAMES_INFO:
747 p += 4;
748 SIVAL(p,0,reskey); p += 4;
749 p += 4;
750 /* this must *not* be null terminated or w2k gets in a loop trying to set an
751 acl on a dir (tridge) */
752 len = srvstr_push(outbuf, p, fname, -1, 0);
753 SIVAL(p, -4, len);
754 p += len;
755 len = PTR_DIFF(p, pdata);
756 len = (len + 3) & ~3;
757 SIVAL(pdata,0,len);
758 p = pdata + len;
759 break;
761 /* CIFS UNIX Extension. */
763 case SMB_FIND_FILE_UNIX:
764 p+= 4;
765 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
767 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
768 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
769 p+= 8;
771 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
772 p+= 8;
774 put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */
775 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
776 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
777 p+= 24;
779 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
780 SIVAL(p,4,0);
781 p+= 8;
783 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
784 SIVAL(p,4,0);
785 p+= 8;
787 SIVAL(p,0,unix_filetype(sbuf.st_mode));
788 p+= 4;
790 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
791 SIVAL(p,4,0);
792 p+= 8;
794 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
795 SIVAL(p,4,0);
796 p+= 8;
798 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
799 p+= 8;
801 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
802 SIVAL(p,4,0);
803 p+= 8;
805 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
806 SIVAL(p,4,0);
807 p+= 8;
809 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
810 p += len;
812 len = PTR_DIFF(p, pdata);
813 len = (len + 3) & ~3;
814 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
815 p = pdata + len;
816 /* End of SMB_QUERY_FILE_UNIX_BASIC */
818 break;
820 default:
821 return(False);
825 if (PTR_DIFF(p,pdata) > space_remaining) {
826 /* Move the dirptr back to prev_dirpos */
827 SeekDir(conn->dirptr, prev_dirpos);
828 *out_of_space = True;
829 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
830 return False; /* Not finished - just out of space */
833 /* Setup the last_filename pointer, as an offset from base_data */
834 *last_name_off = PTR_DIFF(nameptr,base_data);
835 /* Advance the data pointer to the next slot */
836 *ppdata = p;
838 return(found);
841 /****************************************************************************
842 Reply to a TRANS2_FINDFIRST.
843 ****************************************************************************/
845 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
846 char **pparams, int total_params, char **ppdata, int total_data)
848 /* We must be careful here that we don't return more than the
849 allowed number of data bytes. If this means returning fewer than
850 maxentries then so be it. We assume that the redirector has
851 enough room for the fixed number of parameter bytes it has
852 requested. */
853 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
854 char *params = *pparams;
855 char *pdata = *ppdata;
856 int dirtype = SVAL(params,0);
857 int maxentries = SVAL(params,2);
858 BOOL close_after_first = BITSETW(params+4,0);
859 BOOL close_if_end = BITSETW(params+4,1);
860 BOOL requires_resume_key = BITSETW(params+4,2);
861 int info_level = SVAL(params,6);
862 pstring directory;
863 pstring mask;
864 char *p, *wcard;
865 int last_name_off=0;
866 int dptr_num = -1;
867 int numentries = 0;
868 int i;
869 BOOL finished = False;
870 BOOL dont_descend = False;
871 BOOL out_of_space = False;
872 int space_remaining;
873 BOOL bad_path = False;
874 SMB_STRUCT_STAT sbuf;
876 if (total_params < 12)
877 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
879 *directory = *mask = 0;
881 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
882 close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
883 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
884 info_level, max_data_bytes));
886 switch (info_level) {
887 case SMB_INFO_STANDARD:
888 case SMB_INFO_QUERY_EA_SIZE:
889 case SMB_FIND_FILE_DIRECTORY_INFO:
890 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
891 case SMB_FIND_FILE_NAMES_INFO:
892 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
893 break;
894 case SMB_FIND_FILE_UNIX:
895 if (!lp_unix_extensions())
896 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
897 break;
898 default:
899 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
902 srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE);
904 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
906 unix_convert(directory,conn,0,&bad_path,&sbuf);
907 if(!check_name(directory,conn)) {
908 set_bad_path_error(errno, bad_path);
909 return(UNIXERROR(ERRDOS,ERRbadpath));
912 p = strrchr_m(directory,'/');
913 if(p == NULL) {
914 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
915 if((directory[0] == '.') && (directory[1] == '\0'))
916 pstrcpy(mask,"*");
917 else
918 pstrcpy(mask,directory);
919 pstrcpy(directory,"./");
920 } else {
921 pstrcpy(mask,p+1);
922 *p = 0;
925 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
927 pdata = Realloc(*ppdata, max_data_bytes + 1024);
928 if( pdata == NULL )
929 return(ERROR_DOS(ERRDOS,ERRnomem));
931 *ppdata = pdata;
932 memset((char *)pdata,'\0',max_data_bytes + 1024);
934 /* Realloc the params space */
935 params = Realloc(*pparams, 10);
936 if (params == NULL)
937 return ERROR_DOS(ERRDOS,ERRnomem);
938 *pparams = params;
940 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
941 if (dptr_num < 0)
942 return(UNIXERROR(ERRDOS,ERRbadfile));
944 /* Save the wildcard match and attribs we are using on this directory -
945 needed as lanman2 assumes these are being saved between calls */
947 if(!(wcard = strdup(mask))) {
948 dptr_close(&dptr_num);
949 return ERROR_DOS(ERRDOS,ERRnomem);
952 dptr_set_wcard(dptr_num, wcard);
953 dptr_set_attr(dptr_num, dirtype);
955 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
957 /* We don't need to check for VOL here as this is returned by
958 a different TRANS2 call. */
960 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
961 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
962 dont_descend = True;
964 p = pdata;
965 space_remaining = max_data_bytes;
966 out_of_space = False;
968 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
969 BOOL got_exact_match = False;
971 /* this is a heuristic to avoid seeking the dirptr except when
972 absolutely necessary. It allows for a filename of about 40 chars */
973 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
974 out_of_space = True;
975 finished = False;
976 } else {
977 finished = !get_lanman2_dir_entry(conn,
978 inbuf, outbuf,
979 mask,dirtype,info_level,
980 requires_resume_key,dont_descend,
981 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
982 &last_name_off);
985 if (finished && out_of_space)
986 finished = False;
988 if (!finished && !out_of_space)
989 numentries++;
992 * As an optimisation if we know we aren't looking
993 * for a wildcard name (ie. the name matches the wildcard exactly)
994 * then we can finish on any (first) match.
995 * This speeds up large directory searches. JRA.
998 if(got_exact_match)
999 finished = True;
1001 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1004 /* Check if we can close the dirptr */
1005 if(close_after_first || (finished && close_if_end)) {
1006 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1007 dptr_close(&dptr_num);
1011 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1012 * from observation of NT.
1015 if(numentries == 0) {
1016 dptr_close(&dptr_num);
1017 return ERROR_DOS(ERRDOS,ERRbadfile);
1020 /* At this point pdata points to numentries directory entries. */
1022 /* Set up the return parameter block */
1023 SSVAL(params,0,dptr_num);
1024 SSVAL(params,2,numentries);
1025 SSVAL(params,4,finished);
1026 SSVAL(params,6,0); /* Never an EA error */
1027 SSVAL(params,8,last_name_off);
1029 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1031 if ((! *directory) && dptr_path(dptr_num))
1032 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1034 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1035 smb_fn_name(CVAL(inbuf,smb_com)),
1036 mask, directory, dirtype, numentries ) );
1039 * Force a name mangle here to ensure that the
1040 * mask as an 8.3 name is top of the mangled cache.
1041 * The reasons for this are subtle. Don't remove
1042 * this code unless you know what you are doing
1043 * (see PR#13758). JRA.
1046 if(!mangle_is_8_3_wildcards( mask, False))
1047 mangle_map(mask, True, True, SNUM(conn));
1049 return(-1);
1052 /****************************************************************************
1053 Reply to a TRANS2_FINDNEXT.
1054 ****************************************************************************/
1056 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1057 char **pparams, int total_params, char **ppdata, int total_data)
1059 /* We must be careful here that we don't return more than the
1060 allowed number of data bytes. If this means returning fewer than
1061 maxentries then so be it. We assume that the redirector has
1062 enough room for the fixed number of parameter bytes it has
1063 requested. */
1064 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1065 char *params = *pparams;
1066 char *pdata = *ppdata;
1067 int dptr_num = SVAL(params,0);
1068 int maxentries = SVAL(params,2);
1069 uint16 info_level = SVAL(params,4);
1070 uint32 resume_key = IVAL(params,6);
1071 BOOL close_after_request = BITSETW(params+10,0);
1072 BOOL close_if_end = BITSETW(params+10,1);
1073 BOOL requires_resume_key = BITSETW(params+10,2);
1074 BOOL continue_bit = BITSETW(params+10,3);
1075 pstring resume_name;
1076 pstring mask;
1077 pstring directory;
1078 char *p;
1079 uint16 dirtype;
1080 int numentries = 0;
1081 int i, last_name_off=0;
1082 BOOL finished = False;
1083 BOOL dont_descend = False;
1084 BOOL out_of_space = False;
1085 int space_remaining;
1087 if (total_params < 12)
1088 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1090 *mask = *directory = *resume_name = 0;
1092 srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE);
1094 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1095 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1096 resume_key = %d resume name = %s continue=%d level = %d\n",
1097 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1098 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1100 switch (info_level) {
1101 case SMB_INFO_STANDARD:
1102 case SMB_INFO_QUERY_EA_SIZE:
1103 case SMB_FIND_FILE_DIRECTORY_INFO:
1104 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1105 case SMB_FIND_FILE_NAMES_INFO:
1106 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1107 break;
1108 case SMB_FIND_FILE_UNIX:
1109 if (!lp_unix_extensions())
1110 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1111 break;
1112 default:
1113 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1116 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1117 if(pdata == NULL)
1118 return ERROR_DOS(ERRDOS,ERRnomem);
1120 *ppdata = pdata;
1121 memset((char *)pdata,'\0',max_data_bytes + 1024);
1123 /* Realloc the params space */
1124 params = Realloc(*pparams, 6*SIZEOFWORD);
1125 if( params == NULL )
1126 return ERROR_DOS(ERRDOS,ERRnomem);
1128 *pparams = params;
1130 /* Check that the dptr is valid */
1131 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1132 return ERROR_DOS(ERRDOS,ERRnofiles);
1134 string_set(&conn->dirpath,dptr_path(dptr_num));
1136 /* Get the wildcard mask from the dptr */
1137 if((p = dptr_wcard(dptr_num))== NULL) {
1138 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1139 return ERROR_DOS(ERRDOS,ERRnofiles);
1142 pstrcpy(mask, p);
1143 pstrcpy(directory,conn->dirpath);
1145 /* Get the attr mask from the dptr */
1146 dirtype = dptr_attr(dptr_num);
1148 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1149 dptr_num, mask, dirtype,
1150 (long)conn->dirptr,
1151 TellDir(conn->dirptr)));
1153 /* We don't need to check for VOL here as this is returned by
1154 a different TRANS2 call. */
1156 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1157 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1158 dont_descend = True;
1160 p = pdata;
1161 space_remaining = max_data_bytes;
1162 out_of_space = False;
1165 * Seek to the correct position. We no longer use the resume key but
1166 * depend on the last file name instead.
1169 if(requires_resume_key && *resume_name && !continue_bit) {
1172 * Fix for NT redirector problem triggered by resume key indexes
1173 * changing between directory scans. We now return a resume key of 0
1174 * and instead look for the filename to continue from (also given
1175 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1176 * findfirst/findnext (as is usual) then the directory pointer
1177 * should already be at the correct place. Check this by scanning
1178 * backwards looking for an exact (ie. case sensitive) filename match.
1179 * If we get to the beginning of the directory and haven't found it then scan
1180 * forwards again looking for a match. JRA.
1183 int current_pos, start_pos;
1184 const char *dname = NULL;
1185 pstring dname_pstring;
1186 void *dirptr = conn->dirptr;
1187 start_pos = TellDir(dirptr);
1188 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1189 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1191 SeekDir(dirptr, current_pos);
1192 dname = ReadDirName(dirptr);
1193 if (dname) {
1195 * Remember, mangle_map is called by
1196 * get_lanman2_dir_entry(), so the resume name
1197 * could be mangled. Ensure we do the same
1198 * here.
1201 /* make sure we get a copy that mangle_map can modify */
1203 pstrcpy(dname_pstring, dname);
1204 mangle_map( dname_pstring, False, True, SNUM(conn));
1206 if(strcsequal( resume_name, dname_pstring)) {
1207 SeekDir(dirptr, current_pos+1);
1208 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1209 break;
1215 * Scan forward from start if not found going backwards.
1218 if(current_pos < 0) {
1219 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1220 SeekDir(dirptr, start_pos);
1221 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1224 * Remember, mangle_map is called by
1225 * get_lanman2_dir_entry(), so the resume name
1226 * could be mangled. Ensure we do the same
1227 * here.
1230 if(dname) {
1231 /* make sure we get a copy that mangle_map can modify */
1233 pstrcpy(dname_pstring, dname);
1234 mangle_map(dname_pstring, False, True, SNUM(conn));
1236 if(strcsequal( resume_name, dname_pstring)) {
1237 SeekDir(dirptr, current_pos+1);
1238 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1239 break;
1242 } /* end for */
1243 } /* end if current_pos */
1244 } /* end if requires_resume_key && !continue_bit */
1246 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1247 BOOL got_exact_match = False;
1249 /* this is a heuristic to avoid seeking the dirptr except when
1250 absolutely necessary. It allows for a filename of about 40 chars */
1251 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1252 out_of_space = True;
1253 finished = False;
1254 } else {
1255 finished = !get_lanman2_dir_entry(conn,
1256 inbuf, outbuf,
1257 mask,dirtype,info_level,
1258 requires_resume_key,dont_descend,
1259 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1260 &last_name_off);
1263 if (finished && out_of_space)
1264 finished = False;
1266 if (!finished && !out_of_space)
1267 numentries++;
1270 * As an optimisation if we know we aren't looking
1271 * for a wildcard name (ie. the name matches the wildcard exactly)
1272 * then we can finish on any (first) match.
1273 * This speeds up large directory searches. JRA.
1276 if(got_exact_match)
1277 finished = True;
1279 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1282 /* Check if we can close the dirptr */
1283 if(close_after_request || (finished && close_if_end)) {
1284 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1285 dptr_close(&dptr_num); /* This frees up the saved mask */
1288 /* Set up the return parameter block */
1289 SSVAL(params,0,numentries);
1290 SSVAL(params,2,finished);
1291 SSVAL(params,4,0); /* Never an EA error */
1292 SSVAL(params,6,last_name_off);
1294 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1296 if ((! *directory) && dptr_path(dptr_num))
1297 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1299 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1300 smb_fn_name(CVAL(inbuf,smb_com)),
1301 mask, directory, dirtype, numentries ) );
1303 return(-1);
1306 /****************************************************************************
1307 Reply to a TRANS2_QFSINFO (query filesystem info).
1308 ****************************************************************************/
1310 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1311 int length, int bufsize,
1312 char **pparams, int total_params, char **ppdata, int total_data)
1314 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1315 char *pdata = *ppdata;
1316 char *params = *pparams;
1317 uint16 info_level = SVAL(params,0);
1318 int data_len, len;
1319 SMB_STRUCT_STAT st;
1320 char *vname = volume_label(SNUM(conn));
1321 int snum = SNUM(conn);
1322 char *fstype = lp_fstype(SNUM(conn));
1323 int quota_flag = 0;
1325 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1327 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1328 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1329 return ERROR_DOS(ERRSRV,ERRinvdevice);
1332 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1333 if ( pdata == NULL )
1334 return ERROR_DOS(ERRDOS,ERRnomem);
1336 *ppdata = pdata;
1337 memset((char *)pdata,'\0',max_data_bytes + 1024);
1339 switch (info_level) {
1340 case SMB_INFO_ALLOCATION:
1342 SMB_BIG_UINT dfree,dsize,bsize;
1343 data_len = 18;
1344 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1345 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1346 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1347 SIVAL(pdata,l1_cUnit,dsize);
1348 SIVAL(pdata,l1_cUnitAvail,dfree);
1349 SSVAL(pdata,l1_cbSector,512);
1350 DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1351 (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1352 (unsigned int)dfree, 512));
1353 break;
1356 case SMB_INFO_VOLUME:
1357 /* Return volume name */
1359 * Add volume serial number - hash of a combination of
1360 * the called hostname and the service name.
1362 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1363 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_TERMINATE);
1364 SCVAL(pdata,l2_vol_cch,len);
1365 data_len = l2_vol_szVolLabel + len;
1366 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1367 (unsigned)st.st_ctime, len, vname));
1368 break;
1370 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1371 case SMB_FS_ATTRIBUTE_INFORMATION:
1374 #if defined(HAVE_SYS_QUOTAS)
1375 quota_flag = FILE_VOLUME_QUOTAS;
1376 #endif
1378 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1379 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1380 quota_flag); /* FS ATTRIBUTES */
1382 SIVAL(pdata,4,255); /* Max filename component length */
1383 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1384 and will think we can't do long filenames */
1385 len = srvstr_push(outbuf, pdata+12, fstype, -1, 0);
1386 SIVAL(pdata,8,len);
1387 data_len = 12 + len;
1388 break;
1390 case SMB_QUERY_FS_LABEL_INFO:
1391 case SMB_FS_LABEL_INFORMATION:
1392 len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE);
1393 data_len = 4 + len;
1394 SIVAL(pdata,0,len);
1395 break;
1397 case SMB_QUERY_FS_VOLUME_INFO:
1398 case SMB_FS_VOLUME_INFORMATION:
1401 * Add volume serial number - hash of a combination of
1402 * the called hostname and the service name.
1404 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1405 (str_checksum(local_machine)<<16));
1407 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE);
1408 SIVAL(pdata,12,len);
1409 data_len = 18+len;
1410 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1411 (int)strlen(vname),vname, lp_servicename(snum)));
1412 break;
1414 case SMB_QUERY_FS_SIZE_INFO:
1415 case SMB_FS_SIZE_INFORMATION:
1417 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1418 data_len = 24;
1419 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1420 block_size = lp_block_size(snum);
1421 if (bsize < block_size) {
1422 SMB_BIG_UINT factor = block_size/bsize;
1423 bsize = block_size;
1424 dsize /= factor;
1425 dfree /= factor;
1427 if (bsize > block_size) {
1428 SMB_BIG_UINT factor = bsize/block_size;
1429 bsize = block_size;
1430 dsize *= factor;
1431 dfree *= factor;
1433 bytes_per_sector = 512;
1434 sectors_per_unit = bsize/bytes_per_sector;
1435 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1436 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1437 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1438 SBIG_UINT(pdata,0,dsize);
1439 SBIG_UINT(pdata,8,dfree);
1440 SIVAL(pdata,16,sectors_per_unit);
1441 SIVAL(pdata,20,bytes_per_sector);
1442 break;
1445 case SMB_FS_FULL_SIZE_INFORMATION:
1447 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1448 data_len = 32;
1449 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1450 block_size = lp_block_size(snum);
1451 if (bsize < block_size) {
1452 SMB_BIG_UINT factor = block_size/bsize;
1453 bsize = block_size;
1454 dsize /= factor;
1455 dfree /= factor;
1457 if (bsize > block_size) {
1458 SMB_BIG_UINT factor = bsize/block_size;
1459 bsize = block_size;
1460 dsize *= factor;
1461 dfree *= factor;
1463 bytes_per_sector = 512;
1464 sectors_per_unit = bsize/bytes_per_sector;
1465 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1466 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1467 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1468 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1469 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1470 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1471 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1472 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1473 break;
1476 case SMB_QUERY_FS_DEVICE_INFO:
1477 case SMB_FS_DEVICE_INFORMATION:
1478 data_len = 8;
1479 SIVAL(pdata,0,0); /* dev type */
1480 SIVAL(pdata,4,0); /* characteristics */
1481 break;
1483 #ifdef WITH_QUOTAS
1484 case SMB_FS_QUOTA_INFORMATION:
1486 * what we have to send --metze:
1488 * Unknown1: 24 NULL bytes
1489 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1490 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
1491 * Quota Flags: 2 byte :
1492 * Unknown3: 6 NULL bytes
1494 * 48 bytes total
1496 * details for Quota Flags:
1498 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1499 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
1500 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1501 * 0x0001 Enable Quotas: enable quota for this fs
1505 /* we need to fake up a fsp here,
1506 * because its not send in this call
1508 files_struct fsp;
1509 SMB_NTQUOTA_STRUCT quotas;
1511 ZERO_STRUCT(fsp);
1512 ZERO_STRUCT(quotas);
1514 fsp.conn = conn;
1515 fsp.fnum = -1;
1516 fsp.fd = -1;
1518 /* access check */
1519 if (conn->admin_user != True) {
1520 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1521 lp_servicename(SNUM(conn)),conn->user));
1522 return ERROR_DOS(ERRDOS,ERRnoaccess);
1525 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
1526 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
1527 return ERROR_DOS(ERRSRV,ERRerror);
1530 data_len = 48;
1532 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
1534 /* Unknown1 24 NULL bytes*/
1535 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
1536 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
1537 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
1539 /* Default Soft Quota 8 bytes */
1540 SBIG_UINT(pdata,24,quotas.softlim);
1542 /* Default Hard Quota 8 bytes */
1543 SBIG_UINT(pdata,32,quotas.hardlim);
1545 /* Quota flag 2 bytes */
1546 SSVAL(pdata,40,quotas.qflags);
1548 /* Unknown3 6 NULL bytes */
1549 SSVAL(pdata,42,0);
1550 SIVAL(pdata,44,0);
1552 break;
1554 #endif /* WITH_QUOTAS */
1555 case SMB_FS_OBJECTID_INFORMATION:
1556 data_len = 64;
1557 break;
1560 * Query the version and capabilities of the CIFS UNIX extensions
1561 * in use.
1564 case SMB_QUERY_CIFS_UNIX_INFO:
1565 if (!lp_unix_extensions())
1566 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1567 data_len = 12;
1568 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
1569 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
1570 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
1571 break;
1573 case SMB_MAC_QUERY_FS_INFO:
1575 * Thursby MAC extension... ONLY on NTFS filesystems
1576 * once we do streams then we don't need this
1578 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1579 data_len = 88;
1580 SIVAL(pdata,84,0x100); /* Don't support mac... */
1581 break;
1583 /* drop through */
1584 default:
1585 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1589 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1591 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1593 return -1;
1596 #ifdef WITH_QUOTAS
1597 /****************************************************************************
1598 Reply to a TRANS2_SETFSINFO (set filesystem info).
1599 ****************************************************************************/
1601 static int call_trans2setfsinfo(connection_struct *conn,
1602 char *inbuf, char *outbuf, int length, int bufsize,
1603 char **pparams, int total_params, char **ppdata, int total_data)
1605 char *pdata = *ppdata;
1606 char *params = *pparams;
1607 files_struct *fsp = NULL;
1608 uint16 info_level;
1609 int outsize;
1610 SMB_NTQUOTA_STRUCT quotas;
1612 ZERO_STRUCT(quotas);
1614 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
1616 /* access check */
1617 if ((conn->admin_user != True)||!CAN_WRITE(conn)) {
1618 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1619 lp_servicename(SNUM(conn)),conn->user));
1620 return ERROR_DOS(ERRSRV,ERRaccess);
1623 /* */
1624 if (total_params < 4) {
1625 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
1626 total_params));
1627 return ERROR_DOS(ERRDOS,ERRinvalidparam);
1630 fsp = file_fsp(params,0);
1632 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
1633 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
1634 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
1637 info_level = SVAL(params,2);
1639 switch(info_level) {
1640 case SMB_FS_QUOTA_INFORMATION:
1641 /* note: normaly there're 48 bytes,
1642 * but we didn't use the last 6 bytes for now
1643 * --metze
1645 if (total_data < 42) {
1646 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
1647 total_data));
1648 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1651 /* unknown_1 24 NULL bytes in pdata*/
1653 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
1654 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
1655 #ifdef LARGE_SMB_OFF_T
1656 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
1657 #else /* LARGE_SMB_OFF_T */
1658 if ((IVAL(pdata,28) != 0)&&
1659 ((quotas.softlim != 0xFFFFFFFF)||
1660 (IVAL(pdata,28)!=0xFFFFFFFF)))) {
1661 /* more than 32 bits? */
1662 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1664 #endif /* LARGE_SMB_OFF_T */
1666 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
1667 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
1668 #ifdef LARGE_SMB_OFF_T
1669 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
1670 #else /* LARGE_SMB_OFF_T */
1671 if ((IVAL(pdata,36) != 0)&&
1672 ((quotas.hardlim != 0xFFFFFFFF)||
1673 (IVAL(pdata,36)!=0xFFFFFFFF)))) {
1674 /* more than 32 bits? */
1675 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1677 #endif /* LARGE_SMB_OFF_T */
1679 /* quota_flags 2 bytes **/
1680 quotas.qflags = SVAL(pdata,40);
1682 /* unknown_2 6 NULL bytes follow*/
1684 /* now set the quotas */
1685 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
1686 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
1687 return ERROR_DOS(ERRSRV,ERRerror);
1690 break;
1691 default:
1692 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
1693 info_level));
1694 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1695 break;
1699 * sending this reply works fine,
1700 * but I'm not sure it's the same
1701 * like windows do...
1702 * --metze
1704 outsize = set_message(outbuf,10,0,True);
1706 return outsize;
1708 #endif /* WITH_QUOTAS */
1710 /****************************************************************************
1711 * Utility function to set bad path error.
1712 ****************************************************************************/
1714 NTSTATUS set_bad_path_error(int err, BOOL bad_path)
1716 if((err == ENOENT) && bad_path) {
1717 unix_ERR_class = ERRDOS;
1718 unix_ERR_code = ERRbadpath;
1719 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1721 return NT_STATUS_OK;
1724 /****************************************************************************
1725 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1726 file name or file id).
1727 ****************************************************************************/
1729 static int call_trans2qfilepathinfo(connection_struct *conn,
1730 char *inbuf, char *outbuf, int length,
1731 int bufsize,
1732 char **pparams, int total_params, char **ppdata, int total_data)
1734 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1735 char *params = *pparams;
1736 char *pdata = *ppdata;
1737 uint16 tran_call = SVAL(inbuf, smb_setup0);
1738 uint16 info_level;
1739 int mode=0;
1740 SMB_OFF_T file_size=0;
1741 SMB_BIG_UINT allocation_size=0;
1742 unsigned int data_size;
1743 SMB_STRUCT_STAT sbuf;
1744 pstring fname, dos_fname;
1745 char *fullpathname;
1746 char *base_name;
1747 char *p;
1748 SMB_OFF_T pos = 0;
1749 BOOL bad_path = False;
1750 BOOL delete_pending = False;
1751 int len;
1752 time_t c_time;
1753 files_struct *fsp = NULL;
1755 if (!params)
1756 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1758 if (tran_call == TRANSACT2_QFILEINFO) {
1759 if (total_params < 4)
1760 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1762 fsp = file_fsp(params,0);
1763 info_level = SVAL(params,2);
1765 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1767 if(fsp && (fsp->fake_file_handle)) {
1769 * This is actually for the QUOTA_FAKE_FILE --metze
1772 pstrcpy(fname, fsp->fsp_name);
1773 unix_convert(fname,conn,0,&bad_path,&sbuf);
1774 if (!check_name(fname,conn)) {
1775 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno)));
1776 set_bad_path_error(errno, bad_path);
1777 return(UNIXERROR(ERRDOS,ERRbadpath));
1780 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1782 * This is actually a QFILEINFO on a directory
1783 * handle (returned from an NT SMB). NT5.0 seems
1784 * to do this call. JRA.
1786 pstrcpy(fname, fsp->fsp_name);
1787 unix_convert(fname,conn,0,&bad_path,&sbuf);
1788 if (!check_name(fname,conn)) {
1789 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1790 set_bad_path_error(errno, bad_path);
1791 return(UNIXERROR(ERRDOS,ERRbadpath));
1794 if (INFO_LEVEL_IS_UNIX(info_level)) {
1795 /* Always do lstat for UNIX calls. */
1796 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
1797 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
1798 set_bad_path_error(errno, bad_path);
1799 return(UNIXERROR(ERRDOS,ERRbadpath));
1801 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
1802 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
1803 set_bad_path_error(errno, bad_path);
1804 return(UNIXERROR(ERRDOS,ERRbadpath));
1807 delete_pending = fsp->directory_delete_on_close;
1808 } else {
1810 * Original code - this is an open file.
1812 CHECK_FSP(fsp,conn);
1814 pstrcpy(fname, fsp->fsp_name);
1815 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
1816 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
1817 return(UNIXERROR(ERRDOS,ERRbadfid));
1819 if((pos = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1820 return(UNIXERROR(ERRDOS,ERRnoaccess));
1822 delete_pending = fsp->delete_on_close;
1824 } else {
1825 /* qpathinfo */
1826 if (total_params < 6)
1827 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1829 info_level = SVAL(params,0);
1831 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1833 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
1835 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1837 unix_convert(fname,conn,0,&bad_path,&sbuf);
1838 if (!check_name(fname,conn)) {
1839 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1840 set_bad_path_error(errno, bad_path);
1841 return(UNIXERROR(ERRDOS,ERRbadpath));
1844 if (INFO_LEVEL_IS_UNIX(info_level)) {
1845 /* Always do lstat for UNIX calls. */
1846 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
1847 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
1848 set_bad_path_error(errno, bad_path);
1849 return(UNIXERROR(ERRDOS,ERRbadpath));
1851 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
1852 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
1853 set_bad_path_error(errno, bad_path);
1854 return(UNIXERROR(ERRDOS,ERRbadpath));
1858 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
1859 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1861 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1862 fname,info_level,tran_call,total_data));
1864 p = strrchr_m(fname,'/');
1865 if (!p)
1866 base_name = fname;
1867 else
1868 base_name = p+1;
1870 mode = dos_mode(conn,fname,&sbuf);
1871 fullpathname = fname;
1872 file_size = get_file_size(sbuf);
1873 allocation_size = get_allocation_size(fsp,&sbuf);
1874 if (mode & aDIR)
1875 file_size = 0;
1877 params = Realloc(*pparams,2);
1878 if (params == NULL)
1879 return ERROR_DOS(ERRDOS,ERRnomem);
1880 *pparams = params;
1881 memset((char *)params,'\0',2);
1882 data_size = max_data_bytes + 1024;
1883 pdata = Realloc(*ppdata, data_size);
1884 if ( pdata == NULL )
1885 return ERROR_DOS(ERRDOS,ERRnomem);
1886 *ppdata = pdata;
1888 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1889 /* uggh, EAs for OS2 */
1890 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1891 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1894 memset((char *)pdata,'\0',data_size);
1896 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1898 if (lp_dos_filetime_resolution(SNUM(conn))) {
1899 c_time &= ~1;
1900 sbuf.st_atime &= ~1;
1901 sbuf.st_mtime &= ~1;
1902 sbuf.st_mtime &= ~1;
1905 /* NT expects the name to be in an exact form of the *full*
1906 filename. See the trans2 torture test */
1907 if (strequal(base_name,".")) {
1908 pstrcpy(dos_fname, "\\");
1909 } else {
1910 snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname);
1911 string_replace(dos_fname, '/', '\\');
1914 switch (info_level) {
1915 case SMB_INFO_STANDARD:
1916 case SMB_INFO_QUERY_EA_SIZE:
1917 data_size = (info_level==1?22:26);
1918 put_dos_date2(pdata,l1_fdateCreation,c_time);
1919 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1920 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1921 SIVAL(pdata,l1_cbFile,(uint32)file_size);
1922 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
1923 SSVAL(pdata,l1_attrFile,mode);
1924 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1925 break;
1927 case SMB_INFO_QUERY_EAS_FROM_LIST:
1928 data_size = 24;
1929 put_dos_date2(pdata,0,c_time);
1930 put_dos_date2(pdata,4,sbuf.st_atime);
1931 put_dos_date2(pdata,8,sbuf.st_mtime);
1932 SIVAL(pdata,12,(uint32)file_size);
1933 SIVAL(pdata,16,(uint32)allocation_size);
1934 SIVAL(pdata,20,mode);
1935 break;
1937 case SMB_INFO_QUERY_ALL_EAS:
1938 data_size = 4;
1939 SIVAL(pdata,0,data_size);
1940 break;
1942 case 6:
1943 return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */
1945 case SMB_FILE_BASIC_INFORMATION:
1946 case SMB_QUERY_FILE_BASIC_INFO:
1948 if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1949 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1950 else {
1951 data_size = 40;
1952 SIVAL(pdata,36,0);
1954 put_long_date(pdata,c_time);
1955 put_long_date(pdata+8,sbuf.st_atime);
1956 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1957 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1958 SIVAL(pdata,32,mode);
1960 DEBUG(5,("SMB_QFBI - "));
1962 time_t create_time = c_time;
1963 DEBUG(5,("create: %s ", ctime(&create_time)));
1965 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1966 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1967 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1968 DEBUG(5,("mode: %x\n", mode));
1970 break;
1972 case SMB_FILE_STANDARD_INFORMATION:
1973 case SMB_QUERY_FILE_STANDARD_INFO:
1975 data_size = 24;
1976 SOFF_T(pdata,0,allocation_size);
1977 SOFF_T(pdata,8,file_size);
1978 SIVAL(pdata,16,sbuf.st_nlink);
1979 SCVAL(pdata,20,0);
1980 SCVAL(pdata,21,(mode&aDIR)?1:0);
1981 break;
1983 case SMB_FILE_EA_INFORMATION:
1984 case SMB_QUERY_FILE_EA_INFO:
1985 data_size = 4;
1986 break;
1988 /* Get the 8.3 name - used if NT SMB was negotiated. */
1989 case SMB_QUERY_FILE_ALT_NAME_INFO:
1990 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
1992 pstring short_name;
1994 pstrcpy(short_name,base_name);
1995 /* Mangle if not already 8.3 */
1996 if(!mangle_is_8_3(short_name, True)) {
1997 mangle_map(short_name,True,True,SNUM(conn));
1999 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2000 data_size = 4 + len;
2001 SIVAL(pdata,0,len);
2002 break;
2005 case SMB_QUERY_FILE_NAME_INFO:
2007 this must be *exactly* right for ACLs on mapped drives to work
2009 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2010 data_size = 4 + len;
2011 SIVAL(pdata,0,len);
2012 break;
2014 case SMB_FILE_ALLOCATION_INFORMATION:
2015 case SMB_QUERY_FILE_ALLOCATION_INFO:
2016 data_size = 8;
2017 SOFF_T(pdata,0,allocation_size);
2018 break;
2020 case SMB_FILE_END_OF_FILE_INFORMATION:
2021 case SMB_QUERY_FILE_END_OF_FILEINFO:
2022 data_size = 8;
2023 SOFF_T(pdata,0,file_size);
2024 break;
2026 case SMB_QUERY_FILE_ALL_INFO:
2027 put_long_date(pdata,c_time);
2028 put_long_date(pdata+8,sbuf.st_atime);
2029 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2030 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2031 SIVAL(pdata,32,mode);
2032 pdata += 40;
2033 SOFF_T(pdata,0,allocation_size);
2034 SOFF_T(pdata,8,file_size);
2035 SIVAL(pdata,16,sbuf.st_nlink);
2036 SCVAL(pdata,20,delete_pending);
2037 SCVAL(pdata,21,(mode&aDIR)?1:0);
2038 pdata += 24;
2039 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);
2040 pdata += 8; /* index number */
2041 pdata += 4; /* EA info */
2042 if (mode & aRONLY)
2043 SIVAL(pdata,0,0xA9);
2044 else
2045 SIVAL(pdata,0,0xd01BF);
2046 pdata += 4;
2047 SOFF_T(pdata,0,pos); /* current offset */
2048 pdata += 8;
2049 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
2050 pdata += 4;
2051 pdata += 4; /* alignment */
2052 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_TERMINATE);
2053 SIVAL(pdata,0,len);
2054 pdata += 4 + len;
2055 data_size = PTR_DIFF(pdata,(*ppdata));
2056 break;
2058 case SMB_FILE_INTERNAL_INFORMATION:
2059 /* This should be an index number - looks like
2060 dev/ino to me :-)
2062 I think this causes us to fail the IFSKIT
2063 BasicFileInformationTest. -tpot */
2065 SIVAL(pdata,0,sbuf.st_dev);
2066 SIVAL(pdata,4,sbuf.st_ino);
2067 data_size = 8;
2068 break;
2070 case SMB_FILE_ACCESS_INFORMATION:
2071 SIVAL(pdata,0,0x12019F); /* ??? */
2072 data_size = 4;
2073 break;
2075 case SMB_FILE_NAME_INFORMATION:
2076 /* Pathname with leading '\'. */
2078 size_t byte_len;
2079 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2080 SIVAL(pdata,0,byte_len);
2081 data_size = 4 + byte_len;
2082 break;
2085 case SMB_FILE_DISPOSITION_INFORMATION:
2086 data_size = 1;
2087 SCVAL(pdata,0,delete_pending);
2088 break;
2090 case SMB_FILE_POSITION_INFORMATION:
2091 data_size = 8;
2092 SOFF_T(pdata,0,pos);
2093 break;
2095 case SMB_FILE_MODE_INFORMATION:
2096 SIVAL(pdata,0,mode);
2097 data_size = 4;
2098 break;
2100 case SMB_FILE_ALIGNMENT_INFORMATION:
2101 SIVAL(pdata,0,0); /* No alignment needed. */
2102 data_size = 4;
2103 break;
2105 #if 0
2106 /* Not yet finished... JRA */
2107 case 1018:
2109 put_long_date(pdata,c_time);
2110 put_long_date(pdata+8,sbuf.st_atime);
2111 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2112 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2113 SIVAL(pdata,32,mode);
2114 SIVAL(pdata,36,0); /* ??? */
2115 SIVAL(pdata,40,0x20); /* ??? */
2116 SIVAL(pdata,44,0); /* ??? */
2117 SOFF_T(pdata,48,size);
2118 SIVAL(pdata,56,0x1); /* ??? */
2119 SIVAL(pdata,60,0); /* ??? */
2120 SIVAL(pdata,64,0); /* ??? */
2121 SIVAL(pdata,68,length); /* Following string length in bytes. */
2122 dos_PutUniCode(pdata+72,,False);
2123 break;
2125 #endif
2127 #if 0
2129 * NT4 server just returns "invalid query" to this - if we try to answer
2130 * it then NTws gets a BSOD! (tridge).
2131 * W2K seems to want this. JRA.
2133 case SMB_QUERY_FILE_STREAM_INFO:
2134 #endif
2135 case SMB_FILE_STREAM_INFORMATION:
2136 if (mode & aDIR) {
2137 data_size = 0;
2138 } else {
2139 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2140 SIVAL(pdata,0,0); /* ??? */
2141 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2142 SOFF_T(pdata,8,file_size);
2143 SIVAL(pdata,16,allocation_size);
2144 SIVAL(pdata,20,0); /* ??? */
2145 data_size = 24 + byte_len;
2147 break;
2149 case SMB_FILE_COMPRESSION_INFORMATION:
2150 SOFF_T(pdata,0,allocation_size);
2151 SIVAL(pdata,8,0); /* ??? */
2152 SIVAL(pdata,12,0); /* ??? */
2153 data_size = 16;
2154 break;
2156 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2157 put_long_date(pdata,c_time);
2158 put_long_date(pdata+8,sbuf.st_atime);
2159 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2160 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2161 SIVAL(pdata,32,allocation_size);
2162 SOFF_T(pdata,40,file_size);
2163 SIVAL(pdata,48,mode);
2164 SIVAL(pdata,52,0); /* ??? */
2165 data_size = 56;
2166 break;
2168 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2169 SIVAL(pdata,0,mode);
2170 SIVAL(pdata,4,0);
2171 data_size = 8;
2172 break;
2175 * CIFS UNIX Extensions.
2178 case SMB_QUERY_FILE_UNIX_BASIC:
2180 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2182 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2183 pdata += 8;
2185 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2186 pdata += 8;
2188 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2189 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2190 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2191 pdata += 24;
2193 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2194 SIVAL(pdata,4,0);
2195 pdata += 8;
2197 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2198 SIVAL(pdata,4,0);
2199 pdata += 8;
2201 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2202 pdata += 4;
2204 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2205 SIVAL(pdata,4,0);
2206 pdata += 8;
2208 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2209 SIVAL(pdata,4,0);
2210 pdata += 8;
2212 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2213 pdata += 8;
2215 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2216 SIVAL(pdata,4,0);
2217 pdata += 8;
2219 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2220 SIVAL(pdata,4,0);
2221 pdata += 8+1;
2222 data_size = PTR_DIFF(pdata,(*ppdata));
2225 int i;
2226 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2228 for (i=0; i<100; i++)
2229 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2230 DEBUG(4,("\n"));
2233 break;
2235 case SMB_QUERY_FILE_UNIX_LINK:
2237 pstring buffer;
2239 #ifdef S_ISLNK
2240 if(!S_ISLNK(sbuf.st_mode))
2241 return(UNIXERROR(ERRSRV,ERRbadlink));
2242 #else
2243 return(UNIXERROR(ERRDOS,ERRbadlink));
2244 #endif
2245 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2246 if (len == -1)
2247 return(UNIXERROR(ERRDOS,ERRnoaccess));
2248 buffer[len] = 0;
2249 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2250 pdata += len;
2251 data_size = PTR_DIFF(pdata,(*ppdata));
2253 break;
2256 default:
2257 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2260 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size);
2262 return(-1);
2265 /****************************************************************************
2266 Deal with the internal needs of setting the delete on close flag. Note that
2267 as the tdb locking is recursive, it is safe to call this from within
2268 open_file_shared. JRA.
2269 ****************************************************************************/
2271 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2274 * Only allow delete on close for writable shares.
2277 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2278 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2279 fsp->fsp_name ));
2280 return NT_STATUS_ACCESS_DENIED;
2283 * Only allow delete on close for files/directories opened with delete intent.
2286 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2287 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2288 fsp->fsp_name ));
2289 return NT_STATUS_ACCESS_DENIED;
2292 if(fsp->is_directory) {
2293 fsp->directory_delete_on_close = delete_on_close;
2294 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2295 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2296 } else {
2297 fsp->delete_on_close = delete_on_close;
2298 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2299 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2302 return NT_STATUS_OK;
2305 /****************************************************************************
2306 Sets the delete on close flag over all share modes on this file.
2307 Modify the share mode entry for all files open
2308 on this device and inode to tell other smbds we have
2309 changed the delete on close flag. This will be noticed
2310 in the close code, the last closer will delete the file
2311 if flag is set.
2312 ****************************************************************************/
2314 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2316 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2317 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2319 if (fsp->is_directory || fsp->is_stat)
2320 return NT_STATUS_OK;
2322 if (lock_share_entry_fsp(fsp) == False)
2323 return NT_STATUS_ACCESS_DENIED;
2325 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2326 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2327 fsp->fsp_name ));
2328 unlock_share_entry_fsp(fsp);
2329 return NT_STATUS_ACCESS_DENIED;
2332 unlock_share_entry_fsp(fsp);
2333 return NT_STATUS_OK;
2336 /****************************************************************************
2337 Returns true if this pathname is within the share, and thus safe.
2338 ****************************************************************************/
2340 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2342 #ifdef PATH_MAX
2343 char resolved_name[PATH_MAX+1];
2344 #else
2345 pstring resolved_name;
2346 #endif
2347 fstring last_component;
2348 pstring link_dest;
2349 pstring link_test;
2350 char *p;
2351 BOOL bad_path = False;
2352 SMB_STRUCT_STAT sbuf;
2354 pstrcpy(link_dest, link_dest_in);
2355 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2357 /* Store the UNIX converted path. */
2358 pstrcpy(link_dest_out, link_dest);
2360 p = strrchr(link_dest, '/');
2361 if (p) {
2362 fstrcpy(last_component, p+1);
2363 *p = '\0';
2364 } else {
2365 fstrcpy(last_component, link_dest);
2366 pstrcpy(link_dest, "./");
2369 if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL)
2370 return -1;
2372 pstrcpy(link_dest, resolved_name);
2373 pstrcat(link_dest, "/");
2374 pstrcat(link_dest, last_component);
2376 if (*link_dest != '/') {
2377 /* Relative path. */
2378 pstrcpy(link_test, conn->connectpath);
2379 pstrcat(link_test, "/");
2380 pstrcat(link_test, link_dest);
2381 } else {
2382 pstrcpy(link_test, link_dest);
2386 * Check if the link is within the share.
2389 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2390 errno = EACCES;
2391 return -1;
2393 return 0;
2396 /****************************************************************************
2397 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2398 ****************************************************************************/
2400 static int call_trans2setfilepathinfo(connection_struct *conn,
2401 char *inbuf, char *outbuf, int length, int bufsize,
2402 char **pparams, int total_params, char **ppdata, int total_data)
2404 char *params = *pparams;
2405 char *pdata = *ppdata;
2406 uint16 tran_call = SVAL(inbuf, smb_setup0);
2407 uint16 info_level;
2408 int dosmode=0;
2409 SMB_OFF_T size=0;
2410 struct utimbuf tvs;
2411 SMB_STRUCT_STAT sbuf;
2412 pstring fname;
2413 int fd = -1;
2414 BOOL bad_path = False;
2415 files_struct *fsp = NULL;
2416 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2417 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2418 mode_t unixmode = 0;
2420 if (!params)
2421 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2423 if (tran_call == TRANSACT2_SETFILEINFO) {
2424 if (total_params < 4)
2425 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2427 fsp = file_fsp(params,0);
2428 info_level = SVAL(params,2);
2430 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2432 * This is actually a SETFILEINFO on a directory
2433 * handle (returned from an NT SMB). NT5.0 seems
2434 * to do this call. JRA.
2436 pstrcpy(fname, fsp->fsp_name);
2437 unix_convert(fname,conn,0,&bad_path,&sbuf);
2438 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2439 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2440 set_bad_path_error(errno, bad_path);
2441 return(UNIXERROR(ERRDOS,ERRbadpath));
2443 } else if (fsp && fsp->print_file) {
2445 * Doing a DELETE_ON_CLOSE should cancel a print job.
2447 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
2448 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2450 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
2452 SSVAL(params,0,0);
2453 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2454 return(-1);
2455 } else
2456 return (UNIXERROR(ERRDOS,ERRbadpath));
2457 } else {
2459 * Original code - this is an open file.
2461 CHECK_FSP(fsp,conn);
2463 pstrcpy(fname, fsp->fsp_name);
2464 fd = fsp->fd;
2466 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
2467 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2468 return(UNIXERROR(ERRDOS,ERRbadfid));
2471 } else {
2472 /* set path info */
2473 if (total_params < 6)
2474 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2476 info_level = SVAL(params,0);
2477 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
2478 unix_convert(fname,conn,0,&bad_path,&sbuf);
2479 if(!check_name(fname, conn)) {
2480 set_bad_path_error(errno, bad_path);
2481 return(UNIXERROR(ERRDOS,ERRbadpath));
2485 * For CIFS UNIX extensions the target name may not exist.
2488 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2489 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
2490 set_bad_path_error(errno, bad_path);
2491 return(UNIXERROR(ERRDOS,ERRbadpath));
2495 if (!CAN_WRITE(conn))
2496 return ERROR_DOS(ERRSRV,ERRaccess);
2498 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2499 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2501 if (VALID_STAT(sbuf))
2502 unixmode = sbuf.st_mode;
2504 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
2505 tran_call,fname,info_level,total_data));
2507 /* Realloc the parameter and data sizes */
2508 params = Realloc(*pparams,2);
2509 if(params == NULL)
2510 return ERROR_DOS(ERRDOS,ERRnomem);
2511 *pparams = params;
2513 SSVAL(params,0,0);
2515 if (fsp) {
2516 /* the pending modtime overrides the current modtime */
2517 sbuf.st_mtime = fsp->pending_modtime;
2520 size = get_file_size(sbuf);
2521 tvs.modtime = sbuf.st_mtime;
2522 tvs.actime = sbuf.st_atime;
2523 dosmode = dos_mode(conn,fname,&sbuf);
2524 unixmode = sbuf.st_mode;
2526 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2527 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2529 switch (info_level) {
2530 case SMB_INFO_STANDARD:
2532 if (total_data < l1_cbFile+4)
2533 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2535 /* access time */
2536 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2538 /* write time */
2539 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2541 dosmode = SVAL(pdata,l1_attrFile);
2542 size = IVAL(pdata,l1_cbFile);
2544 break;
2547 case SMB_INFO_SET_EA:
2548 return(ERROR_DOS(ERRDOS,ERReasnotsupported));
2550 /* XXXX um, i don't think this is right.
2551 it's also not in the cifs6.txt spec.
2553 case SMB_INFO_QUERY_EAS_FROM_LIST:
2554 if (total_data < 28)
2555 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2557 tvs.actime = make_unix_date2(pdata+8);
2558 tvs.modtime = make_unix_date2(pdata+12);
2559 size = IVAL(pdata,16);
2560 dosmode = IVAL(pdata,24);
2561 break;
2563 /* XXXX nor this. not in cifs6.txt, either. */
2564 case SMB_INFO_QUERY_ALL_EAS:
2565 if (total_data < 28)
2566 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2568 tvs.actime = make_unix_date2(pdata+8);
2569 tvs.modtime = make_unix_date2(pdata+12);
2570 size = IVAL(pdata,16);
2571 dosmode = IVAL(pdata,24);
2572 break;
2574 case SMB_SET_FILE_BASIC_INFO:
2575 case SMB_FILE_BASIC_INFORMATION:
2577 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2578 time_t write_time;
2579 time_t changed_time;
2581 if (total_data < 36)
2582 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2584 /* Ignore create time at offset pdata. */
2586 /* access time */
2587 tvs.actime = interpret_long_date(pdata+8);
2589 write_time = interpret_long_date(pdata+16);
2590 changed_time = interpret_long_date(pdata+24);
2592 tvs.modtime = MIN(write_time, changed_time);
2594 if (write_time > tvs.modtime && write_time != 0xffffffff) {
2595 tvs.modtime = write_time;
2597 /* Prefer a defined time to an undefined one. */
2598 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2599 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2600 ? changed_time : write_time);
2602 /* attributes */
2603 dosmode = IVAL(pdata,32);
2604 break;
2607 case SMB_FILE_ALLOCATION_INFORMATION:
2608 case SMB_SET_FILE_ALLOCATION_INFO:
2610 int ret = -1;
2611 SMB_BIG_UINT allocation_size;
2613 if (total_data < 8)
2614 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2616 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
2617 #ifdef LARGE_SMB_OFF_T
2618 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
2619 #else /* LARGE_SMB_OFF_T */
2620 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2621 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2622 #endif /* LARGE_SMB_OFF_T */
2623 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2624 fname, (double)allocation_size ));
2626 if (allocation_size)
2627 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
2629 if(allocation_size != get_file_size(sbuf)) {
2630 SMB_STRUCT_STAT new_sbuf;
2632 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2633 fname, (double)allocation_size ));
2635 if (fd == -1) {
2636 files_struct *new_fsp = NULL;
2637 int access_mode = 0;
2638 int action = 0;
2640 if(global_oplock_break) {
2641 /* Queue this file modify as we are the process of an oplock break. */
2643 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2644 DEBUGADD(2,( "in oplock break state.\n"));
2646 push_oplock_pending_smb_message(inbuf, length);
2647 return -1;
2650 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2651 SET_OPEN_MODE(DOS_OPEN_RDWR),
2652 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2653 0, 0, &access_mode, &action);
2655 if (new_fsp == NULL)
2656 return(UNIXERROR(ERRDOS,ERRbadpath));
2657 ret = vfs_allocate_file_space(new_fsp, allocation_size);
2658 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2659 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2660 new_fsp->fnum, strerror(errno)));
2661 ret = -1;
2663 close_file(new_fsp,True);
2664 } else {
2665 ret = vfs_allocate_file_space(fsp, allocation_size);
2666 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
2667 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2668 fsp->fnum, strerror(errno)));
2669 ret = -1;
2672 if (ret == -1)
2673 return ERROR_NT(NT_STATUS_DISK_FULL);
2675 /* Allocate can truncate size... */
2676 size = get_file_size(new_sbuf);
2679 break;
2682 case SMB_FILE_END_OF_FILE_INFORMATION:
2683 case SMB_SET_FILE_END_OF_FILE_INFO:
2685 if (total_data < 8)
2686 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2688 size = IVAL(pdata,0);
2689 #ifdef LARGE_SMB_OFF_T
2690 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2691 #else /* LARGE_SMB_OFF_T */
2692 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2693 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2694 #endif /* LARGE_SMB_OFF_T */
2695 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2696 break;
2699 case SMB_FILE_DISPOSITION_INFORMATION:
2700 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2702 BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
2703 NTSTATUS status;
2705 if (total_data < 1)
2706 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2708 if (tran_call != TRANSACT2_SETFILEINFO)
2709 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2711 if (fsp == NULL)
2712 return(UNIXERROR(ERRDOS,ERRbadfid));
2714 status = set_delete_on_close_internal(fsp, delete_on_close);
2716 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2717 return ERROR_NT(status);
2719 /* The set is across all open files on this dev/inode pair. */
2720 status =set_delete_on_close_over_all(fsp, delete_on_close);
2721 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2722 return ERROR_NT(status);
2724 break;
2728 * CIFS UNIX extensions.
2731 case SMB_SET_FILE_UNIX_BASIC:
2733 uint32 raw_unixmode;
2735 if (total_data < 100)
2736 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2738 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
2739 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
2740 size=IVAL(pdata,0); /* first 8 Bytes are size */
2741 #ifdef LARGE_SMB_OFF_T
2742 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2743 #else /* LARGE_SMB_OFF_T */
2744 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2745 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2746 #endif /* LARGE_SMB_OFF_T */
2748 pdata+=24; /* ctime & st_blocks are not changed */
2749 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
2750 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
2751 pdata+=16;
2752 set_owner = (uid_t)IVAL(pdata,0);
2753 pdata += 8;
2754 set_grp = (gid_t)IVAL(pdata,0);
2755 pdata += 8;
2756 raw_unixmode = IVAL(pdata,28);
2757 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2758 dosmode = 0; /* Ensure dos mode change doesn't override this. */
2760 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2761 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2762 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2764 if (!VALID_STAT(sbuf)) {
2767 * The only valid use of this is to create character and block
2768 * devices, and named pipes. This is deprecated (IMHO) and
2769 * a new info level should be used for mknod. JRA.
2772 #if !defined(HAVE_MAKEDEV_FN)
2773 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2774 #else /* HAVE_MAKEDEV_FN */
2775 uint32 file_type = IVAL(pdata,0);
2776 uint32 dev_major = IVAL(pdata,4);
2777 uint32 dev_minor = IVAL(pdata,12);
2779 uid_t myuid = geteuid();
2780 gid_t mygid = getegid();
2781 SMB_DEV_T dev;
2783 if (tran_call == TRANSACT2_SETFILEINFO)
2784 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2786 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2787 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2789 dev = makedev(dev_major, dev_minor);
2791 /* We can only create as the owner/group we are. */
2793 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2794 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2795 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2796 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2798 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2799 file_type != UNIX_TYPE_FIFO)
2800 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2802 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2803 0%o for file %s\n", (double)dev, unixmode, fname ));
2805 /* Ok - do the mknod. */
2806 if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
2807 return(UNIXERROR(ERRDOS,ERRnoaccess));
2809 inherit_access_acl(conn, fname, unixmode);
2811 SSVAL(params,0,0);
2812 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2813 return(-1);
2814 #endif /* HAVE_MAKEDEV_FN */
2819 * Deal with the UNIX specific mode set.
2822 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
2823 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2824 (unsigned int)unixmode, fname ));
2825 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
2826 return(UNIXERROR(ERRDOS,ERRnoaccess));
2830 * Deal with the UNIX specific uid set.
2833 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
2834 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2835 (unsigned int)set_owner, fname ));
2836 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
2837 return(UNIXERROR(ERRDOS,ERRnoaccess));
2841 * Deal with the UNIX specific gid set.
2844 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
2845 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2846 (unsigned int)set_owner, fname ));
2847 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
2848 return(UNIXERROR(ERRDOS,ERRnoaccess));
2850 break;
2853 case SMB_SET_FILE_UNIX_LINK:
2855 pstring link_dest;
2856 /* Set a symbolic link. */
2857 /* Don't allow this if follow links is false. */
2859 if (!lp_symlinks(SNUM(conn)))
2860 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2862 /* Disallow if already exists. */
2863 if (VALID_STAT(sbuf))
2864 return(ERROR_DOS(ERRDOS,ERRbadpath));
2866 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2868 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2869 return(UNIXERROR(ERRDOS,ERRnoaccess));
2871 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2872 fname, link_dest ));
2874 if (SMB_VFS_SYMLINK(conn,link_dest,fname) != 0)
2875 return(UNIXERROR(ERRDOS,ERRnoaccess));
2876 SSVAL(params,0,0);
2877 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2878 return(-1);
2881 case SMB_SET_FILE_UNIX_HLINK:
2883 pstring link_dest;
2885 /* Set a hard link. */
2887 /* Disallow if already exists. */
2888 if (VALID_STAT(sbuf))
2889 return(ERROR_DOS(ERRDOS,ERRbadpath));
2891 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2893 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2894 return(UNIXERROR(ERRDOS,ERRnoaccess));
2896 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2897 fname, link_dest ));
2899 if (SMB_VFS_LINK(conn,link_dest,fname) != 0)
2900 return(UNIXERROR(ERRDOS,ERRnoaccess));
2901 SSVAL(params,0,0);
2902 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2903 return(-1);
2906 default:
2907 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2910 /* get some defaults (no modifications) if any info is zero or -1. */
2911 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2912 tvs.actime = sbuf.st_atime;
2914 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2915 tvs.modtime = sbuf.st_mtime;
2917 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2918 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2919 DEBUG(6,("size: %.0f ", (double)size));
2921 if (S_ISDIR(sbuf.st_mode))
2922 dosmode |= aDIR;
2923 else
2924 dosmode &= ~aDIR;
2926 DEBUG(6,("dosmode: %x\n" , dosmode));
2928 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2929 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2930 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2931 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2934 * Only do this test if we are not explicitly
2935 * changing the size of a file.
2937 if (!size)
2938 size = get_file_size(sbuf);
2942 * Try and set the times, size and mode of this file -
2943 * if they are different from the current values
2945 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2946 if(fsp != NULL) {
2948 * This was a setfileinfo on an open file.
2949 * NT does this a lot. It's actually pointless
2950 * setting the time here, as it will be overwritten
2951 * on the next write, so we save the request
2952 * away and will set it on file close. JRA.
2955 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2956 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
2957 fsp->pending_modtime = tvs.modtime;
2960 } else {
2962 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2964 if(file_utime(conn, fname, &tvs)!=0)
2965 return(UNIXERROR(ERRDOS,ERRnoaccess));
2969 /* check the mode isn't different, before changing it */
2970 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
2972 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
2974 if(file_chmod(conn, fname, dosmode, NULL)) {
2975 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2976 return(UNIXERROR(ERRDOS,ERRnoaccess));
2980 if (size != get_file_size(sbuf)) {
2982 int ret;
2984 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2985 fname, (double)size ));
2987 if (fd == -1) {
2988 files_struct *new_fsp = NULL;
2989 int access_mode = 0;
2990 int action = 0;
2992 if(global_oplock_break) {
2993 /* Queue this file modify as we are the process of an oplock break. */
2995 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2996 DEBUGADD(2,( "in oplock break state.\n"));
2998 push_oplock_pending_smb_message(inbuf, length);
2999 return -1;
3002 new_fsp = open_file_shared(conn, fname, &sbuf,
3003 SET_OPEN_MODE(DOS_OPEN_RDWR),
3004 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3005 0, 0, &access_mode, &action);
3007 if (new_fsp == NULL)
3008 return(UNIXERROR(ERRDOS,ERRbadpath));
3009 ret = vfs_set_filelen(new_fsp, size);
3010 close_file(new_fsp,True);
3011 } else {
3012 ret = vfs_set_filelen(fsp, size);
3015 if (ret == -1)
3016 return (UNIXERROR(ERRHRD,ERRdiskfull));
3019 SSVAL(params,0,0);
3020 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3022 return(-1);
3025 /****************************************************************************
3026 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3027 ****************************************************************************/
3029 static int call_trans2mkdir(connection_struct *conn,
3030 char *inbuf, char *outbuf, int length, int bufsize,
3031 char **pparams, int total_params, char **ppdata, int total_data)
3033 char *params = *pparams;
3034 pstring directory;
3035 int ret = -1;
3036 SMB_STRUCT_STAT sbuf;
3037 BOOL bad_path = False;
3039 if (!CAN_WRITE(conn))
3040 return ERROR_DOS(ERRSRV,ERRaccess);
3042 if (total_params < 4)
3043 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3045 srvstr_pull(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE);
3047 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3049 unix_convert(directory,conn,0,&bad_path,&sbuf);
3050 if (check_name(directory,conn))
3051 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3053 if(ret < 0) {
3054 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3055 set_bad_path_error(errno, bad_path);
3056 return(UNIXERROR(ERRDOS,ERRnoaccess));
3059 /* Realloc the parameter and data sizes */
3060 params = Realloc(*pparams,2);
3061 if(params == NULL)
3062 return ERROR_DOS(ERRDOS,ERRnomem);
3063 *pparams = params;
3065 SSVAL(params,0,0);
3067 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3069 return(-1);
3072 /****************************************************************************
3073 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3074 We don't actually do this - we just send a null response.
3075 ****************************************************************************/
3077 static int call_trans2findnotifyfirst(connection_struct *conn,
3078 char *inbuf, char *outbuf, int length, int bufsize,
3079 char **pparams, int total_params, char **ppdata, int total_data)
3081 static uint16 fnf_handle = 257;
3082 char *params = *pparams;
3083 uint16 info_level;
3085 if (total_params < 6)
3086 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3088 info_level = SVAL(params,4);
3089 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3091 switch (info_level) {
3092 case 1:
3093 case 2:
3094 break;
3095 default:
3096 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3099 /* Realloc the parameter and data sizes */
3100 params = Realloc(*pparams,6);
3101 if(params == NULL)
3102 return ERROR_DOS(ERRDOS,ERRnomem);
3103 *pparams = params;
3105 SSVAL(params,0,fnf_handle);
3106 SSVAL(params,2,0); /* No changes */
3107 SSVAL(params,4,0); /* No EA errors */
3109 fnf_handle++;
3111 if(fnf_handle == 0)
3112 fnf_handle = 257;
3114 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3116 return(-1);
3119 /****************************************************************************
3120 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3121 changes). Currently this does nothing.
3122 ****************************************************************************/
3124 static int call_trans2findnotifynext(connection_struct *conn,
3125 char *inbuf, char *outbuf, int length, int bufsize,
3126 char **pparams, int total_params, char **ppdata, int total_data)
3128 char *params = *pparams;
3130 DEBUG(3,("call_trans2findnotifynext\n"));
3132 /* Realloc the parameter and data sizes */
3133 params = Realloc(*pparams,4);
3134 if(params == NULL)
3135 return ERROR_DOS(ERRDOS,ERRnomem);
3136 *pparams = params;
3138 SSVAL(params,0,0); /* No changes */
3139 SSVAL(params,2,0); /* No EA errors */
3141 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3143 return(-1);
3146 /****************************************************************************
3147 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3148 ****************************************************************************/
3150 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3151 char* outbuf, int length, int bufsize,
3152 char **pparams, int total_params, char **ppdata, int total_data)
3154 char *params = *pparams;
3155 pstring pathname;
3156 int reply_size = 0;
3157 int max_referral_level;
3159 DEBUG(10,("call_trans2getdfsreferral\n"));
3161 if (total_params < 2)
3162 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3164 max_referral_level = SVAL(params,0);
3166 if(!lp_host_msdfs())
3167 return ERROR_DOS(ERRDOS,ERRbadfunc);
3169 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
3171 if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
3172 return ERROR_DOS(ERRDOS,ERRbadfile);
3174 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3175 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3177 return(-1);
3180 #define LMCAT_SPL 0x53
3181 #define LMFUNC_GETJOBID 0x60
3183 /****************************************************************************
3184 Reply to a TRANS2_IOCTL - used for OS/2 printing.
3185 ****************************************************************************/
3187 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3188 char* outbuf, int length, int bufsize,
3189 char **pparams, int total_params, char **ppdata, int total_data)
3191 char *pdata = *ppdata;
3192 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3194 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3195 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3196 pdata = Realloc(*ppdata, 32);
3197 if(pdata == NULL)
3198 return ERROR_DOS(ERRDOS,ERRnomem);
3199 *ppdata = pdata;
3201 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3202 CAN ACCEPT THIS IN UNICODE. JRA. */
3204 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
3205 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3206 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3207 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3208 return(-1);
3209 } else {
3210 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3211 return ERROR_DOS(ERRSRV,ERRerror);
3215 /****************************************************************************
3216 Reply to a SMBfindclose (stop trans2 directory search).
3217 ****************************************************************************/
3219 int reply_findclose(connection_struct *conn,
3220 char *inbuf,char *outbuf,int length,int bufsize)
3222 int outsize = 0;
3223 int dptr_num=SVALS(inbuf,smb_vwv0);
3224 START_PROFILE(SMBfindclose);
3226 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3228 dptr_close(&dptr_num);
3230 outsize = set_message(outbuf,0,0,True);
3232 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3234 END_PROFILE(SMBfindclose);
3235 return(outsize);
3238 /****************************************************************************
3239 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3240 ****************************************************************************/
3242 int reply_findnclose(connection_struct *conn,
3243 char *inbuf,char *outbuf,int length,int bufsize)
3245 int outsize = 0;
3246 int dptr_num= -1;
3247 START_PROFILE(SMBfindnclose);
3249 dptr_num = SVAL(inbuf,smb_vwv0);
3251 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3253 /* We never give out valid handles for a
3254 findnotifyfirst - so any dptr_num is ok here.
3255 Just ignore it. */
3257 outsize = set_message(outbuf,0,0,True);
3259 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3261 END_PROFILE(SMBfindnclose);
3262 return(outsize);
3265 /****************************************************************************
3266 Reply to a SMBtranss2 - just ignore it!
3267 ****************************************************************************/
3269 int reply_transs2(connection_struct *conn,
3270 char *inbuf,char *outbuf,int length,int bufsize)
3272 START_PROFILE(SMBtranss2);
3273 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3274 END_PROFILE(SMBtranss2);
3275 return(-1);
3278 /****************************************************************************
3279 Reply to a SMBtrans2.
3280 ****************************************************************************/
3282 int reply_trans2(connection_struct *conn,
3283 char *inbuf,char *outbuf,int length,int bufsize)
3285 int outsize = 0;
3286 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3287 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3288 #if 0
3289 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3290 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3291 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3292 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3293 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3294 int32 timeout = IVALS(inbuf,smb_timeout);
3295 #endif
3296 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3297 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3298 char *params = NULL, *data = NULL;
3299 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
3300 START_PROFILE(SMBtrans2);
3302 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3303 /* Queue this open message as we are the process of an
3304 * oplock break. */
3306 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3307 DEBUGADD(2,( "in oplock break state.\n"));
3309 push_oplock_pending_smb_message(inbuf, length);
3310 END_PROFILE(SMBtrans2);
3311 return -1;
3314 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3315 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3316 END_PROFILE(SMBtrans2);
3317 return ERROR_DOS(ERRSRV,ERRaccess);
3320 outsize = set_message(outbuf,0,0,True);
3322 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3323 is so as a sanity check */
3324 if (suwcnt != 1) {
3326 * Need to have rc=0 for ioctl to get job id for OS/2.
3327 * Network printing will fail if function is not successful.
3328 * Similar function in reply.c will be used if protocol
3329 * is LANMAN1.0 instead of LM1.2X002.
3330 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3331 * outbuf doesn't have to be set(only job id is used).
3333 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3334 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3335 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3336 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3337 } else {
3338 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
3339 DEBUG(2,("Transaction is %d\n",tran_call));
3340 END_PROFILE(SMBtrans2);
3341 ERROR_DOS(ERRDOS,ERRinvalidparam);
3345 /* Allocate the space for the maximum needed parameters and data */
3346 if (total_params > 0)
3347 params = (char *)malloc(total_params);
3348 if (total_data > 0)
3349 data = (char *)malloc(total_data);
3351 if ((total_params && !params) || (total_data && !data)) {
3352 DEBUG(2,("Out of memory in reply_trans2\n"));
3353 SAFE_FREE(params);
3354 SAFE_FREE(data);
3355 END_PROFILE(SMBtrans2);
3356 return ERROR_DOS(ERRDOS,ERRnomem);
3359 /* Copy the param and data bytes sent with this request into
3360 the params buffer */
3361 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3362 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3364 if (num_params > total_params || num_data > total_data)
3365 exit_server("invalid params in reply_trans2");
3367 if(params) {
3368 unsigned int psoff = SVAL(inbuf, smb_psoff);
3369 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
3370 goto bad_param;
3371 if (smb_base(inbuf) + psoff + num_params > inbuf + length)
3372 goto bad_param;
3373 memcpy( params, smb_base(inbuf) + psoff, num_params);
3375 if(data) {
3376 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
3377 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
3378 goto bad_param;
3379 if (smb_base(inbuf) + dsoff + num_data > inbuf + length)
3380 goto bad_param;
3381 memcpy( data, smb_base(inbuf) + dsoff, num_data);
3384 if(num_data_sofar < total_data || num_params_sofar < total_params) {
3385 /* We need to send an interim response then receive the rest
3386 of the parameter/data bytes */
3387 outsize = set_message(outbuf,0,0,True);
3388 if (!send_smb(smbd_server_fd(),outbuf))
3389 exit_server("reply_trans2: send_smb failed.");
3391 while (num_data_sofar < total_data ||
3392 num_params_sofar < total_params) {
3393 BOOL ret;
3394 unsigned int param_disp;
3395 unsigned int param_off;
3396 unsigned int data_disp;
3397 unsigned int data_off;
3399 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3401 if ((ret &&
3402 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3403 outsize = set_message(outbuf,0,0,True);
3404 if(ret)
3405 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3406 else
3407 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3408 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3409 goto bad_param;
3412 /* Revise total_params and total_data in case
3413 they have changed downwards */
3414 if (SVAL(inbuf, smb_tpscnt) < total_params)
3415 total_params = SVAL(inbuf, smb_tpscnt);
3416 if (SVAL(inbuf, smb_tdscnt) < total_data)
3417 total_data = SVAL(inbuf, smb_tdscnt);
3419 num_params = SVAL(inbuf,smb_spscnt);
3420 param_off = SVAL(inbuf, smb_spsoff);
3421 param_disp = SVAL(inbuf, smb_spsdisp);
3422 num_params_sofar += num_params;
3424 num_data = SVAL(inbuf, smb_sdscnt);
3425 data_off = SVAL(inbuf, smb_sdsoff);
3426 data_disp = SVAL(inbuf, smb_sdsdisp);
3427 num_data_sofar += num_data;
3429 if (num_params_sofar > total_params || num_data_sofar > total_data)
3430 goto bad_param;
3432 if (num_params) {
3433 if (param_disp + num_params >= total_params)
3434 goto bad_param;
3435 if ((param_disp + num_params < param_disp) ||
3436 (param_disp + num_params < num_params))
3437 goto bad_param;
3438 if (smb_base(inbuf) + param_off + num_params >= inbuf + bufsize)
3439 goto bad_param;
3440 if (params + param_disp < params)
3441 goto bad_param;
3443 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
3445 if (num_data) {
3446 if (data_disp + num_data >= total_data)
3447 goto bad_param;
3448 if ((data_disp + num_data < data_disp) ||
3449 (data_disp + num_data < num_data))
3450 goto bad_param;
3451 if (smb_base(inbuf) + data_off + num_data >= inbuf + bufsize)
3452 goto bad_param;
3453 if (data + data_disp < data)
3454 goto bad_param;
3456 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
3461 if (Protocol >= PROTOCOL_NT1) {
3462 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
3465 /* Now we must call the relevant TRANS2 function */
3466 switch(tran_call) {
3467 case TRANSACT2_OPEN:
3468 START_PROFILE_NESTED(Trans2_open);
3469 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
3470 &params, total_params, &data, total_data);
3471 END_PROFILE_NESTED(Trans2_open);
3472 break;
3474 case TRANSACT2_FINDFIRST:
3475 START_PROFILE_NESTED(Trans2_findfirst);
3476 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3477 &params, total_params, &data, total_data);
3478 END_PROFILE_NESTED(Trans2_findfirst);
3479 break;
3481 case TRANSACT2_FINDNEXT:
3482 START_PROFILE_NESTED(Trans2_findnext);
3483 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
3484 &params, total_params, &data, total_data);
3485 END_PROFILE_NESTED(Trans2_findnext);
3486 break;
3488 case TRANSACT2_QFSINFO:
3489 START_PROFILE_NESTED(Trans2_qfsinfo);
3490 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3491 &params, total_params, &data, total_data);
3492 END_PROFILE_NESTED(Trans2_qfsinfo);
3493 break;
3495 #ifdef WITH_QUOTAS
3496 case TRANSACT2_SETFSINFO:
3497 START_PROFILE_NESTED(Trans2_setfsinfo);
3498 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
3499 &params, total_params, &data, total_data);
3500 END_PROFILE_NESTED(Trans2_setfsinfo);
3501 break;
3502 #endif
3503 case TRANSACT2_QPATHINFO:
3504 case TRANSACT2_QFILEINFO:
3505 START_PROFILE_NESTED(Trans2_qpathinfo);
3506 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3507 &params, total_params, &data, total_data);
3508 END_PROFILE_NESTED(Trans2_qpathinfo);
3509 break;
3510 case TRANSACT2_SETPATHINFO:
3511 case TRANSACT2_SETFILEINFO:
3512 START_PROFILE_NESTED(Trans2_setpathinfo);
3513 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3514 &params, total_params, &data, total_data);
3515 END_PROFILE_NESTED(Trans2_setpathinfo);
3516 break;
3518 case TRANSACT2_FINDNOTIFYFIRST:
3519 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3520 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
3521 &params, total_params, &data, total_data);
3522 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3523 break;
3525 case TRANSACT2_FINDNOTIFYNEXT:
3526 START_PROFILE_NESTED(Trans2_findnotifynext);
3527 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
3528 &params, total_params, &data, total_data);
3529 END_PROFILE_NESTED(Trans2_findnotifynext);
3530 break;
3531 case TRANSACT2_MKDIR:
3532 START_PROFILE_NESTED(Trans2_mkdir);
3533 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3534 &params, total_params, &data, total_data);
3535 END_PROFILE_NESTED(Trans2_mkdir);
3536 break;
3538 case TRANSACT2_GET_DFS_REFERRAL:
3539 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3540 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3541 &params, total_params, &data, total_data);
3542 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3543 break;
3544 case TRANSACT2_IOCTL:
3545 START_PROFILE_NESTED(Trans2_ioctl);
3546 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3547 &params, total_params, &data, total_data);
3548 END_PROFILE_NESTED(Trans2_ioctl);
3549 break;
3550 default:
3551 /* Error in request */
3552 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3553 SAFE_FREE(params);
3554 SAFE_FREE(data);
3555 END_PROFILE(SMBtrans2);
3556 return ERROR_DOS(ERRSRV,ERRerror);
3559 /* As we do not know how many data packets will need to be
3560 returned here the various call_trans2xxxx calls
3561 must send their own. Thus a call_trans2xxx routine only
3562 returns a value other than -1 when it wants to send
3563 an error packet.
3566 SAFE_FREE(params);
3567 SAFE_FREE(data);
3568 END_PROFILE(SMBtrans2);
3569 return outsize; /* If a correct response was needed the
3570 call_trans2xxx calls have already sent
3571 it. If outsize != -1 then it is returning */
3573 bad_param:
3575 SAFE_FREE(params);
3576 SAFE_FREE(data);
3577 END_PROFILE(SMBtrans2);
3578 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);