this fixes a bug where Samba would under some circumstances return
[Samba/gebeck_regimport.git] / source / smbd / trans2.c
blob398646a6cd8154a1a4caed1336a70bfe98028007
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 if (StrCaseCmp(str,mask) != 0) {
330 return False;
332 if (ms_has_wild(str)) {
333 return False;
335 return True;
338 /****************************************************************************
339 Return the filetype for UNIX extensions.
340 ****************************************************************************/
342 static uint32 unix_filetype(mode_t mode)
344 if(S_ISREG(mode))
345 return UNIX_TYPE_FILE;
346 else if(S_ISDIR(mode))
347 return UNIX_TYPE_DIR;
348 #ifdef S_ISLNK
349 else if(S_ISLNK(mode))
350 return UNIX_TYPE_SYMLINK;
351 #endif
352 #ifdef S_ISCHR
353 else if(S_ISCHR(mode))
354 return UNIX_TYPE_CHARDEV;
355 #endif
356 #ifdef S_ISBLK
357 else if(S_ISBLK(mode))
358 return UNIX_TYPE_BLKDEV;
359 #endif
360 #ifdef S_ISFIFO
361 else if(S_ISFIFO(mode))
362 return UNIX_TYPE_FIFO;
363 #endif
364 #ifdef S_ISSOCK
365 else if(S_ISSOCK(mode))
366 return UNIX_TYPE_SOCKET;
367 #endif
369 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
370 return UNIX_TYPE_UNKNOWN;
373 /****************************************************************************
374 Return the major devicenumber for UNIX extensions.
375 ****************************************************************************/
377 static uint32 unix_dev_major(SMB_DEV_T dev)
379 #if defined(HAVE_DEVICE_MAJOR_FN)
380 return (uint32)major(dev);
381 #else
382 return (uint32)(dev >> 8);
383 #endif
386 /****************************************************************************
387 Return the minor devicenumber for UNIX extensions.
388 ****************************************************************************/
390 static uint32 unix_dev_minor(SMB_DEV_T dev)
392 #if defined(HAVE_DEVICE_MINOR_FN)
393 return (uint32)minor(dev);
394 #else
395 return (uint32)(dev & 0xff);
396 #endif
399 /****************************************************************************
400 Map wire perms onto standard UNIX permissions. Obey share restrictions.
401 ****************************************************************************/
403 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
405 mode_t ret = 0;
407 if (perms == SMB_MODE_NO_CHANGE)
408 return pst->st_mode;
410 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
411 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
412 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
413 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
414 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
415 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
416 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
417 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
418 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
419 #ifdef S_ISVTX
420 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
421 #endif
422 #ifdef S_ISGID
423 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
424 #endif
425 #ifdef S_ISUID
426 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
427 #endif
429 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
430 ret &= lp_dir_mask(SNUM(conn));
431 /* Add in force bits */
432 ret |= lp_force_dir_mode(SNUM(conn));
433 } else {
434 /* Apply mode mask */
435 ret &= lp_create_mask(SNUM(conn));
436 /* Add in force bits */
437 ret |= lp_force_create_mode(SNUM(conn));
440 return ret;
443 /****************************************************************************
444 checks for SMB_TIME_NO_CHANGE and if not found
445 calls interpret_long_date
446 ****************************************************************************/
447 time_t interpret_long_unix_date(char *p)
449 DEBUG(1,("interpret_long_unix_date\n"));
450 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
451 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
452 return -1;
453 } else {
454 return interpret_long_date(p);
458 /****************************************************************************
459 Get a level dependent lanman2 dir entry.
460 ****************************************************************************/
462 static BOOL get_lanman2_dir_entry(connection_struct *conn,
463 void *inbuf, void *outbuf,
464 char *path_mask,int dirtype,int info_level,
465 int requires_resume_key,
466 BOOL dont_descend,char **ppdata,
467 char *base_data, int space_remaining,
468 BOOL *out_of_space, BOOL *got_exact_match,
469 int *last_name_off)
471 const char *dname;
472 BOOL found = False;
473 SMB_STRUCT_STAT sbuf;
474 pstring mask;
475 pstring pathreal;
476 pstring fname;
477 char *p, *q, *pdata = *ppdata;
478 uint32 reskey=0;
479 int prev_dirpos=0;
480 int mode=0;
481 SMB_OFF_T file_size = 0;
482 SMB_BIG_UINT allocation_size = 0;
483 uint32 len;
484 time_t mdate=0, adate=0, cdate=0;
485 char *nameptr;
486 BOOL was_8_3;
487 int nt_extmode; /* Used for NT connections instead of mode */
488 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
490 *fname = 0;
491 *out_of_space = False;
492 *got_exact_match = False;
494 if (!conn->dirptr)
495 return(False);
497 p = strrchr_m(path_mask,'/');
498 if(p != NULL) {
499 if(p[1] == '\0')
500 pstrcpy(mask,"*.*");
501 else
502 pstrcpy(mask, p+1);
503 } else
504 pstrcpy(mask, path_mask);
506 while (!found) {
507 BOOL got_match;
509 /* Needed if we run out of space */
510 prev_dirpos = TellDir(conn->dirptr);
511 dname = ReadDirName(conn->dirptr);
514 * Due to bugs in NT client redirectors we are not using
515 * resume keys any more - set them to zero.
516 * Check out the related comments in findfirst/findnext.
517 * JRA.
520 reskey = 0;
522 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
523 (long)conn->dirptr,TellDir(conn->dirptr)));
525 if (!dname)
526 return(False);
528 pstrcpy(fname,dname);
530 if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
531 got_match = mask_match(fname, mask, case_sensitive);
533 if(!got_match && !mangle_is_8_3(fname, False)) {
536 * It turns out that NT matches wildcards against
537 * both long *and* short names. This may explain some
538 * of the wildcard wierdness from old DOS clients
539 * that some people have been seeing.... JRA.
542 pstring newname;
543 pstrcpy( newname, fname);
544 mangle_map( newname, True, False, SNUM(conn));
545 if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
546 got_match = mask_match(newname, mask, case_sensitive);
549 if(got_match) {
550 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
551 if (dont_descend && !isdots)
552 continue;
554 pstrcpy(pathreal,conn->dirpath);
555 if(needslash)
556 pstrcat(pathreal,"/");
557 pstrcat(pathreal,dname);
559 if (INFO_LEVEL_IS_UNIX(info_level)) {
560 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
561 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
562 pathreal,strerror(errno)));
563 continue;
565 } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
567 /* Needed to show the msdfs symlinks as
568 * directories */
570 if(lp_host_msdfs() &&
571 lp_msdfs_root(SNUM(conn)) &&
572 is_msdfs_link(conn, pathreal, NULL, NULL,
573 &sbuf)) {
575 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
576 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
578 } else {
580 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
581 pathreal,strerror(errno)));
582 continue;
586 mode = dos_mode(conn,pathreal,&sbuf);
588 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
589 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
590 continue;
593 file_size = get_file_size(sbuf);
594 allocation_size = get_allocation_size(NULL,&sbuf);
595 mdate = sbuf.st_mtime;
596 adate = sbuf.st_atime;
597 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
599 if (lp_dos_filetime_resolution(SNUM(conn))) {
600 cdate &= ~1;
601 mdate &= ~1;
602 adate &= ~1;
605 if(mode & aDIR)
606 file_size = 0;
608 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
610 found = True;
614 mangle_map(fname,False,True,SNUM(conn));
616 p = pdata;
617 nameptr = p;
619 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
621 switch (info_level) {
622 case SMB_INFO_STANDARD:
623 if(requires_resume_key) {
624 SIVAL(p,0,reskey);
625 p += 4;
627 put_dos_date2(p,l1_fdateCreation,cdate);
628 put_dos_date2(p,l1_fdateLastAccess,adate);
629 put_dos_date2(p,l1_fdateLastWrite,mdate);
630 SIVAL(p,l1_cbFile,(uint32)file_size);
631 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
632 SSVAL(p,l1_attrFile,mode);
633 p += l1_achName;
634 nameptr = p;
635 p += align_string(outbuf, p, 0);
636 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
637 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS)
638 SCVAL(nameptr, -1, len-2);
639 else
640 SCVAL(nameptr, -1, len-1);
641 p += len;
642 break;
644 case SMB_INFO_QUERY_EA_SIZE:
645 if(requires_resume_key) {
646 SIVAL(p,0,reskey);
647 p += 4;
649 put_dos_date2(p,l2_fdateCreation,cdate);
650 put_dos_date2(p,l2_fdateLastAccess,adate);
651 put_dos_date2(p,l2_fdateLastWrite,mdate);
652 SIVAL(p,l2_cbFile,(uint32)file_size);
653 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
654 SSVAL(p,l2_attrFile,mode);
655 SIVAL(p,l2_cbList,0); /* No extended attributes */
656 p += l2_achName;
657 nameptr = p;
658 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
659 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS)
660 SCVAL(nameptr, -1, len-2);
661 else
662 SCVAL(nameptr, -1, len-1);
663 p += len;
664 break;
666 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
667 was_8_3 = mangle_is_8_3(fname, True);
668 p += 4;
669 SIVAL(p,0,reskey); p += 4;
670 put_long_date(p,cdate); p += 8;
671 put_long_date(p,adate); p += 8;
672 put_long_date(p,mdate); p += 8;
673 put_long_date(p,mdate); p += 8;
674 SOFF_T(p,0,file_size);
675 SOFF_T(p,8,allocation_size);
676 p += 16;
677 SIVAL(p,0,nt_extmode); p += 4;
678 q = p; p += 4;
679 SIVAL(p,0,0); p += 4;
680 /* Clear the short name buffer. This is
681 * IMPORTANT as not doing so will trigger
682 * a Win2k client bug. JRA.
684 memset(p,'\0',26);
685 if (!was_8_3) {
686 pstring mangled_name;
687 pstrcpy(mangled_name, fname);
688 mangle_map(mangled_name,True,True,SNUM(conn));
689 mangled_name[12] = 0;
690 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
691 SSVAL(p, 0, len);
692 } else {
693 SSVAL(p,0,0);
694 *(p+2) = 0;
696 p += 2 + 24;
697 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
698 SIVAL(q,0,len);
699 p += len;
700 len = PTR_DIFF(p, pdata);
701 len = (len + 3) & ~3;
702 SIVAL(pdata,0,len);
703 p = pdata + len;
704 break;
706 case SMB_FIND_FILE_DIRECTORY_INFO:
707 p += 4;
708 SIVAL(p,0,reskey); p += 4;
709 put_long_date(p,cdate); p += 8;
710 put_long_date(p,adate); p += 8;
711 put_long_date(p,mdate); p += 8;
712 put_long_date(p,mdate); p += 8;
713 SOFF_T(p,0,file_size);
714 SOFF_T(p,8,allocation_size);
715 p += 16;
716 SIVAL(p,0,nt_extmode); p += 4;
717 p += 4;
718 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
719 SIVAL(p, -4, len);
720 p += len;
721 len = PTR_DIFF(p, pdata);
722 len = (len + 3) & ~3;
723 SIVAL(pdata,0,len);
724 p = pdata + len;
725 break;
727 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
728 p += 4;
729 SIVAL(p,0,reskey); p += 4;
730 put_long_date(p,cdate); p += 8;
731 put_long_date(p,adate); p += 8;
732 put_long_date(p,mdate); p += 8;
733 put_long_date(p,mdate); p += 8;
734 SOFF_T(p,0,file_size);
735 SOFF_T(p,8,allocation_size);
736 p += 16;
737 SIVAL(p,0,nt_extmode);
738 p += 4;
740 SIVAL(p,4,0); /* ea size */
741 len = srvstr_push(outbuf, p+8, fname, -1, STR_TERMINATE_ASCII);
742 SIVAL(p, 0, len);
743 p += 8 + len;
745 len = PTR_DIFF(p, pdata);
746 len = (len + 3) & ~3;
747 SIVAL(pdata,0,len);
748 p = pdata + len;
749 break;
751 case SMB_FIND_FILE_NAMES_INFO:
752 p += 4;
753 SIVAL(p,0,reskey); p += 4;
754 p += 4;
755 /* this must *not* be null terminated or w2k gets in a loop trying to set an
756 acl on a dir (tridge) */
757 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
758 SIVAL(p, -4, len);
759 p += len;
760 len = PTR_DIFF(p, pdata);
761 len = (len + 3) & ~3;
762 SIVAL(pdata,0,len);
763 p = pdata + len;
764 break;
766 /* CIFS UNIX Extension. */
768 case SMB_FIND_FILE_UNIX:
769 p+= 4;
770 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
772 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
773 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
774 p+= 8;
776 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
777 p+= 8;
779 put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */
780 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
781 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
782 p+= 24;
784 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
785 SIVAL(p,4,0);
786 p+= 8;
788 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
789 SIVAL(p,4,0);
790 p+= 8;
792 SIVAL(p,0,unix_filetype(sbuf.st_mode));
793 p+= 4;
795 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
796 SIVAL(p,4,0);
797 p+= 8;
799 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
800 SIVAL(p,4,0);
801 p+= 8;
803 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
804 p+= 8;
806 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
807 SIVAL(p,4,0);
808 p+= 8;
810 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
811 SIVAL(p,4,0);
812 p+= 8;
814 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
815 p += len;
817 len = PTR_DIFF(p, pdata);
818 len = (len + 3) & ~3;
819 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
820 p = pdata + len;
821 /* End of SMB_QUERY_FILE_UNIX_BASIC */
823 break;
825 default:
826 return(False);
830 if (PTR_DIFF(p,pdata) > space_remaining) {
831 /* Move the dirptr back to prev_dirpos */
832 SeekDir(conn->dirptr, prev_dirpos);
833 *out_of_space = True;
834 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
835 return False; /* Not finished - just out of space */
838 /* Setup the last_filename pointer, as an offset from base_data */
839 *last_name_off = PTR_DIFF(nameptr,base_data);
840 /* Advance the data pointer to the next slot */
841 *ppdata = p;
843 return(found);
846 /****************************************************************************
847 Reply to a TRANS2_FINDFIRST.
848 ****************************************************************************/
850 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
851 char **pparams, int total_params, char **ppdata, int total_data)
853 /* We must be careful here that we don't return more than the
854 allowed number of data bytes. If this means returning fewer than
855 maxentries then so be it. We assume that the redirector has
856 enough room for the fixed number of parameter bytes it has
857 requested. */
858 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
859 char *params = *pparams;
860 char *pdata = *ppdata;
861 int dirtype = SVAL(params,0);
862 int maxentries = SVAL(params,2);
863 BOOL close_after_first = BITSETW(params+4,0);
864 BOOL close_if_end = BITSETW(params+4,1);
865 BOOL requires_resume_key = BITSETW(params+4,2);
866 int info_level = SVAL(params,6);
867 pstring directory;
868 pstring mask;
869 char *p, *wcard;
870 int last_name_off=0;
871 int dptr_num = -1;
872 int numentries = 0;
873 int i;
874 BOOL finished = False;
875 BOOL dont_descend = False;
876 BOOL out_of_space = False;
877 int space_remaining;
878 BOOL bad_path = False;
879 SMB_STRUCT_STAT sbuf;
881 if (total_params < 12)
882 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
884 *directory = *mask = 0;
886 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
887 close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
888 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
889 info_level, max_data_bytes));
891 switch (info_level) {
892 case SMB_INFO_STANDARD:
893 case SMB_INFO_QUERY_EA_SIZE:
894 case SMB_FIND_FILE_DIRECTORY_INFO:
895 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
896 case SMB_FIND_FILE_NAMES_INFO:
897 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
898 break;
899 case SMB_FIND_FILE_UNIX:
900 if (!lp_unix_extensions())
901 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
902 break;
903 default:
904 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
907 srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE);
909 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
911 unix_convert(directory,conn,0,&bad_path,&sbuf);
912 if(!check_name(directory,conn)) {
913 set_bad_path_error(errno, bad_path);
914 return(UNIXERROR(ERRDOS,ERRbadpath));
917 p = strrchr_m(directory,'/');
918 if(p == NULL) {
919 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
920 if((directory[0] == '.') && (directory[1] == '\0'))
921 pstrcpy(mask,"*");
922 else
923 pstrcpy(mask,directory);
924 pstrcpy(directory,"./");
925 } else {
926 pstrcpy(mask,p+1);
927 *p = 0;
930 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
932 pdata = Realloc(*ppdata, max_data_bytes + 1024);
933 if( pdata == NULL )
934 return(ERROR_DOS(ERRDOS,ERRnomem));
936 *ppdata = pdata;
937 memset((char *)pdata,'\0',max_data_bytes + 1024);
939 /* Realloc the params space */
940 params = Realloc(*pparams, 10);
941 if (params == NULL)
942 return ERROR_DOS(ERRDOS,ERRnomem);
943 *pparams = params;
945 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
946 if (dptr_num < 0)
947 return(UNIXERROR(ERRDOS,ERRbadfile));
949 /* Save the wildcard match and attribs we are using on this directory -
950 needed as lanman2 assumes these are being saved between calls */
952 if(!(wcard = strdup(mask))) {
953 dptr_close(&dptr_num);
954 return ERROR_DOS(ERRDOS,ERRnomem);
957 dptr_set_wcard(dptr_num, wcard);
958 dptr_set_attr(dptr_num, dirtype);
960 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
962 /* We don't need to check for VOL here as this is returned by
963 a different TRANS2 call. */
965 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
966 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
967 dont_descend = True;
969 p = pdata;
970 space_remaining = max_data_bytes;
971 out_of_space = False;
973 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
974 BOOL got_exact_match = False;
976 /* this is a heuristic to avoid seeking the dirptr except when
977 absolutely necessary. It allows for a filename of about 40 chars */
978 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
979 out_of_space = True;
980 finished = False;
981 } else {
982 finished = !get_lanman2_dir_entry(conn,
983 inbuf, outbuf,
984 mask,dirtype,info_level,
985 requires_resume_key,dont_descend,
986 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
987 &last_name_off);
990 if (finished && out_of_space)
991 finished = False;
993 if (!finished && !out_of_space)
994 numentries++;
997 * As an optimisation if we know we aren't looking
998 * for a wildcard name (ie. the name matches the wildcard exactly)
999 * then we can finish on any (first) match.
1000 * This speeds up large directory searches. JRA.
1003 if(got_exact_match)
1004 finished = True;
1006 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1009 /* Check if we can close the dirptr */
1010 if(close_after_first || (finished && close_if_end)) {
1011 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1012 dptr_close(&dptr_num);
1016 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1017 * from observation of NT.
1020 if(numentries == 0) {
1021 dptr_close(&dptr_num);
1022 return ERROR_DOS(ERRDOS,ERRbadfile);
1025 /* At this point pdata points to numentries directory entries. */
1027 /* Set up the return parameter block */
1028 SSVAL(params,0,dptr_num);
1029 SSVAL(params,2,numentries);
1030 SSVAL(params,4,finished);
1031 SSVAL(params,6,0); /* Never an EA error */
1032 SSVAL(params,8,last_name_off);
1034 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1036 if ((! *directory) && dptr_path(dptr_num))
1037 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1039 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1040 smb_fn_name(CVAL(inbuf,smb_com)),
1041 mask, directory, dirtype, numentries ) );
1044 * Force a name mangle here to ensure that the
1045 * mask as an 8.3 name is top of the mangled cache.
1046 * The reasons for this are subtle. Don't remove
1047 * this code unless you know what you are doing
1048 * (see PR#13758). JRA.
1051 if(!mangle_is_8_3_wildcards( mask, False))
1052 mangle_map(mask, True, True, SNUM(conn));
1054 return(-1);
1057 /****************************************************************************
1058 Reply to a TRANS2_FINDNEXT.
1059 ****************************************************************************/
1061 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1062 char **pparams, int total_params, char **ppdata, int total_data)
1064 /* We must be careful here that we don't return more than the
1065 allowed number of data bytes. If this means returning fewer than
1066 maxentries then so be it. We assume that the redirector has
1067 enough room for the fixed number of parameter bytes it has
1068 requested. */
1069 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1070 char *params = *pparams;
1071 char *pdata = *ppdata;
1072 int dptr_num = SVAL(params,0);
1073 int maxentries = SVAL(params,2);
1074 uint16 info_level = SVAL(params,4);
1075 uint32 resume_key = IVAL(params,6);
1076 BOOL close_after_request = BITSETW(params+10,0);
1077 BOOL close_if_end = BITSETW(params+10,1);
1078 BOOL requires_resume_key = BITSETW(params+10,2);
1079 BOOL continue_bit = BITSETW(params+10,3);
1080 pstring resume_name;
1081 pstring mask;
1082 pstring directory;
1083 char *p;
1084 uint16 dirtype;
1085 int numentries = 0;
1086 int i, last_name_off=0;
1087 BOOL finished = False;
1088 BOOL dont_descend = False;
1089 BOOL out_of_space = False;
1090 int space_remaining;
1092 if (total_params < 12)
1093 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1095 *mask = *directory = *resume_name = 0;
1097 srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE);
1099 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1100 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1101 resume_key = %d resume name = %s continue=%d level = %d\n",
1102 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1103 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1105 switch (info_level) {
1106 case SMB_INFO_STANDARD:
1107 case SMB_INFO_QUERY_EA_SIZE:
1108 case SMB_FIND_FILE_DIRECTORY_INFO:
1109 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1110 case SMB_FIND_FILE_NAMES_INFO:
1111 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1112 break;
1113 case SMB_FIND_FILE_UNIX:
1114 if (!lp_unix_extensions())
1115 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1116 break;
1117 default:
1118 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1121 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1122 if(pdata == NULL)
1123 return ERROR_DOS(ERRDOS,ERRnomem);
1125 *ppdata = pdata;
1126 memset((char *)pdata,'\0',max_data_bytes + 1024);
1128 /* Realloc the params space */
1129 params = Realloc(*pparams, 6*SIZEOFWORD);
1130 if( params == NULL )
1131 return ERROR_DOS(ERRDOS,ERRnomem);
1133 *pparams = params;
1135 /* Check that the dptr is valid */
1136 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1137 return ERROR_DOS(ERRDOS,ERRnofiles);
1139 string_set(&conn->dirpath,dptr_path(dptr_num));
1141 /* Get the wildcard mask from the dptr */
1142 if((p = dptr_wcard(dptr_num))== NULL) {
1143 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1144 return ERROR_DOS(ERRDOS,ERRnofiles);
1147 pstrcpy(mask, p);
1148 pstrcpy(directory,conn->dirpath);
1150 /* Get the attr mask from the dptr */
1151 dirtype = dptr_attr(dptr_num);
1153 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1154 dptr_num, mask, dirtype,
1155 (long)conn->dirptr,
1156 TellDir(conn->dirptr)));
1158 /* We don't need to check for VOL here as this is returned by
1159 a different TRANS2 call. */
1161 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1162 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1163 dont_descend = True;
1165 p = pdata;
1166 space_remaining = max_data_bytes;
1167 out_of_space = False;
1170 * Seek to the correct position. We no longer use the resume key but
1171 * depend on the last file name instead.
1174 if(requires_resume_key && *resume_name && !continue_bit) {
1177 * Fix for NT redirector problem triggered by resume key indexes
1178 * changing between directory scans. We now return a resume key of 0
1179 * and instead look for the filename to continue from (also given
1180 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1181 * findfirst/findnext (as is usual) then the directory pointer
1182 * should already be at the correct place. Check this by scanning
1183 * backwards looking for an exact (ie. case sensitive) filename match.
1184 * If we get to the beginning of the directory and haven't found it then scan
1185 * forwards again looking for a match. JRA.
1188 int current_pos, start_pos;
1189 const char *dname = NULL;
1190 pstring dname_pstring;
1191 void *dirptr = conn->dirptr;
1192 start_pos = TellDir(dirptr);
1193 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1194 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1196 SeekDir(dirptr, current_pos);
1197 dname = ReadDirName(dirptr);
1198 if (dname) {
1200 * Remember, mangle_map is called by
1201 * get_lanman2_dir_entry(), so the resume name
1202 * could be mangled. Ensure we do the same
1203 * here.
1206 /* make sure we get a copy that mangle_map can modify */
1208 pstrcpy(dname_pstring, dname);
1209 mangle_map( dname_pstring, False, True, SNUM(conn));
1211 if(strcsequal( resume_name, dname_pstring)) {
1212 SeekDir(dirptr, current_pos+1);
1213 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1214 break;
1220 * Scan forward from start if not found going backwards.
1223 if(current_pos < 0) {
1224 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1225 SeekDir(dirptr, start_pos);
1226 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1229 * Remember, mangle_map is called by
1230 * get_lanman2_dir_entry(), so the resume name
1231 * could be mangled. Ensure we do the same
1232 * here.
1235 if(dname) {
1236 /* make sure we get a copy that mangle_map can modify */
1238 pstrcpy(dname_pstring, dname);
1239 mangle_map(dname_pstring, False, True, SNUM(conn));
1241 if(strcsequal( resume_name, dname_pstring)) {
1242 SeekDir(dirptr, current_pos+1);
1243 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1244 break;
1247 } /* end for */
1248 } /* end if current_pos */
1249 } /* end if requires_resume_key && !continue_bit */
1251 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1252 BOOL got_exact_match = False;
1254 /* this is a heuristic to avoid seeking the dirptr except when
1255 absolutely necessary. It allows for a filename of about 40 chars */
1256 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1257 out_of_space = True;
1258 finished = False;
1259 } else {
1260 finished = !get_lanman2_dir_entry(conn,
1261 inbuf, outbuf,
1262 mask,dirtype,info_level,
1263 requires_resume_key,dont_descend,
1264 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1265 &last_name_off);
1268 if (finished && out_of_space)
1269 finished = False;
1271 if (!finished && !out_of_space)
1272 numentries++;
1275 * As an optimisation if we know we aren't looking
1276 * for a wildcard name (ie. the name matches the wildcard exactly)
1277 * then we can finish on any (first) match.
1278 * This speeds up large directory searches. JRA.
1281 if(got_exact_match)
1282 finished = True;
1284 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1287 /* Check if we can close the dirptr */
1288 if(close_after_request || (finished && close_if_end)) {
1289 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1290 dptr_close(&dptr_num); /* This frees up the saved mask */
1293 /* Set up the return parameter block */
1294 SSVAL(params,0,numentries);
1295 SSVAL(params,2,finished);
1296 SSVAL(params,4,0); /* Never an EA error */
1297 SSVAL(params,6,last_name_off);
1299 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1301 if ((! *directory) && dptr_path(dptr_num))
1302 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1304 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1305 smb_fn_name(CVAL(inbuf,smb_com)),
1306 mask, directory, dirtype, numentries ) );
1308 return(-1);
1311 /****************************************************************************
1312 Reply to a TRANS2_QFSINFO (query filesystem info).
1313 ****************************************************************************/
1315 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1316 int length, int bufsize,
1317 char **pparams, int total_params, char **ppdata, int total_data)
1319 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1320 char *pdata = *ppdata;
1321 char *params = *pparams;
1322 uint16 info_level = SVAL(params,0);
1323 int data_len, len;
1324 SMB_STRUCT_STAT st;
1325 char *vname = volume_label(SNUM(conn));
1326 int snum = SNUM(conn);
1327 char *fstype = lp_fstype(SNUM(conn));
1328 int quota_flag = 0;
1330 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1332 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1333 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1334 return ERROR_DOS(ERRSRV,ERRinvdevice);
1337 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1338 if ( pdata == NULL )
1339 return ERROR_DOS(ERRDOS,ERRnomem);
1341 *ppdata = pdata;
1342 memset((char *)pdata,'\0',max_data_bytes + 1024);
1344 switch (info_level) {
1345 case SMB_INFO_ALLOCATION:
1347 SMB_BIG_UINT dfree,dsize,bsize;
1348 data_len = 18;
1349 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1350 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1351 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1352 SIVAL(pdata,l1_cUnit,dsize);
1353 SIVAL(pdata,l1_cUnitAvail,dfree);
1354 SSVAL(pdata,l1_cbSector,512);
1355 DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1356 (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1357 (unsigned int)dfree, 512));
1358 break;
1361 case SMB_INFO_VOLUME:
1362 /* Return volume name */
1364 * Add volume serial number - hash of a combination of
1365 * the called hostname and the service name.
1367 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1368 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, 0);
1369 SCVAL(pdata,l2_vol_cch,len);
1370 data_len = l2_vol_szVolLabel + len;
1371 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1372 (unsigned)st.st_ctime, len, vname));
1373 break;
1375 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1376 case SMB_FS_ATTRIBUTE_INFORMATION:
1379 #if defined(HAVE_SYS_QUOTAS)
1380 quota_flag = FILE_VOLUME_QUOTAS;
1381 #endif
1383 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1384 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1385 quota_flag); /* FS ATTRIBUTES */
1387 SIVAL(pdata,4,255); /* Max filename component length */
1388 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1389 and will think we can't do long filenames */
1390 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1391 SIVAL(pdata,8,len);
1392 data_len = 12 + len;
1393 break;
1395 case SMB_QUERY_FS_LABEL_INFO:
1396 case SMB_FS_LABEL_INFORMATION:
1397 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1398 data_len = 4 + len;
1399 SIVAL(pdata,0,len);
1400 break;
1402 case SMB_QUERY_FS_VOLUME_INFO:
1403 case SMB_FS_VOLUME_INFORMATION:
1406 * Add volume serial number - hash of a combination of
1407 * the called hostname and the service name.
1409 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1410 (str_checksum(local_machine)<<16));
1412 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1413 SIVAL(pdata,12,len);
1414 data_len = 18+len;
1415 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1416 (int)strlen(vname),vname, lp_servicename(snum)));
1417 break;
1419 case SMB_QUERY_FS_SIZE_INFO:
1420 case SMB_FS_SIZE_INFORMATION:
1422 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1423 data_len = 24;
1424 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1425 block_size = lp_block_size(snum);
1426 if (bsize < block_size) {
1427 SMB_BIG_UINT factor = block_size/bsize;
1428 bsize = block_size;
1429 dsize /= factor;
1430 dfree /= factor;
1432 if (bsize > block_size) {
1433 SMB_BIG_UINT factor = bsize/block_size;
1434 bsize = block_size;
1435 dsize *= factor;
1436 dfree *= factor;
1438 bytes_per_sector = 512;
1439 sectors_per_unit = bsize/bytes_per_sector;
1440 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1441 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1442 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1443 SBIG_UINT(pdata,0,dsize);
1444 SBIG_UINT(pdata,8,dfree);
1445 SIVAL(pdata,16,sectors_per_unit);
1446 SIVAL(pdata,20,bytes_per_sector);
1447 break;
1450 case SMB_FS_FULL_SIZE_INFORMATION:
1452 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1453 data_len = 32;
1454 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1455 block_size = lp_block_size(snum);
1456 if (bsize < block_size) {
1457 SMB_BIG_UINT factor = block_size/bsize;
1458 bsize = block_size;
1459 dsize /= factor;
1460 dfree /= factor;
1462 if (bsize > block_size) {
1463 SMB_BIG_UINT factor = bsize/block_size;
1464 bsize = block_size;
1465 dsize *= factor;
1466 dfree *= factor;
1468 bytes_per_sector = 512;
1469 sectors_per_unit = bsize/bytes_per_sector;
1470 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1471 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1472 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1473 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1474 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1475 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1476 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1477 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1478 break;
1481 case SMB_QUERY_FS_DEVICE_INFO:
1482 case SMB_FS_DEVICE_INFORMATION:
1483 data_len = 8;
1484 SIVAL(pdata,0,0); /* dev type */
1485 SIVAL(pdata,4,0); /* characteristics */
1486 break;
1488 #ifdef HAVE_SYS_QUOTAS
1489 case SMB_FS_QUOTA_INFORMATION:
1491 * what we have to send --metze:
1493 * Unknown1: 24 NULL bytes
1494 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1495 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
1496 * Quota Flags: 2 byte :
1497 * Unknown3: 6 NULL bytes
1499 * 48 bytes total
1501 * details for Quota Flags:
1503 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1504 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
1505 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1506 * 0x0001 Enable Quotas: enable quota for this fs
1510 /* we need to fake up a fsp here,
1511 * because its not send in this call
1513 files_struct fsp;
1514 SMB_NTQUOTA_STRUCT quotas;
1516 ZERO_STRUCT(fsp);
1517 ZERO_STRUCT(quotas);
1519 fsp.conn = conn;
1520 fsp.fnum = -1;
1521 fsp.fd = -1;
1523 /* access check */
1524 if (conn->admin_user != True) {
1525 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1526 lp_servicename(SNUM(conn)),conn->user));
1527 return ERROR_DOS(ERRDOS,ERRnoaccess);
1530 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
1531 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
1532 return ERROR_DOS(ERRSRV,ERRerror);
1535 data_len = 48;
1537 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
1539 /* Unknown1 24 NULL bytes*/
1540 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
1541 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
1542 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
1544 /* Default Soft Quota 8 bytes */
1545 SBIG_UINT(pdata,24,quotas.softlim);
1547 /* Default Hard Quota 8 bytes */
1548 SBIG_UINT(pdata,32,quotas.hardlim);
1550 /* Quota flag 2 bytes */
1551 SSVAL(pdata,40,quotas.qflags);
1553 /* Unknown3 6 NULL bytes */
1554 SSVAL(pdata,42,0);
1555 SIVAL(pdata,44,0);
1557 break;
1559 #endif /* HAVE_SYS_QUOTAS */
1560 case SMB_FS_OBJECTID_INFORMATION:
1561 data_len = 64;
1562 break;
1565 * Query the version and capabilities of the CIFS UNIX extensions
1566 * in use.
1569 case SMB_QUERY_CIFS_UNIX_INFO:
1570 if (!lp_unix_extensions())
1571 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1572 data_len = 12;
1573 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
1574 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
1575 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
1576 break;
1578 case SMB_MAC_QUERY_FS_INFO:
1580 * Thursby MAC extension... ONLY on NTFS filesystems
1581 * once we do streams then we don't need this
1583 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1584 data_len = 88;
1585 SIVAL(pdata,84,0x100); /* Don't support mac... */
1586 break;
1588 /* drop through */
1589 default:
1590 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1594 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1596 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1598 return -1;
1601 #ifdef HAVE_SYS_QUOTAS
1602 /****************************************************************************
1603 Reply to a TRANS2_SETFSINFO (set filesystem info).
1604 ****************************************************************************/
1606 static int call_trans2setfsinfo(connection_struct *conn,
1607 char *inbuf, char *outbuf, int length, int bufsize,
1608 char **pparams, int total_params, char **ppdata, int total_data)
1610 char *pdata = *ppdata;
1611 char *params = *pparams;
1612 files_struct *fsp = NULL;
1613 uint16 info_level;
1614 int outsize;
1615 SMB_NTQUOTA_STRUCT quotas;
1617 ZERO_STRUCT(quotas);
1619 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
1621 /* access check */
1622 if ((conn->admin_user != True)||!CAN_WRITE(conn)) {
1623 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1624 lp_servicename(SNUM(conn)),conn->user));
1625 return ERROR_DOS(ERRSRV,ERRaccess);
1628 /* */
1629 if (total_params < 4) {
1630 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
1631 total_params));
1632 return ERROR_DOS(ERRDOS,ERRinvalidparam);
1635 fsp = file_fsp(params,0);
1637 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
1638 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
1639 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
1642 info_level = SVAL(params,2);
1644 switch(info_level) {
1645 case SMB_FS_QUOTA_INFORMATION:
1646 /* note: normaly there're 48 bytes,
1647 * but we didn't use the last 6 bytes for now
1648 * --metze
1650 if (total_data < 42) {
1651 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
1652 total_data));
1653 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1656 /* unknown_1 24 NULL bytes in pdata*/
1658 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
1659 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
1660 #ifdef LARGE_SMB_OFF_T
1661 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
1662 #else /* LARGE_SMB_OFF_T */
1663 if ((IVAL(pdata,28) != 0)&&
1664 ((quotas.softlim != 0xFFFFFFFF)||
1665 (IVAL(pdata,28)!=0xFFFFFFFF))) {
1666 /* more than 32 bits? */
1667 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1669 #endif /* LARGE_SMB_OFF_T */
1671 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
1672 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
1673 #ifdef LARGE_SMB_OFF_T
1674 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
1675 #else /* LARGE_SMB_OFF_T */
1676 if ((IVAL(pdata,36) != 0)&&
1677 ((quotas.hardlim != 0xFFFFFFFF)||
1678 (IVAL(pdata,36)!=0xFFFFFFFF))) {
1679 /* more than 32 bits? */
1680 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1682 #endif /* LARGE_SMB_OFF_T */
1684 /* quota_flags 2 bytes **/
1685 quotas.qflags = SVAL(pdata,40);
1687 /* unknown_2 6 NULL bytes follow*/
1689 /* now set the quotas */
1690 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
1691 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
1692 return ERROR_DOS(ERRSRV,ERRerror);
1695 break;
1696 default:
1697 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
1698 info_level));
1699 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1700 break;
1704 * sending this reply works fine,
1705 * but I'm not sure it's the same
1706 * like windows do...
1707 * --metze
1709 outsize = set_message(outbuf,10,0,True);
1711 return outsize;
1713 #endif /* HAVE_SYS_QUOTAS */
1715 /****************************************************************************
1716 * Utility function to set bad path error.
1717 ****************************************************************************/
1719 NTSTATUS set_bad_path_error(int err, BOOL bad_path)
1721 if((err == ENOENT) && bad_path) {
1722 unix_ERR_class = ERRDOS;
1723 unix_ERR_code = ERRbadpath;
1724 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1726 return NT_STATUS_OK;
1729 /****************************************************************************
1730 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1731 file name or file id).
1732 ****************************************************************************/
1734 static int call_trans2qfilepathinfo(connection_struct *conn,
1735 char *inbuf, char *outbuf, int length,
1736 int bufsize,
1737 char **pparams, int total_params, char **ppdata, int total_data)
1739 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1740 char *params = *pparams;
1741 char *pdata = *ppdata;
1742 uint16 tran_call = SVAL(inbuf, smb_setup0);
1743 uint16 info_level;
1744 int mode=0;
1745 SMB_OFF_T file_size=0;
1746 SMB_BIG_UINT allocation_size=0;
1747 unsigned int data_size;
1748 SMB_STRUCT_STAT sbuf;
1749 pstring fname, dos_fname;
1750 char *fullpathname;
1751 char *base_name;
1752 char *p;
1753 SMB_OFF_T pos = 0;
1754 BOOL bad_path = False;
1755 BOOL delete_pending = False;
1756 int len;
1757 time_t c_time;
1758 files_struct *fsp = NULL;
1760 if (!params)
1761 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1763 if (tran_call == TRANSACT2_QFILEINFO) {
1764 if (total_params < 4)
1765 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1767 fsp = file_fsp(params,0);
1768 info_level = SVAL(params,2);
1770 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1772 if(fsp && (fsp->fake_file_handle)) {
1774 * This is actually for the QUOTA_FAKE_FILE --metze
1777 pstrcpy(fname, fsp->fsp_name);
1778 unix_convert(fname,conn,0,&bad_path,&sbuf);
1779 if (!check_name(fname,conn)) {
1780 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno)));
1781 set_bad_path_error(errno, bad_path);
1782 return(UNIXERROR(ERRDOS,ERRbadpath));
1785 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1787 * This is actually a QFILEINFO on a directory
1788 * handle (returned from an NT SMB). NT5.0 seems
1789 * to do this call. JRA.
1791 pstrcpy(fname, fsp->fsp_name);
1792 unix_convert(fname,conn,0,&bad_path,&sbuf);
1793 if (!check_name(fname,conn)) {
1794 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1795 set_bad_path_error(errno, bad_path);
1796 return(UNIXERROR(ERRDOS,ERRbadpath));
1799 if (INFO_LEVEL_IS_UNIX(info_level)) {
1800 /* Always do lstat for UNIX calls. */
1801 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
1802 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
1803 set_bad_path_error(errno, bad_path);
1804 return(UNIXERROR(ERRDOS,ERRbadpath));
1806 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
1807 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
1808 set_bad_path_error(errno, bad_path);
1809 return(UNIXERROR(ERRDOS,ERRbadpath));
1812 delete_pending = fsp->directory_delete_on_close;
1813 } else {
1815 * Original code - this is an open file.
1817 CHECK_FSP(fsp,conn);
1819 pstrcpy(fname, fsp->fsp_name);
1820 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
1821 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
1822 return(UNIXERROR(ERRDOS,ERRbadfid));
1824 if((pos = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1825 return(UNIXERROR(ERRDOS,ERRnoaccess));
1827 delete_pending = fsp->delete_on_close;
1829 } else {
1830 /* qpathinfo */
1831 if (total_params < 6)
1832 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1834 info_level = SVAL(params,0);
1836 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1838 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
1840 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1842 unix_convert(fname,conn,0,&bad_path,&sbuf);
1843 if (!check_name(fname,conn)) {
1844 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1845 set_bad_path_error(errno, bad_path);
1846 return(UNIXERROR(ERRDOS,ERRbadpath));
1849 if (INFO_LEVEL_IS_UNIX(info_level)) {
1850 /* Always do lstat for UNIX calls. */
1851 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
1852 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
1853 set_bad_path_error(errno, bad_path);
1854 return(UNIXERROR(ERRDOS,ERRbadpath));
1856 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
1857 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
1858 set_bad_path_error(errno, bad_path);
1859 return(UNIXERROR(ERRDOS,ERRbadpath));
1863 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
1864 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1866 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1867 fname,info_level,tran_call,total_data));
1869 p = strrchr_m(fname,'/');
1870 if (!p)
1871 base_name = fname;
1872 else
1873 base_name = p+1;
1875 mode = dos_mode(conn,fname,&sbuf);
1876 fullpathname = fname;
1877 file_size = get_file_size(sbuf);
1878 allocation_size = get_allocation_size(fsp,&sbuf);
1879 if (mode & aDIR)
1880 file_size = 0;
1882 params = Realloc(*pparams,2);
1883 if (params == NULL)
1884 return ERROR_DOS(ERRDOS,ERRnomem);
1885 *pparams = params;
1886 memset((char *)params,'\0',2);
1887 data_size = max_data_bytes + 1024;
1888 pdata = Realloc(*ppdata, data_size);
1889 if ( pdata == NULL )
1890 return ERROR_DOS(ERRDOS,ERRnomem);
1891 *ppdata = pdata;
1893 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1894 /* uggh, EAs for OS2 */
1895 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1896 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1899 memset((char *)pdata,'\0',data_size);
1901 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1903 if (lp_dos_filetime_resolution(SNUM(conn))) {
1904 c_time &= ~1;
1905 sbuf.st_atime &= ~1;
1906 sbuf.st_mtime &= ~1;
1907 sbuf.st_mtime &= ~1;
1910 /* NT expects the name to be in an exact form of the *full*
1911 filename. See the trans2 torture test */
1912 if (strequal(base_name,".")) {
1913 pstrcpy(dos_fname, "\\");
1914 } else {
1915 snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname);
1916 string_replace(dos_fname, '/', '\\');
1919 switch (info_level) {
1920 case SMB_INFO_STANDARD:
1921 case SMB_INFO_QUERY_EA_SIZE:
1922 data_size = (info_level==1?22:26);
1923 put_dos_date2(pdata,l1_fdateCreation,c_time);
1924 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1925 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1926 SIVAL(pdata,l1_cbFile,(uint32)file_size);
1927 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
1928 SSVAL(pdata,l1_attrFile,mode);
1929 SIVAL(pdata,l1_attrFile+2,0); /* this is what win2003 does */
1930 break;
1932 case SMB_INFO_IS_NAME_VALID:
1933 if (tran_call == TRANSACT2_QFILEINFO) {
1934 /* os/2 needs this ? really ?*/
1935 return ERROR_DOS(ERRDOS,ERRbadfunc);
1937 data_size = 0;
1938 break;
1940 case SMB_INFO_QUERY_EAS_FROM_LIST:
1941 data_size = 24;
1942 put_dos_date2(pdata,0,c_time);
1943 put_dos_date2(pdata,4,sbuf.st_atime);
1944 put_dos_date2(pdata,8,sbuf.st_mtime);
1945 SIVAL(pdata,12,(uint32)file_size);
1946 SIVAL(pdata,16,(uint32)allocation_size);
1947 SIVAL(pdata,20,mode);
1948 break;
1950 case SMB_INFO_QUERY_ALL_EAS:
1951 data_size = 4;
1952 SIVAL(pdata,0,0); /* ea size */
1953 break;
1955 case SMB_FILE_BASIC_INFORMATION:
1956 case SMB_QUERY_FILE_BASIC_INFO:
1958 if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1959 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1960 else {
1961 data_size = 40;
1962 SIVAL(pdata,36,0);
1964 put_long_date(pdata,c_time);
1965 put_long_date(pdata+8,sbuf.st_atime);
1966 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1967 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1968 SIVAL(pdata,32,mode);
1970 DEBUG(5,("SMB_QFBI - "));
1972 time_t create_time = c_time;
1973 DEBUG(5,("create: %s ", ctime(&create_time)));
1975 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1976 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1977 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1978 DEBUG(5,("mode: %x\n", mode));
1980 break;
1982 case SMB_FILE_STANDARD_INFORMATION:
1983 case SMB_QUERY_FILE_STANDARD_INFO:
1985 data_size = 24;
1986 SOFF_T(pdata,0,allocation_size);
1987 SOFF_T(pdata,8,file_size);
1988 SIVAL(pdata,16,sbuf.st_nlink);
1989 SCVAL(pdata,20,0);
1990 SCVAL(pdata,21,(mode&aDIR)?1:0);
1991 break;
1993 case SMB_FILE_EA_INFORMATION:
1994 case SMB_QUERY_FILE_EA_INFO:
1995 data_size = 4;
1996 break;
1998 /* Get the 8.3 name - used if NT SMB was negotiated. */
1999 case SMB_QUERY_FILE_ALT_NAME_INFO:
2000 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2002 pstring short_name;
2004 pstrcpy(short_name,base_name);
2005 /* Mangle if not already 8.3 */
2006 if(!mangle_is_8_3(short_name, True)) {
2007 mangle_map(short_name,True,True,SNUM(conn));
2009 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2010 data_size = 4 + len;
2011 SIVAL(pdata,0,len);
2012 break;
2015 case SMB_QUERY_FILE_NAME_INFO:
2017 this must be *exactly* right for ACLs on mapped drives to work
2019 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2020 data_size = 4 + len;
2021 SIVAL(pdata,0,len);
2022 break;
2024 case SMB_FILE_ALLOCATION_INFORMATION:
2025 case SMB_QUERY_FILE_ALLOCATION_INFO:
2026 data_size = 8;
2027 SOFF_T(pdata,0,allocation_size);
2028 break;
2030 case SMB_FILE_END_OF_FILE_INFORMATION:
2031 case SMB_QUERY_FILE_END_OF_FILEINFO:
2032 data_size = 8;
2033 SOFF_T(pdata,0,file_size);
2034 break;
2036 case SMB_QUERY_FILE_ALL_INFO:
2037 case SMB_FILE_ALL_INFORMATION:
2038 put_long_date(pdata,c_time);
2039 put_long_date(pdata+8,sbuf.st_atime);
2040 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2041 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2042 SIVAL(pdata,32,mode);
2043 pdata += 40;
2044 SOFF_T(pdata,0,allocation_size);
2045 SOFF_T(pdata,8,file_size);
2046 SIVAL(pdata,16,sbuf.st_nlink);
2047 SCVAL(pdata,20,delete_pending);
2048 SCVAL(pdata,21,(mode&aDIR)?1:0);
2049 pdata += 24;
2050 pdata += 4; /* EA info */
2051 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2052 SIVAL(pdata,0,len);
2053 pdata += 4 + len;
2054 data_size = PTR_DIFF(pdata,(*ppdata));
2055 break;
2057 case SMB_FILE_INTERNAL_INFORMATION:
2058 /* This should be an index number - looks like
2059 dev/ino to me :-)
2061 I think this causes us to fail the IFSKIT
2062 BasicFileInformationTest. -tpot */
2064 SIVAL(pdata,0,sbuf.st_dev);
2065 SIVAL(pdata,4,sbuf.st_ino);
2066 data_size = 8;
2067 break;
2069 case SMB_FILE_ACCESS_INFORMATION:
2070 SIVAL(pdata,0,0x12019F); /* ??? */
2071 data_size = 4;
2072 break;
2074 case SMB_FILE_NAME_INFORMATION:
2075 /* Pathname with leading '\'. */
2077 size_t byte_len;
2078 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2079 SIVAL(pdata,0,byte_len);
2080 data_size = 4 + byte_len;
2081 break;
2084 case SMB_FILE_DISPOSITION_INFORMATION:
2085 data_size = 1;
2086 SCVAL(pdata,0,delete_pending);
2087 break;
2089 case SMB_FILE_POSITION_INFORMATION:
2090 data_size = 8;
2091 SOFF_T(pdata,0,pos);
2092 break;
2094 case SMB_FILE_MODE_INFORMATION:
2095 SIVAL(pdata,0,mode);
2096 data_size = 4;
2097 break;
2099 case SMB_FILE_ALIGNMENT_INFORMATION:
2100 SIVAL(pdata,0,0); /* No alignment needed. */
2101 data_size = 4;
2102 break;
2104 #if 0
2106 * NT4 server just returns "invalid query" to this - if we try to answer
2107 * it then NTws gets a BSOD! (tridge).
2108 * W2K seems to want this. JRA.
2110 case SMB_QUERY_FILE_STREAM_INFO:
2111 #endif
2112 case SMB_FILE_STREAM_INFORMATION:
2113 if (mode & aDIR) {
2114 data_size = 0;
2115 } else {
2116 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2117 SIVAL(pdata,0,0); /* ??? */
2118 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2119 SOFF_T(pdata,8,file_size);
2120 SIVAL(pdata,16,allocation_size);
2121 SIVAL(pdata,20,0); /* ??? */
2122 data_size = 24 + byte_len;
2124 break;
2126 case SMB_QUERY_COMPRESSION_INFO:
2127 case SMB_FILE_COMPRESSION_INFORMATION:
2128 SOFF_T(pdata,0,file_size);
2129 SIVAL(pdata,8,0); /* ??? */
2130 SIVAL(pdata,12,0); /* ??? */
2131 data_size = 16;
2132 break;
2134 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2135 put_long_date(pdata,c_time);
2136 put_long_date(pdata+8,sbuf.st_atime);
2137 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2138 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2139 SIVAL(pdata,32,allocation_size);
2140 SOFF_T(pdata,40,file_size);
2141 SIVAL(pdata,48,mode);
2142 SIVAL(pdata,52,0); /* ??? */
2143 data_size = 56;
2144 break;
2146 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2147 SIVAL(pdata,0,mode);
2148 SIVAL(pdata,4,0);
2149 data_size = 8;
2150 break;
2153 * CIFS UNIX Extensions.
2156 case SMB_QUERY_FILE_UNIX_BASIC:
2158 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2160 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2161 pdata += 8;
2163 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2164 pdata += 8;
2166 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2167 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2168 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2169 pdata += 24;
2171 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2172 SIVAL(pdata,4,0);
2173 pdata += 8;
2175 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2176 SIVAL(pdata,4,0);
2177 pdata += 8;
2179 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2180 pdata += 4;
2182 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2183 SIVAL(pdata,4,0);
2184 pdata += 8;
2186 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2187 SIVAL(pdata,4,0);
2188 pdata += 8;
2190 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2191 pdata += 8;
2193 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2194 SIVAL(pdata,4,0);
2195 pdata += 8;
2197 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2198 SIVAL(pdata,4,0);
2199 pdata += 8+1;
2200 data_size = PTR_DIFF(pdata,(*ppdata));
2203 int i;
2204 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2206 for (i=0; i<100; i++)
2207 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2208 DEBUG(4,("\n"));
2211 break;
2213 case SMB_QUERY_FILE_UNIX_LINK:
2215 pstring buffer;
2217 #ifdef S_ISLNK
2218 if(!S_ISLNK(sbuf.st_mode))
2219 return(UNIXERROR(ERRSRV,ERRbadlink));
2220 #else
2221 return(UNIXERROR(ERRDOS,ERRbadlink));
2222 #endif
2223 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2224 if (len == -1)
2225 return(UNIXERROR(ERRDOS,ERRnoaccess));
2226 buffer[len] = 0;
2227 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2228 pdata += len;
2229 data_size = PTR_DIFF(pdata,(*ppdata));
2231 break;
2234 default:
2235 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2238 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size);
2240 return(-1);
2243 /****************************************************************************
2244 Deal with the internal needs of setting the delete on close flag. Note that
2245 as the tdb locking is recursive, it is safe to call this from within
2246 open_file_shared. JRA.
2247 ****************************************************************************/
2249 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2252 * Only allow delete on close for writable shares.
2255 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2256 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2257 fsp->fsp_name ));
2258 return NT_STATUS_ACCESS_DENIED;
2261 * Only allow delete on close for files/directories opened with delete intent.
2264 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2265 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2266 fsp->fsp_name ));
2267 return NT_STATUS_ACCESS_DENIED;
2270 if(fsp->is_directory) {
2271 fsp->directory_delete_on_close = delete_on_close;
2272 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2273 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2274 } else {
2275 fsp->delete_on_close = delete_on_close;
2276 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2277 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2280 return NT_STATUS_OK;
2283 /****************************************************************************
2284 Sets the delete on close flag over all share modes on this file.
2285 Modify the share mode entry for all files open
2286 on this device and inode to tell other smbds we have
2287 changed the delete on close flag. This will be noticed
2288 in the close code, the last closer will delete the file
2289 if flag is set.
2290 ****************************************************************************/
2292 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2294 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2295 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2297 if (fsp->is_directory || fsp->is_stat)
2298 return NT_STATUS_OK;
2300 if (lock_share_entry_fsp(fsp) == False)
2301 return NT_STATUS_ACCESS_DENIED;
2303 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2304 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2305 fsp->fsp_name ));
2306 unlock_share_entry_fsp(fsp);
2307 return NT_STATUS_ACCESS_DENIED;
2310 unlock_share_entry_fsp(fsp);
2311 return NT_STATUS_OK;
2314 /****************************************************************************
2315 Returns true if this pathname is within the share, and thus safe.
2316 ****************************************************************************/
2318 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2320 #ifdef PATH_MAX
2321 char resolved_name[PATH_MAX+1];
2322 #else
2323 pstring resolved_name;
2324 #endif
2325 fstring last_component;
2326 pstring link_dest;
2327 pstring link_test;
2328 char *p;
2329 BOOL bad_path = False;
2330 SMB_STRUCT_STAT sbuf;
2332 pstrcpy(link_dest, link_dest_in);
2333 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2335 /* Store the UNIX converted path. */
2336 pstrcpy(link_dest_out, link_dest);
2338 p = strrchr(link_dest, '/');
2339 if (p) {
2340 fstrcpy(last_component, p+1);
2341 *p = '\0';
2342 } else {
2343 fstrcpy(last_component, link_dest);
2344 pstrcpy(link_dest, "./");
2347 if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL)
2348 return -1;
2350 pstrcpy(link_dest, resolved_name);
2351 pstrcat(link_dest, "/");
2352 pstrcat(link_dest, last_component);
2354 if (*link_dest != '/') {
2355 /* Relative path. */
2356 pstrcpy(link_test, conn->connectpath);
2357 pstrcat(link_test, "/");
2358 pstrcat(link_test, link_dest);
2359 } else {
2360 pstrcpy(link_test, link_dest);
2364 * Check if the link is within the share.
2367 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2368 errno = EACCES;
2369 return -1;
2371 return 0;
2374 /****************************************************************************
2375 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2376 ****************************************************************************/
2378 static int call_trans2setfilepathinfo(connection_struct *conn,
2379 char *inbuf, char *outbuf, int length, int bufsize,
2380 char **pparams, int total_params, char **ppdata, int total_data)
2382 char *params = *pparams;
2383 char *pdata = *ppdata;
2384 uint16 tran_call = SVAL(inbuf, smb_setup0);
2385 uint16 info_level;
2386 int dosmode=0;
2387 SMB_OFF_T size=0;
2388 struct utimbuf tvs;
2389 SMB_STRUCT_STAT sbuf;
2390 pstring fname;
2391 int fd = -1;
2392 BOOL bad_path = False;
2393 files_struct *fsp = NULL;
2394 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2395 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2396 mode_t unixmode = 0;
2398 if (!params)
2399 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2401 if (tran_call == TRANSACT2_SETFILEINFO) {
2402 if (total_params < 4)
2403 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2405 fsp = file_fsp(params,0);
2406 info_level = SVAL(params,2);
2408 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2410 * This is actually a SETFILEINFO on a directory
2411 * handle (returned from an NT SMB). NT5.0 seems
2412 * to do this call. JRA.
2414 pstrcpy(fname, fsp->fsp_name);
2415 unix_convert(fname,conn,0,&bad_path,&sbuf);
2416 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2417 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2418 set_bad_path_error(errno, bad_path);
2419 return(UNIXERROR(ERRDOS,ERRbadpath));
2421 } else if (fsp && fsp->print_file) {
2423 * Doing a DELETE_ON_CLOSE should cancel a print job.
2425 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
2426 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2428 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
2430 SSVAL(params,0,0);
2431 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2432 return(-1);
2433 } else
2434 return (UNIXERROR(ERRDOS,ERRbadpath));
2435 } else {
2437 * Original code - this is an open file.
2439 CHECK_FSP(fsp,conn);
2441 pstrcpy(fname, fsp->fsp_name);
2442 fd = fsp->fd;
2444 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
2445 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2446 return(UNIXERROR(ERRDOS,ERRbadfid));
2449 } else {
2450 /* set path info */
2451 if (total_params < 6)
2452 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2454 info_level = SVAL(params,0);
2455 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
2456 unix_convert(fname,conn,0,&bad_path,&sbuf);
2457 if(!check_name(fname, conn)) {
2458 set_bad_path_error(errno, bad_path);
2459 return(UNIXERROR(ERRDOS,ERRbadpath));
2463 * For CIFS UNIX extensions the target name may not exist.
2466 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2467 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
2468 set_bad_path_error(errno, bad_path);
2469 return(UNIXERROR(ERRDOS,ERRbadpath));
2473 if (!CAN_WRITE(conn))
2474 return ERROR_DOS(ERRSRV,ERRaccess);
2476 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2477 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2479 if (VALID_STAT(sbuf))
2480 unixmode = sbuf.st_mode;
2482 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
2483 tran_call,fname,info_level,total_data));
2485 /* Realloc the parameter and data sizes */
2486 params = Realloc(*pparams,2);
2487 if(params == NULL)
2488 return ERROR_DOS(ERRDOS,ERRnomem);
2489 *pparams = params;
2491 SSVAL(params,0,0);
2493 if (fsp) {
2494 /* the pending modtime overrides the current modtime */
2495 sbuf.st_mtime = fsp->pending_modtime;
2498 size = get_file_size(sbuf);
2499 tvs.modtime = sbuf.st_mtime;
2500 tvs.actime = sbuf.st_atime;
2501 dosmode = dos_mode(conn,fname,&sbuf);
2502 unixmode = sbuf.st_mode;
2504 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2505 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2507 switch (info_level) {
2508 case SMB_INFO_STANDARD:
2510 if (total_data < l1_cbFile+4)
2511 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2513 /* access time */
2514 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2516 /* write time */
2517 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2519 dosmode = SVAL(pdata,l1_attrFile);
2520 size = IVAL(pdata,l1_cbFile);
2522 break;
2525 case SMB_INFO_SET_EA:
2526 return(ERROR_DOS(ERRDOS,ERReasnotsupported));
2528 /* XXXX um, i don't think this is right.
2529 it's also not in the cifs6.txt spec.
2531 case SMB_INFO_QUERY_EAS_FROM_LIST:
2532 if (total_data < 28)
2533 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2535 tvs.actime = make_unix_date2(pdata+8);
2536 tvs.modtime = make_unix_date2(pdata+12);
2537 size = IVAL(pdata,16);
2538 dosmode = IVAL(pdata,24);
2539 break;
2541 /* XXXX nor this. not in cifs6.txt, either. */
2542 case SMB_INFO_QUERY_ALL_EAS:
2543 if (total_data < 28)
2544 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2546 tvs.actime = make_unix_date2(pdata+8);
2547 tvs.modtime = make_unix_date2(pdata+12);
2548 size = IVAL(pdata,16);
2549 dosmode = IVAL(pdata,24);
2550 break;
2552 case SMB_SET_FILE_BASIC_INFO:
2553 case SMB_FILE_BASIC_INFORMATION:
2555 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2556 time_t write_time;
2557 time_t changed_time;
2559 if (total_data < 36)
2560 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2562 /* Ignore create time at offset pdata. */
2564 /* access time */
2565 tvs.actime = interpret_long_date(pdata+8);
2567 write_time = interpret_long_date(pdata+16);
2568 changed_time = interpret_long_date(pdata+24);
2570 tvs.modtime = MIN(write_time, changed_time);
2572 if (write_time > tvs.modtime && write_time != 0xffffffff) {
2573 tvs.modtime = write_time;
2575 /* Prefer a defined time to an undefined one. */
2576 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2577 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2578 ? changed_time : write_time);
2580 /* attributes */
2581 dosmode = IVAL(pdata,32);
2582 break;
2585 case SMB_FILE_ALLOCATION_INFORMATION:
2586 case SMB_SET_FILE_ALLOCATION_INFO:
2588 int ret = -1;
2589 SMB_BIG_UINT allocation_size;
2591 if (total_data < 8)
2592 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2594 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
2595 #ifdef LARGE_SMB_OFF_T
2596 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
2597 #else /* LARGE_SMB_OFF_T */
2598 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2599 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2600 #endif /* LARGE_SMB_OFF_T */
2601 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2602 fname, (double)allocation_size ));
2604 if (allocation_size)
2605 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
2607 if(allocation_size != get_file_size(sbuf)) {
2608 SMB_STRUCT_STAT new_sbuf;
2610 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2611 fname, (double)allocation_size ));
2613 if (fd == -1) {
2614 files_struct *new_fsp = NULL;
2615 int access_mode = 0;
2616 int action = 0;
2618 if(global_oplock_break) {
2619 /* Queue this file modify as we are the process of an oplock break. */
2621 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2622 DEBUGADD(2,( "in oplock break state.\n"));
2624 push_oplock_pending_smb_message(inbuf, length);
2625 return -1;
2628 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2629 SET_OPEN_MODE(DOS_OPEN_RDWR),
2630 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2631 0, 0, &access_mode, &action);
2633 if (new_fsp == NULL)
2634 return(UNIXERROR(ERRDOS,ERRbadpath));
2635 ret = vfs_allocate_file_space(new_fsp, allocation_size);
2636 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2637 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2638 new_fsp->fnum, strerror(errno)));
2639 ret = -1;
2641 close_file(new_fsp,True);
2642 } else {
2643 ret = vfs_allocate_file_space(fsp, allocation_size);
2644 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
2645 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2646 fsp->fnum, strerror(errno)));
2647 ret = -1;
2650 if (ret == -1)
2651 return ERROR_NT(NT_STATUS_DISK_FULL);
2653 /* Allocate can truncate size... */
2654 size = get_file_size(new_sbuf);
2657 break;
2660 case SMB_FILE_END_OF_FILE_INFORMATION:
2661 case SMB_SET_FILE_END_OF_FILE_INFO:
2663 if (total_data < 8)
2664 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2666 size = IVAL(pdata,0);
2667 #ifdef LARGE_SMB_OFF_T
2668 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2669 #else /* LARGE_SMB_OFF_T */
2670 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2671 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2672 #endif /* LARGE_SMB_OFF_T */
2673 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2674 break;
2677 case SMB_FILE_DISPOSITION_INFORMATION:
2678 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2680 BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
2681 NTSTATUS status;
2683 if (total_data < 1)
2684 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2686 if (tran_call != TRANSACT2_SETFILEINFO)
2687 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2689 if (fsp == NULL)
2690 return(UNIXERROR(ERRDOS,ERRbadfid));
2692 status = set_delete_on_close_internal(fsp, delete_on_close);
2694 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2695 return ERROR_NT(status);
2697 /* The set is across all open files on this dev/inode pair. */
2698 status =set_delete_on_close_over_all(fsp, delete_on_close);
2699 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2700 return ERROR_NT(status);
2702 break;
2706 * CIFS UNIX extensions.
2709 case SMB_SET_FILE_UNIX_BASIC:
2711 uint32 raw_unixmode;
2713 if (total_data < 100)
2714 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2716 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
2717 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
2718 size=IVAL(pdata,0); /* first 8 Bytes are size */
2719 #ifdef LARGE_SMB_OFF_T
2720 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2721 #else /* LARGE_SMB_OFF_T */
2722 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2723 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2724 #endif /* LARGE_SMB_OFF_T */
2726 pdata+=24; /* ctime & st_blocks are not changed */
2727 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
2728 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
2729 pdata+=16;
2730 set_owner = (uid_t)IVAL(pdata,0);
2731 pdata += 8;
2732 set_grp = (gid_t)IVAL(pdata,0);
2733 pdata += 8;
2734 raw_unixmode = IVAL(pdata,28);
2735 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2736 dosmode = 0; /* Ensure dos mode change doesn't override this. */
2738 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2739 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2740 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2742 if (!VALID_STAT(sbuf)) {
2745 * The only valid use of this is to create character and block
2746 * devices, and named pipes. This is deprecated (IMHO) and
2747 * a new info level should be used for mknod. JRA.
2750 #if !defined(HAVE_MAKEDEV_FN)
2751 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2752 #else /* HAVE_MAKEDEV_FN */
2753 uint32 file_type = IVAL(pdata,0);
2754 uint32 dev_major = IVAL(pdata,4);
2755 uint32 dev_minor = IVAL(pdata,12);
2757 uid_t myuid = geteuid();
2758 gid_t mygid = getegid();
2759 SMB_DEV_T dev;
2761 if (tran_call == TRANSACT2_SETFILEINFO)
2762 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2764 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2765 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2767 dev = makedev(dev_major, dev_minor);
2769 /* We can only create as the owner/group we are. */
2771 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2772 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2773 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2774 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2776 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2777 file_type != UNIX_TYPE_FIFO)
2778 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2780 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2781 0%o for file %s\n", (double)dev, unixmode, fname ));
2783 /* Ok - do the mknod. */
2784 if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
2785 return(UNIXERROR(ERRDOS,ERRnoaccess));
2787 inherit_access_acl(conn, fname, unixmode);
2789 SSVAL(params,0,0);
2790 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2791 return(-1);
2792 #endif /* HAVE_MAKEDEV_FN */
2797 * Deal with the UNIX specific mode set.
2800 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
2801 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2802 (unsigned int)unixmode, fname ));
2803 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
2804 return(UNIXERROR(ERRDOS,ERRnoaccess));
2808 * Deal with the UNIX specific uid set.
2811 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
2812 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2813 (unsigned int)set_owner, fname ));
2814 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
2815 return(UNIXERROR(ERRDOS,ERRnoaccess));
2819 * Deal with the UNIX specific gid set.
2822 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
2823 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2824 (unsigned int)set_owner, fname ));
2825 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
2826 return(UNIXERROR(ERRDOS,ERRnoaccess));
2828 break;
2831 case SMB_SET_FILE_UNIX_LINK:
2833 pstring link_dest;
2834 /* Set a symbolic link. */
2835 /* Don't allow this if follow links is false. */
2837 if (!lp_symlinks(SNUM(conn)))
2838 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2840 /* Disallow if already exists. */
2841 if (VALID_STAT(sbuf))
2842 return(ERROR_DOS(ERRDOS,ERRbadpath));
2844 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2846 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2847 return(UNIXERROR(ERRDOS,ERRnoaccess));
2849 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2850 fname, link_dest ));
2852 if (SMB_VFS_SYMLINK(conn,link_dest,fname) != 0)
2853 return(UNIXERROR(ERRDOS,ERRnoaccess));
2854 SSVAL(params,0,0);
2855 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2856 return(-1);
2859 case SMB_SET_FILE_UNIX_HLINK:
2861 pstring link_dest;
2863 /* Set a hard link. */
2865 /* Disallow if already exists. */
2866 if (VALID_STAT(sbuf))
2867 return(ERROR_DOS(ERRDOS,ERRbadpath));
2869 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2871 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2872 return(UNIXERROR(ERRDOS,ERRnoaccess));
2874 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2875 fname, link_dest ));
2877 if (SMB_VFS_LINK(conn,link_dest,fname) != 0)
2878 return(UNIXERROR(ERRDOS,ERRnoaccess));
2879 SSVAL(params,0,0);
2880 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2881 return(-1);
2884 default:
2885 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2888 /* get some defaults (no modifications) if any info is zero or -1. */
2889 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2890 tvs.actime = sbuf.st_atime;
2892 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2893 tvs.modtime = sbuf.st_mtime;
2895 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2896 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2897 DEBUG(6,("size: %.0f ", (double)size));
2899 if (S_ISDIR(sbuf.st_mode))
2900 dosmode |= aDIR;
2901 else
2902 dosmode &= ~aDIR;
2904 DEBUG(6,("dosmode: %x\n" , dosmode));
2906 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2907 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2908 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2909 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2912 * Only do this test if we are not explicitly
2913 * changing the size of a file.
2915 if (!size)
2916 size = get_file_size(sbuf);
2920 * Try and set the times, size and mode of this file -
2921 * if they are different from the current values
2923 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2924 if(fsp != NULL) {
2926 * This was a setfileinfo on an open file.
2927 * NT does this a lot. It's actually pointless
2928 * setting the time here, as it will be overwritten
2929 * on the next write, so we save the request
2930 * away and will set it on file close. JRA.
2933 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2934 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
2935 fsp->pending_modtime = tvs.modtime;
2938 } else {
2940 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2942 if(file_utime(conn, fname, &tvs)!=0)
2943 return(UNIXERROR(ERRDOS,ERRnoaccess));
2947 /* check the mode isn't different, before changing it */
2948 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
2950 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
2952 if(file_chmod(conn, fname, dosmode, NULL)) {
2953 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2954 return(UNIXERROR(ERRDOS,ERRnoaccess));
2958 if (size != get_file_size(sbuf)) {
2960 int ret;
2962 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2963 fname, (double)size ));
2965 if (fd == -1) {
2966 files_struct *new_fsp = NULL;
2967 int access_mode = 0;
2968 int action = 0;
2970 if(global_oplock_break) {
2971 /* Queue this file modify as we are the process of an oplock break. */
2973 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2974 DEBUGADD(2,( "in oplock break state.\n"));
2976 push_oplock_pending_smb_message(inbuf, length);
2977 return -1;
2980 new_fsp = open_file_shared(conn, fname, &sbuf,
2981 SET_OPEN_MODE(DOS_OPEN_RDWR),
2982 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2983 0, 0, &access_mode, &action);
2985 if (new_fsp == NULL)
2986 return(UNIXERROR(ERRDOS,ERRbadpath));
2987 ret = vfs_set_filelen(new_fsp, size);
2988 close_file(new_fsp,True);
2989 } else {
2990 ret = vfs_set_filelen(fsp, size);
2993 if (ret == -1)
2994 return (UNIXERROR(ERRHRD,ERRdiskfull));
2997 SSVAL(params,0,0);
2998 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3000 return(-1);
3003 /****************************************************************************
3004 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3005 ****************************************************************************/
3007 static int call_trans2mkdir(connection_struct *conn,
3008 char *inbuf, char *outbuf, int length, int bufsize,
3009 char **pparams, int total_params, char **ppdata, int total_data)
3011 char *params = *pparams;
3012 pstring directory;
3013 int ret = -1;
3014 SMB_STRUCT_STAT sbuf;
3015 BOOL bad_path = False;
3017 if (!CAN_WRITE(conn))
3018 return ERROR_DOS(ERRSRV,ERRaccess);
3020 if (total_params < 4)
3021 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3023 srvstr_pull(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE);
3025 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3027 unix_convert(directory,conn,0,&bad_path,&sbuf);
3028 if (check_name(directory,conn))
3029 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3031 if(ret < 0) {
3032 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3033 set_bad_path_error(errno, bad_path);
3034 return(UNIXERROR(ERRDOS,ERRnoaccess));
3037 /* Realloc the parameter and data sizes */
3038 params = Realloc(*pparams,2);
3039 if(params == NULL)
3040 return ERROR_DOS(ERRDOS,ERRnomem);
3041 *pparams = params;
3043 SSVAL(params,0,0);
3045 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3047 return(-1);
3050 /****************************************************************************
3051 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3052 We don't actually do this - we just send a null response.
3053 ****************************************************************************/
3055 static int call_trans2findnotifyfirst(connection_struct *conn,
3056 char *inbuf, char *outbuf, int length, int bufsize,
3057 char **pparams, int total_params, char **ppdata, int total_data)
3059 static uint16 fnf_handle = 257;
3060 char *params = *pparams;
3061 uint16 info_level;
3063 if (total_params < 6)
3064 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3066 info_level = SVAL(params,4);
3067 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3069 switch (info_level) {
3070 case 1:
3071 case 2:
3072 break;
3073 default:
3074 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3077 /* Realloc the parameter and data sizes */
3078 params = Realloc(*pparams,6);
3079 if(params == NULL)
3080 return ERROR_DOS(ERRDOS,ERRnomem);
3081 *pparams = params;
3083 SSVAL(params,0,fnf_handle);
3084 SSVAL(params,2,0); /* No changes */
3085 SSVAL(params,4,0); /* No EA errors */
3087 fnf_handle++;
3089 if(fnf_handle == 0)
3090 fnf_handle = 257;
3092 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3094 return(-1);
3097 /****************************************************************************
3098 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3099 changes). Currently this does nothing.
3100 ****************************************************************************/
3102 static int call_trans2findnotifynext(connection_struct *conn,
3103 char *inbuf, char *outbuf, int length, int bufsize,
3104 char **pparams, int total_params, char **ppdata, int total_data)
3106 char *params = *pparams;
3108 DEBUG(3,("call_trans2findnotifynext\n"));
3110 /* Realloc the parameter and data sizes */
3111 params = Realloc(*pparams,4);
3112 if(params == NULL)
3113 return ERROR_DOS(ERRDOS,ERRnomem);
3114 *pparams = params;
3116 SSVAL(params,0,0); /* No changes */
3117 SSVAL(params,2,0); /* No EA errors */
3119 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3121 return(-1);
3124 /****************************************************************************
3125 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3126 ****************************************************************************/
3128 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3129 char* outbuf, int length, int bufsize,
3130 char **pparams, int total_params, char **ppdata, int total_data)
3132 char *params = *pparams;
3133 pstring pathname;
3134 int reply_size = 0;
3135 int max_referral_level;
3137 DEBUG(10,("call_trans2getdfsreferral\n"));
3139 if (total_params < 2)
3140 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3142 max_referral_level = SVAL(params,0);
3144 if(!lp_host_msdfs())
3145 return ERROR_DOS(ERRDOS,ERRbadfunc);
3147 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
3149 if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
3150 return ERROR_DOS(ERRDOS,ERRbadfile);
3152 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3153 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3155 return(-1);
3158 #define LMCAT_SPL 0x53
3159 #define LMFUNC_GETJOBID 0x60
3161 /****************************************************************************
3162 Reply to a TRANS2_IOCTL - used for OS/2 printing.
3163 ****************************************************************************/
3165 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3166 char* outbuf, int length, int bufsize,
3167 char **pparams, int total_params, char **ppdata, int total_data)
3169 char *pdata = *ppdata;
3170 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3172 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3173 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3174 pdata = Realloc(*ppdata, 32);
3175 if(pdata == NULL)
3176 return ERROR_DOS(ERRDOS,ERRnomem);
3177 *ppdata = pdata;
3179 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3180 CAN ACCEPT THIS IN UNICODE. JRA. */
3182 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
3183 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3184 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3185 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3186 return(-1);
3187 } else {
3188 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3189 return ERROR_DOS(ERRSRV,ERRerror);
3193 /****************************************************************************
3194 Reply to a SMBfindclose (stop trans2 directory search).
3195 ****************************************************************************/
3197 int reply_findclose(connection_struct *conn,
3198 char *inbuf,char *outbuf,int length,int bufsize)
3200 int outsize = 0;
3201 int dptr_num=SVALS(inbuf,smb_vwv0);
3202 START_PROFILE(SMBfindclose);
3204 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3206 dptr_close(&dptr_num);
3208 outsize = set_message(outbuf,0,0,True);
3210 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3212 END_PROFILE(SMBfindclose);
3213 return(outsize);
3216 /****************************************************************************
3217 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3218 ****************************************************************************/
3220 int reply_findnclose(connection_struct *conn,
3221 char *inbuf,char *outbuf,int length,int bufsize)
3223 int outsize = 0;
3224 int dptr_num= -1;
3225 START_PROFILE(SMBfindnclose);
3227 dptr_num = SVAL(inbuf,smb_vwv0);
3229 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3231 /* We never give out valid handles for a
3232 findnotifyfirst - so any dptr_num is ok here.
3233 Just ignore it. */
3235 outsize = set_message(outbuf,0,0,True);
3237 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3239 END_PROFILE(SMBfindnclose);
3240 return(outsize);
3243 /****************************************************************************
3244 Reply to a SMBtranss2 - just ignore it!
3245 ****************************************************************************/
3247 int reply_transs2(connection_struct *conn,
3248 char *inbuf,char *outbuf,int length,int bufsize)
3250 START_PROFILE(SMBtranss2);
3251 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3252 END_PROFILE(SMBtranss2);
3253 return(-1);
3256 /****************************************************************************
3257 Reply to a SMBtrans2.
3258 ****************************************************************************/
3260 int reply_trans2(connection_struct *conn,
3261 char *inbuf,char *outbuf,int length,int bufsize)
3263 int outsize = 0;
3264 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3265 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3266 #if 0
3267 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3268 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3269 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3270 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3271 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3272 int32 timeout = IVALS(inbuf,smb_timeout);
3273 #endif
3274 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3275 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3276 char *params = NULL, *data = NULL;
3277 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
3278 START_PROFILE(SMBtrans2);
3280 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3281 /* Queue this open message as we are the process of an
3282 * oplock break. */
3284 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3285 DEBUGADD(2,( "in oplock break state.\n"));
3287 push_oplock_pending_smb_message(inbuf, length);
3288 END_PROFILE(SMBtrans2);
3289 return -1;
3292 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3293 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3294 END_PROFILE(SMBtrans2);
3295 return ERROR_DOS(ERRSRV,ERRaccess);
3298 outsize = set_message(outbuf,0,0,True);
3300 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3301 is so as a sanity check */
3302 if (suwcnt != 1) {
3304 * Need to have rc=0 for ioctl to get job id for OS/2.
3305 * Network printing will fail if function is not successful.
3306 * Similar function in reply.c will be used if protocol
3307 * is LANMAN1.0 instead of LM1.2X002.
3308 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3309 * outbuf doesn't have to be set(only job id is used).
3311 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3312 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3313 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3314 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3315 } else {
3316 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
3317 DEBUG(2,("Transaction is %d\n",tran_call));
3318 END_PROFILE(SMBtrans2);
3319 ERROR_DOS(ERRDOS,ERRinvalidparam);
3323 /* Allocate the space for the maximum needed parameters and data */
3324 if (total_params > 0)
3325 params = (char *)malloc(total_params);
3326 if (total_data > 0)
3327 data = (char *)malloc(total_data);
3329 if ((total_params && !params) || (total_data && !data)) {
3330 DEBUG(2,("Out of memory in reply_trans2\n"));
3331 SAFE_FREE(params);
3332 SAFE_FREE(data);
3333 END_PROFILE(SMBtrans2);
3334 return ERROR_DOS(ERRDOS,ERRnomem);
3337 /* Copy the param and data bytes sent with this request into
3338 the params buffer */
3339 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3340 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3342 if (num_params > total_params || num_data > total_data)
3343 exit_server("invalid params in reply_trans2");
3345 if(params) {
3346 unsigned int psoff = SVAL(inbuf, smb_psoff);
3347 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
3348 goto bad_param;
3349 if (smb_base(inbuf) + psoff + num_params > inbuf + length)
3350 goto bad_param;
3351 memcpy( params, smb_base(inbuf) + psoff, num_params);
3353 if(data) {
3354 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
3355 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
3356 goto bad_param;
3357 if (smb_base(inbuf) + dsoff + num_data > inbuf + length)
3358 goto bad_param;
3359 memcpy( data, smb_base(inbuf) + dsoff, num_data);
3362 if(num_data_sofar < total_data || num_params_sofar < total_params) {
3363 /* We need to send an interim response then receive the rest
3364 of the parameter/data bytes */
3365 outsize = set_message(outbuf,0,0,True);
3366 if (!send_smb(smbd_server_fd(),outbuf))
3367 exit_server("reply_trans2: send_smb failed.");
3369 while (num_data_sofar < total_data ||
3370 num_params_sofar < total_params) {
3371 BOOL ret;
3372 unsigned int param_disp;
3373 unsigned int param_off;
3374 unsigned int data_disp;
3375 unsigned int data_off;
3377 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3379 if ((ret &&
3380 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3381 outsize = set_message(outbuf,0,0,True);
3382 if(ret)
3383 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3384 else
3385 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3386 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3387 goto bad_param;
3390 /* Revise total_params and total_data in case
3391 they have changed downwards */
3392 if (SVAL(inbuf, smb_tpscnt) < total_params)
3393 total_params = SVAL(inbuf, smb_tpscnt);
3394 if (SVAL(inbuf, smb_tdscnt) < total_data)
3395 total_data = SVAL(inbuf, smb_tdscnt);
3397 num_params = SVAL(inbuf,smb_spscnt);
3398 param_off = SVAL(inbuf, smb_spsoff);
3399 param_disp = SVAL(inbuf, smb_spsdisp);
3400 num_params_sofar += num_params;
3402 num_data = SVAL(inbuf, smb_sdscnt);
3403 data_off = SVAL(inbuf, smb_sdsoff);
3404 data_disp = SVAL(inbuf, smb_sdsdisp);
3405 num_data_sofar += num_data;
3407 if (num_params_sofar > total_params || num_data_sofar > total_data)
3408 goto bad_param;
3410 if (num_params) {
3411 if (param_disp + num_params >= total_params)
3412 goto bad_param;
3413 if ((param_disp + num_params < param_disp) ||
3414 (param_disp + num_params < num_params))
3415 goto bad_param;
3416 if (smb_base(inbuf) + param_off + num_params >= inbuf + bufsize)
3417 goto bad_param;
3418 if (params + param_disp < params)
3419 goto bad_param;
3421 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
3423 if (num_data) {
3424 if (data_disp + num_data >= total_data)
3425 goto bad_param;
3426 if ((data_disp + num_data < data_disp) ||
3427 (data_disp + num_data < num_data))
3428 goto bad_param;
3429 if (smb_base(inbuf) + data_off + num_data >= inbuf + bufsize)
3430 goto bad_param;
3431 if (data + data_disp < data)
3432 goto bad_param;
3434 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
3439 if (Protocol >= PROTOCOL_NT1) {
3440 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
3443 /* Now we must call the relevant TRANS2 function */
3444 switch(tran_call) {
3445 case TRANSACT2_OPEN:
3446 START_PROFILE_NESTED(Trans2_open);
3447 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
3448 &params, total_params, &data, total_data);
3449 END_PROFILE_NESTED(Trans2_open);
3450 break;
3452 case TRANSACT2_FINDFIRST:
3453 START_PROFILE_NESTED(Trans2_findfirst);
3454 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3455 &params, total_params, &data, total_data);
3456 END_PROFILE_NESTED(Trans2_findfirst);
3457 break;
3459 case TRANSACT2_FINDNEXT:
3460 START_PROFILE_NESTED(Trans2_findnext);
3461 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
3462 &params, total_params, &data, total_data);
3463 END_PROFILE_NESTED(Trans2_findnext);
3464 break;
3466 case TRANSACT2_QFSINFO:
3467 START_PROFILE_NESTED(Trans2_qfsinfo);
3468 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3469 &params, total_params, &data, total_data);
3470 END_PROFILE_NESTED(Trans2_qfsinfo);
3471 break;
3473 #ifdef HAVE_SYS_QUOTAS
3474 case TRANSACT2_SETFSINFO:
3475 START_PROFILE_NESTED(Trans2_setfsinfo);
3476 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
3477 &params, total_params, &data, total_data);
3478 END_PROFILE_NESTED(Trans2_setfsinfo);
3479 break;
3480 #endif
3481 case TRANSACT2_QPATHINFO:
3482 case TRANSACT2_QFILEINFO:
3483 START_PROFILE_NESTED(Trans2_qpathinfo);
3484 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3485 &params, total_params, &data, total_data);
3486 END_PROFILE_NESTED(Trans2_qpathinfo);
3487 break;
3488 case TRANSACT2_SETPATHINFO:
3489 case TRANSACT2_SETFILEINFO:
3490 START_PROFILE_NESTED(Trans2_setpathinfo);
3491 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3492 &params, total_params, &data, total_data);
3493 END_PROFILE_NESTED(Trans2_setpathinfo);
3494 break;
3496 case TRANSACT2_FINDNOTIFYFIRST:
3497 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3498 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
3499 &params, total_params, &data, total_data);
3500 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3501 break;
3503 case TRANSACT2_FINDNOTIFYNEXT:
3504 START_PROFILE_NESTED(Trans2_findnotifynext);
3505 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
3506 &params, total_params, &data, total_data);
3507 END_PROFILE_NESTED(Trans2_findnotifynext);
3508 break;
3509 case TRANSACT2_MKDIR:
3510 START_PROFILE_NESTED(Trans2_mkdir);
3511 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3512 &params, total_params, &data, total_data);
3513 END_PROFILE_NESTED(Trans2_mkdir);
3514 break;
3516 case TRANSACT2_GET_DFS_REFERRAL:
3517 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3518 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3519 &params, total_params, &data, total_data);
3520 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3521 break;
3522 case TRANSACT2_IOCTL:
3523 START_PROFILE_NESTED(Trans2_ioctl);
3524 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3525 &params, total_params, &data, total_data);
3526 END_PROFILE_NESTED(Trans2_ioctl);
3527 break;
3528 default:
3529 /* Error in request */
3530 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3531 SAFE_FREE(params);
3532 SAFE_FREE(data);
3533 END_PROFILE(SMBtrans2);
3534 return ERROR_DOS(ERRSRV,ERRerror);
3537 /* As we do not know how many data packets will need to be
3538 returned here the various call_trans2xxxx calls
3539 must send their own. Thus a call_trans2xxx routine only
3540 returns a value other than -1 when it wants to send
3541 an error packet.
3544 SAFE_FREE(params);
3545 SAFE_FREE(data);
3546 END_PROFILE(SMBtrans2);
3547 return outsize; /* If a correct response was needed the
3548 call_trans2xxx calls have already sent
3549 it. If outsize != -1 then it is returning */
3551 bad_param:
3553 SAFE_FREE(params);
3554 SAFE_FREE(data);
3555 END_PROFILE(SMBtrans2);
3556 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);