Setting EA's to zero length deletes them.
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blob9f5ef09454ad8dbfd324940b4c68498e20c96544
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2003
5 Copyright (C) Stefan (metze) Metzmacher 2003
7 Extensively modified by Andrew Tridgell, 1995
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 extern int Protocol;
27 extern BOOL case_sensitive;
28 extern int smb_read_error;
29 extern fstring local_machine;
30 extern int global_oplock_break;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
34 #define get_file_size(sbuf) ((sbuf).st_size)
36 /* given a stat buffer return the allocated size on disk, taking into
37 account sparse files */
38 SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
40 SMB_BIG_UINT ret;
41 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
42 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
43 #else
44 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
45 #endif
46 if (!ret && fsp && fsp->initial_allocation_size)
47 ret = fsp->initial_allocation_size;
48 ret = SMB_ROUNDUP(ret,SMB_ROUNDUP_ALLOCATION_SIZE);
49 return ret;
52 /****************************************************************************
53 Utility functions for dealing with extended attributes.
54 ****************************************************************************/
56 struct ea_list {
57 struct ea_list *next, *prev;
58 struct ea_struct ea;
61 static
62 /****************************************************************************
63 Send the required number of replies back.
64 We assume all fields other than the data fields are
65 set correctly for the type of call.
66 HACK ! Always assumes smb_setup field is zero.
67 ****************************************************************************/
69 static int send_trans2_replies(char *outbuf,
70 int bufsize,
71 char *params,
72 int paramsize,
73 char *pdata,
74 int datasize)
76 /* As we are using a protocol > LANMAN1 then the max_send
77 variable must have been set in the sessetupX call.
78 This takes precedence over the max_xmit field in the
79 global struct. These different max_xmit variables should
80 be merged as this is now too confusing */
82 extern int max_send;
83 int data_to_send = datasize;
84 int params_to_send = paramsize;
85 int useable_space;
86 char *pp = params;
87 char *pd = pdata;
88 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
89 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
90 int data_alignment_offset = 0;
92 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
94 set_message(outbuf,10,0,True);
96 /* If there genuinely are no parameters or data to send just send the empty packet */
98 if(params_to_send == 0 && data_to_send == 0) {
99 if (!send_smb(smbd_server_fd(),outbuf))
100 exit_server("send_trans2_replies: send_smb failed.");
101 return 0;
104 /* When sending params and data ensure that both are nicely aligned */
105 /* Only do this alignment when there is also data to send - else
106 can cause NT redirector problems. */
108 if (((params_to_send % 4) != 0) && (data_to_send != 0))
109 data_alignment_offset = 4 - (params_to_send % 4);
111 /* Space is bufsize minus Netbios over TCP header minus SMB header */
112 /* The alignment_offset is to align the param bytes on an even byte
113 boundary. NT 4.0 Beta needs this to work correctly. */
115 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
117 /* useable_space can never be more than max_send minus the alignment offset. */
119 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
121 while (params_to_send || data_to_send) {
122 /* Calculate whether we will totally or partially fill this packet */
124 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
126 /* We can never send more than useable_space */
128 * Note that 'useable_space' does not include the alignment offsets,
129 * but we must include the alignment offsets in the calculation of
130 * the length of the data we send over the wire, as the alignment offsets
131 * are sent here. Fix from Marc_Jacobsen@hp.com.
134 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
136 set_message(outbuf, 10, total_sent_thistime, True);
138 /* Set total params and data to be sent */
139 SSVAL(outbuf,smb_tprcnt,paramsize);
140 SSVAL(outbuf,smb_tdrcnt,datasize);
142 /* Calculate how many parameters and data we can fit into
143 * this packet. Parameters get precedence
146 params_sent_thistime = MIN(params_to_send,useable_space);
147 data_sent_thistime = useable_space - params_sent_thistime;
148 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
150 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
152 /* smb_proff is the offset from the start of the SMB header to the
153 parameter bytes, however the first 4 bytes of outbuf are
154 the Netbios over TCP header. Thus use smb_base() to subtract
155 them from the calculation */
157 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
159 if(params_sent_thistime == 0)
160 SSVAL(outbuf,smb_prdisp,0);
161 else
162 /* Absolute displacement of param bytes sent in this packet */
163 SSVAL(outbuf,smb_prdisp,pp - params);
165 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
166 if(data_sent_thistime == 0) {
167 SSVAL(outbuf,smb_droff,0);
168 SSVAL(outbuf,smb_drdisp, 0);
169 } else {
170 /* The offset of the data bytes is the offset of the
171 parameter bytes plus the number of parameters being sent this time */
172 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
173 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
174 SSVAL(outbuf,smb_drdisp, pd - pdata);
177 /* Copy the param bytes into the packet */
179 if(params_sent_thistime)
180 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
182 /* Copy in the data bytes */
183 if(data_sent_thistime)
184 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
185 data_alignment_offset,pd,data_sent_thistime);
187 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
188 params_sent_thistime, data_sent_thistime, useable_space));
189 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
190 params_to_send, data_to_send, paramsize, datasize));
192 /* Send the packet */
193 if (!send_smb(smbd_server_fd(),outbuf))
194 exit_server("send_trans2_replies: send_smb failed.");
196 pp += params_sent_thistime;
197 pd += data_sent_thistime;
199 params_to_send -= params_sent_thistime;
200 data_to_send -= data_sent_thistime;
202 /* Sanity check */
203 if(params_to_send < 0 || data_to_send < 0) {
204 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
205 params_to_send, data_to_send));
206 return -1;
210 return 0;
213 /****************************************************************************
214 Reply to a TRANSACT2_OPEN.
215 ****************************************************************************/
217 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
218 char **pparams, int total_params, char **ppdata, int total_data)
220 char *params = *pparams;
221 int16 open_mode;
222 int16 open_attr;
223 BOOL oplock_request;
224 #if 0
225 BOOL return_additional_info;
226 int16 open_sattr;
227 time_t open_time;
228 #endif
229 int16 open_ofun;
230 int32 open_size;
231 char *pname;
232 pstring fname;
233 mode_t unixmode;
234 SMB_OFF_T size=0;
235 int fmode=0,mtime=0,rmode;
236 SMB_INO_T inode = 0;
237 SMB_STRUCT_STAT sbuf;
238 int smb_action = 0;
239 BOOL bad_path = False;
240 files_struct *fsp;
241 NTSTATUS status;
244 * Ensure we have enough parameters to perform the operation.
247 if (total_params < 29)
248 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
250 open_mode = SVAL(params, 2);
251 open_attr = SVAL(params,6);
252 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
253 #if 0
254 return_additional_info = BITSETW(params,0);
255 open_sattr = SVAL(params, 4);
256 open_time = make_unix_date3(params+8);
257 #endif
258 open_ofun = SVAL(params,12);
259 open_size = IVAL(params,14);
260 pname = &params[28];
262 if (IS_IPC(conn))
263 return(ERROR_DOS(ERRSRV,ERRaccess));
265 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);
266 if (!NT_STATUS_IS_OK(status)) {
267 return ERROR_NT(status);
270 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
271 fname,open_mode, open_attr, open_ofun, open_size));
273 /* XXXX we need to handle passed times, sattr and flags */
275 unix_convert(fname,conn,0,&bad_path,&sbuf);
277 if (!check_name(fname,conn)) {
278 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
281 unixmode = unix_mode(conn,open_attr | aARCH, fname);
283 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode,
284 oplock_request, &rmode,&smb_action);
286 if (!fsp) {
287 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
290 size = get_file_size(sbuf);
291 fmode = dos_mode(conn,fname,&sbuf);
292 mtime = sbuf.st_mtime;
293 inode = sbuf.st_ino;
294 if (fmode & aDIR) {
295 close_file(fsp,False);
296 return(ERROR_DOS(ERRDOS,ERRnoaccess));
299 /* Realloc the size of parameters and data we will return */
300 params = Realloc(*pparams, 28);
301 if( params == NULL )
302 return(ERROR_DOS(ERRDOS,ERRnomem));
303 *pparams = params;
305 memset((char *)params,'\0',28);
306 SSVAL(params,0,fsp->fnum);
307 SSVAL(params,2,fmode);
308 put_dos_date2(params,4, mtime);
309 SIVAL(params,8, (uint32)size);
310 SSVAL(params,12,rmode);
312 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
313 smb_action |= EXTENDED_OPLOCK_GRANTED;
315 SSVAL(params,18,smb_action);
318 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
320 SIVAL(params,20,inode);
322 /* Send the required number of replies */
323 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
325 return -1;
328 /*********************************************************
329 Routine to check if a given string matches exactly.
330 as a special case a mask of "." does NOT match. That
331 is required for correct wildcard semantics
332 Case can be significant or not.
333 **********************************************************/
335 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
337 if (mask[0] == '.' && mask[1] == 0)
338 return False;
339 if (case_sig)
340 return strcmp(str,mask)==0;
341 if (StrCaseCmp(str,mask) != 0) {
342 return False;
344 if (ms_has_wild(str)) {
345 return False;
347 return True;
350 /****************************************************************************
351 Return the filetype for UNIX extensions.
352 ****************************************************************************/
354 static uint32 unix_filetype(mode_t mode)
356 if(S_ISREG(mode))
357 return UNIX_TYPE_FILE;
358 else if(S_ISDIR(mode))
359 return UNIX_TYPE_DIR;
360 #ifdef S_ISLNK
361 else if(S_ISLNK(mode))
362 return UNIX_TYPE_SYMLINK;
363 #endif
364 #ifdef S_ISCHR
365 else if(S_ISCHR(mode))
366 return UNIX_TYPE_CHARDEV;
367 #endif
368 #ifdef S_ISBLK
369 else if(S_ISBLK(mode))
370 return UNIX_TYPE_BLKDEV;
371 #endif
372 #ifdef S_ISFIFO
373 else if(S_ISFIFO(mode))
374 return UNIX_TYPE_FIFO;
375 #endif
376 #ifdef S_ISSOCK
377 else if(S_ISSOCK(mode))
378 return UNIX_TYPE_SOCKET;
379 #endif
381 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
382 return UNIX_TYPE_UNKNOWN;
385 /****************************************************************************
386 Return the major devicenumber for UNIX extensions.
387 ****************************************************************************/
389 static uint32 unix_dev_major(SMB_DEV_T dev)
391 #if defined(HAVE_DEVICE_MAJOR_FN)
392 return (uint32)major(dev);
393 #else
394 return (uint32)(dev >> 8);
395 #endif
398 /****************************************************************************
399 Return the minor devicenumber for UNIX extensions.
400 ****************************************************************************/
402 static uint32 unix_dev_minor(SMB_DEV_T dev)
404 #if defined(HAVE_DEVICE_MINOR_FN)
405 return (uint32)minor(dev);
406 #else
407 return (uint32)(dev & 0xff);
408 #endif
411 /****************************************************************************
412 Map wire perms onto standard UNIX permissions. Obey share restrictions.
413 ****************************************************************************/
415 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
417 mode_t ret = 0;
419 if (perms == SMB_MODE_NO_CHANGE)
420 return pst->st_mode;
422 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
423 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
424 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
425 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
426 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
427 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
428 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
429 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
430 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
431 #ifdef S_ISVTX
432 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
433 #endif
434 #ifdef S_ISGID
435 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
436 #endif
437 #ifdef S_ISUID
438 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
439 #endif
441 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
442 ret &= lp_dir_mask(SNUM(conn));
443 /* Add in force bits */
444 ret |= lp_force_dir_mode(SNUM(conn));
445 } else {
446 /* Apply mode mask */
447 ret &= lp_create_mask(SNUM(conn));
448 /* Add in force bits */
449 ret |= lp_force_create_mode(SNUM(conn));
452 return ret;
455 /****************************************************************************
456 Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
457 ****************************************************************************/
459 time_t interpret_long_unix_date(char *p)
461 DEBUG(1,("interpret_long_unix_date\n"));
462 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
463 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
464 return -1;
465 } else {
466 return interpret_long_date(p);
470 /****************************************************************************
471 Get a level dependent lanman2 dir entry.
472 ****************************************************************************/
474 static BOOL get_lanman2_dir_entry(connection_struct *conn,
475 void *inbuf, void *outbuf,
476 char *path_mask,int dirtype,int info_level,
477 int requires_resume_key,
478 BOOL dont_descend,char **ppdata,
479 char *base_data, int space_remaining,
480 BOOL *out_of_space, BOOL *got_exact_match,
481 int *last_name_off)
483 const char *dname;
484 BOOL found = False;
485 SMB_STRUCT_STAT sbuf;
486 pstring mask;
487 pstring pathreal;
488 pstring fname;
489 char *p, *q, *pdata = *ppdata;
490 uint32 reskey=0;
491 int prev_dirpos=0;
492 int mode=0;
493 SMB_OFF_T file_size = 0;
494 SMB_BIG_UINT allocation_size = 0;
495 uint32 len;
496 time_t mdate=0, adate=0, cdate=0;
497 char *nameptr;
498 BOOL was_8_3;
499 int nt_extmode; /* Used for NT connections instead of mode */
500 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
502 *fname = 0;
503 *out_of_space = False;
504 *got_exact_match = False;
506 if (!conn->dirptr)
507 return(False);
509 p = strrchr_m(path_mask,'/');
510 if(p != NULL) {
511 if(p[1] == '\0')
512 pstrcpy(mask,"*.*");
513 else
514 pstrcpy(mask, p+1);
515 } else
516 pstrcpy(mask, path_mask);
518 while (!found) {
519 BOOL got_match;
521 /* Needed if we run out of space */
522 prev_dirpos = TellDir(conn->dirptr);
523 dname = ReadDirName(conn->dirptr);
526 * Due to bugs in NT client redirectors we are not using
527 * resume keys any more - set them to zero.
528 * Check out the related comments in findfirst/findnext.
529 * JRA.
532 reskey = 0;
534 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
535 (long)conn->dirptr,TellDir(conn->dirptr)));
537 if (!dname)
538 return(False);
540 pstrcpy(fname,dname);
542 if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
543 got_match = mask_match(fname, mask, case_sensitive);
545 if(!got_match && !mangle_is_8_3(fname, False)) {
548 * It turns out that NT matches wildcards against
549 * both long *and* short names. This may explain some
550 * of the wildcard wierdness from old DOS clients
551 * that some people have been seeing.... JRA.
554 pstring newname;
555 pstrcpy( newname, fname);
556 mangle_map( newname, True, False, SNUM(conn));
557 if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
558 got_match = mask_match(newname, mask, case_sensitive);
561 if(got_match) {
562 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
563 if (dont_descend && !isdots)
564 continue;
566 pstrcpy(pathreal,conn->dirpath);
567 if(needslash)
568 pstrcat(pathreal,"/");
569 pstrcat(pathreal,dname);
571 if (INFO_LEVEL_IS_UNIX(info_level)) {
572 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
573 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
574 pathreal,strerror(errno)));
575 continue;
577 } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
579 /* Needed to show the msdfs symlinks as
580 * directories */
582 if(lp_host_msdfs() &&
583 lp_msdfs_root(SNUM(conn)) &&
584 is_msdfs_link(conn, pathreal, NULL, NULL,
585 &sbuf)) {
587 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
588 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
590 } else {
592 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
593 pathreal,strerror(errno)));
594 continue;
598 mode = dos_mode(conn,pathreal,&sbuf);
600 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
601 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
602 continue;
605 file_size = get_file_size(sbuf);
606 allocation_size = get_allocation_size(NULL,&sbuf);
607 mdate = sbuf.st_mtime;
608 adate = sbuf.st_atime;
609 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
611 if (lp_dos_filetime_resolution(SNUM(conn))) {
612 cdate &= ~1;
613 mdate &= ~1;
614 adate &= ~1;
617 if(mode & aDIR)
618 file_size = 0;
620 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
622 found = True;
626 mangle_map(fname,False,True,SNUM(conn));
628 p = pdata;
629 nameptr = p;
631 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
633 switch (info_level) {
634 case SMB_INFO_STANDARD:
635 if(requires_resume_key) {
636 SIVAL(p,0,reskey);
637 p += 4;
639 put_dos_date2(p,l1_fdateCreation,cdate);
640 put_dos_date2(p,l1_fdateLastAccess,adate);
641 put_dos_date2(p,l1_fdateLastWrite,mdate);
642 SIVAL(p,l1_cbFile,(uint32)file_size);
643 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
644 SSVAL(p,l1_attrFile,mode);
645 p += l1_achName;
646 nameptr = p;
647 p += align_string(outbuf, p, 0);
648 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
649 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS)
650 SCVAL(nameptr, -1, len-2);
651 else
652 SCVAL(nameptr, -1, len-1);
653 p += len;
654 break;
656 case SMB_INFO_QUERY_EA_SIZE:
657 if(requires_resume_key) {
658 SIVAL(p,0,reskey);
659 p += 4;
661 put_dos_date2(p,l2_fdateCreation,cdate);
662 put_dos_date2(p,l2_fdateLastAccess,adate);
663 put_dos_date2(p,l2_fdateLastWrite,mdate);
664 SIVAL(p,l2_cbFile,(uint32)file_size);
665 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
666 SSVAL(p,l2_attrFile,mode);
667 SIVAL(p,l2_cbList,0); /* No extended attributes */
668 p += l2_achName;
669 nameptr = p;
670 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
671 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS)
672 SCVAL(nameptr, -1, len-2);
673 else
674 SCVAL(nameptr, -1, len-1);
675 p += len;
676 break;
678 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
679 was_8_3 = mangle_is_8_3(fname, True);
680 p += 4;
681 SIVAL(p,0,reskey); p += 4;
682 put_long_date(p,cdate); p += 8;
683 put_long_date(p,adate); p += 8;
684 put_long_date(p,mdate); p += 8;
685 put_long_date(p,mdate); p += 8;
686 SOFF_T(p,0,file_size);
687 SOFF_T(p,8,allocation_size);
688 p += 16;
689 SIVAL(p,0,nt_extmode); p += 4;
690 q = p; p += 4;
691 SIVAL(p,0,0); p += 4;
692 /* Clear the short name buffer. This is
693 * IMPORTANT as not doing so will trigger
694 * a Win2k client bug. JRA.
696 memset(p,'\0',26);
697 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
698 pstring mangled_name;
699 pstrcpy(mangled_name, fname);
700 mangle_map(mangled_name,True,True,SNUM(conn));
701 mangled_name[12] = 0;
702 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
703 SSVAL(p, 0, len);
704 } else {
705 SSVAL(p,0,0);
706 *(p+2) = 0;
708 p += 2 + 24;
709 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
710 SIVAL(q,0,len);
711 p += len;
712 len = PTR_DIFF(p, pdata);
713 len = (len + 3) & ~3;
714 SIVAL(pdata,0,len);
715 p = pdata + len;
716 break;
718 case SMB_FIND_FILE_DIRECTORY_INFO:
719 p += 4;
720 SIVAL(p,0,reskey); p += 4;
721 put_long_date(p,cdate); p += 8;
722 put_long_date(p,adate); p += 8;
723 put_long_date(p,mdate); p += 8;
724 put_long_date(p,mdate); p += 8;
725 SOFF_T(p,0,file_size);
726 SOFF_T(p,8,allocation_size);
727 p += 16;
728 SIVAL(p,0,nt_extmode); p += 4;
729 p += 4;
730 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
731 SIVAL(p, -4, len);
732 p += len;
733 len = PTR_DIFF(p, pdata);
734 len = (len + 3) & ~3;
735 SIVAL(pdata,0,len);
736 p = pdata + len;
737 break;
739 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
740 p += 4;
741 SIVAL(p,0,reskey); p += 4;
742 put_long_date(p,cdate); p += 8;
743 put_long_date(p,adate); p += 8;
744 put_long_date(p,mdate); p += 8;
745 put_long_date(p,mdate); p += 8;
746 SOFF_T(p,0,file_size);
747 SOFF_T(p,8,allocation_size);
748 p += 16;
749 SIVAL(p,0,nt_extmode);
750 p += 4;
752 SIVAL(p,4,0); /* ea size */
753 len = srvstr_push(outbuf, p+8, fname, -1, STR_TERMINATE_ASCII);
754 SIVAL(p, 0, len);
755 p += 8 + len;
757 len = PTR_DIFF(p, pdata);
758 len = (len + 3) & ~3;
759 SIVAL(pdata,0,len);
760 p = pdata + len;
761 break;
763 case SMB_FIND_FILE_NAMES_INFO:
764 p += 4;
765 SIVAL(p,0,reskey); p += 4;
766 p += 4;
767 /* this must *not* be null terminated or w2k gets in a loop trying to set an
768 acl on a dir (tridge) */
769 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
770 SIVAL(p, -4, len);
771 p += len;
772 len = PTR_DIFF(p, pdata);
773 len = (len + 3) & ~3;
774 SIVAL(pdata,0,len);
775 p = pdata + len;
776 break;
778 case SMB_FIND_FILE_LEVEL_261:
779 p += 4;
780 SIVAL(p,0,reskey); p += 4;
781 put_long_date(p,cdate); p += 8;
782 put_long_date(p,adate); p += 8;
783 put_long_date(p,mdate); p += 8;
784 put_long_date(p,mdate); p += 8;
785 SOFF_T(p,0,file_size);
786 SOFF_T(p,8,allocation_size);
787 p += 16;
788 SIVAL(p,0,nt_extmode);
789 p += 4;
790 len = srvstr_push(outbuf, p + 20, fname, -1, STR_TERMINATE_ASCII);
791 SIVAL(p, 0, len);
792 memset(p+4,'\0',16); /* EA size. Unknown 0 1 2 */
793 p += 20 + len; /* Strlen, EA size. Unknown 0 1 2, string itself */
794 len = PTR_DIFF(p, pdata);
795 len = (len + 3) & ~3;
796 SIVAL(pdata,0,len);
797 p = pdata + len;
798 break;
800 case SMB_FIND_FILE_LEVEL_262:
801 was_8_3 = mangle_is_8_3(fname, True);
802 p += 4;
803 SIVAL(p,0,reskey); p += 4;
804 put_long_date(p,cdate); p += 8;
805 put_long_date(p,adate); p += 8;
806 put_long_date(p,mdate); p += 8;
807 put_long_date(p,mdate); p += 8;
808 SOFF_T(p,0,file_size);
809 SOFF_T(p,8,allocation_size);
810 p += 16;
811 SIVAL(p,0,nt_extmode); p += 4;
812 q = p; p += 4;
813 SIVAL(p,0,0); p += 4;
814 /* Clear the short name buffer. This is
815 * IMPORTANT as not doing so will trigger
816 * a Win2k client bug. JRA.
818 memset(p,'\0',26);
819 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
820 pstring mangled_name;
821 pstrcpy(mangled_name, fname);
822 mangle_map(mangled_name,True,True,SNUM(conn));
823 mangled_name[12] = 0;
824 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
825 SSVAL(p, 0, len);
826 } else {
827 SSVAL(p,0,0);
828 *(p+2) = 0;
830 p += 2 + 24;
831 memset(p, '\0', 10); /* 2 4 byte unknowns plus a zero reserved. */
832 p += 10;
833 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
834 SIVAL(q,0,len);
835 p += len;
836 len = PTR_DIFF(p, pdata);
837 len = (len + 3) & ~3;
838 SIVAL(pdata,0,len);
839 p = pdata + len;
840 break;
842 /* CIFS UNIX Extension. */
844 case SMB_FIND_FILE_UNIX:
845 p+= 4;
846 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
848 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
849 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
850 p+= 8;
852 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
853 p+= 8;
855 put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */
856 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
857 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
858 p+= 24;
860 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
861 SIVAL(p,4,0);
862 p+= 8;
864 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
865 SIVAL(p,4,0);
866 p+= 8;
868 SIVAL(p,0,unix_filetype(sbuf.st_mode));
869 p+= 4;
871 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
872 SIVAL(p,4,0);
873 p+= 8;
875 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
876 SIVAL(p,4,0);
877 p+= 8;
879 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
880 p+= 8;
882 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
883 SIVAL(p,4,0);
884 p+= 8;
886 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
887 SIVAL(p,4,0);
888 p+= 8;
890 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
891 p += len;
893 len = PTR_DIFF(p, pdata);
894 len = (len + 3) & ~3;
895 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
896 p = pdata + len;
897 /* End of SMB_QUERY_FILE_UNIX_BASIC */
899 break;
901 default:
902 return(False);
906 if (PTR_DIFF(p,pdata) > space_remaining) {
907 /* Move the dirptr back to prev_dirpos */
908 SeekDir(conn->dirptr, prev_dirpos);
909 *out_of_space = True;
910 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
911 return False; /* Not finished - just out of space */
914 /* Setup the last_filename pointer, as an offset from base_data */
915 *last_name_off = PTR_DIFF(nameptr,base_data);
916 /* Advance the data pointer to the next slot */
917 *ppdata = p;
919 return(found);
922 /****************************************************************************
923 Reply to a TRANS2_FINDFIRST.
924 ****************************************************************************/
926 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
927 char **pparams, int total_params, char **ppdata, int total_data)
929 /* We must be careful here that we don't return more than the
930 allowed number of data bytes. If this means returning fewer than
931 maxentries then so be it. We assume that the redirector has
932 enough room for the fixed number of parameter bytes it has
933 requested. */
934 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
935 char *params = *pparams;
936 char *pdata = *ppdata;
937 int dirtype = SVAL(params,0);
938 int maxentries = SVAL(params,2);
939 BOOL close_after_first = BITSETW(params+4,0);
940 BOOL close_if_end = BITSETW(params+4,1);
941 BOOL requires_resume_key = BITSETW(params+4,2);
942 int info_level = SVAL(params,6);
943 pstring directory;
944 pstring mask;
945 char *p, *wcard;
946 int last_name_off=0;
947 int dptr_num = -1;
948 int numentries = 0;
949 int i;
950 BOOL finished = False;
951 BOOL dont_descend = False;
952 BOOL out_of_space = False;
953 int space_remaining;
954 BOOL bad_path = False;
955 SMB_STRUCT_STAT sbuf;
956 NTSTATUS ntstatus = NT_STATUS_OK;
958 if (total_params < 12)
959 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
961 *directory = *mask = 0;
963 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
964 close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
965 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
966 info_level, max_data_bytes));
968 switch (info_level) {
969 case SMB_INFO_STANDARD:
970 case SMB_INFO_QUERY_EA_SIZE:
971 case SMB_FIND_FILE_DIRECTORY_INFO:
972 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
973 case SMB_FIND_FILE_NAMES_INFO:
974 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
975 case SMB_FIND_FILE_LEVEL_261:
976 case SMB_FIND_FILE_LEVEL_262:
977 break;
978 case SMB_FIND_FILE_UNIX:
979 if (!lp_unix_extensions())
980 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
981 break;
982 default:
983 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
986 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus);
987 if (!NT_STATUS_IS_OK(ntstatus)) {
988 return ERROR_NT(ntstatus);
991 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
993 unix_convert(directory,conn,0,&bad_path,&sbuf);
994 if(!check_name(directory,conn)) {
995 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
998 p = strrchr_m(directory,'/');
999 if(p == NULL) {
1000 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1001 if((directory[0] == '.') && (directory[1] == '\0'))
1002 pstrcpy(mask,"*");
1003 else
1004 pstrcpy(mask,directory);
1005 pstrcpy(directory,"./");
1006 } else {
1007 pstrcpy(mask,p+1);
1008 *p = 0;
1011 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1013 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1014 if( pdata == NULL )
1015 return(ERROR_DOS(ERRDOS,ERRnomem));
1017 *ppdata = pdata;
1018 memset((char *)pdata,'\0',max_data_bytes + 1024);
1020 /* Realloc the params space */
1021 params = Realloc(*pparams, 10);
1022 if (params == NULL)
1023 return ERROR_DOS(ERRDOS,ERRnomem);
1024 *pparams = params;
1026 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1027 if (dptr_num < 0)
1028 return(UNIXERROR(ERRDOS,ERRbadfile));
1030 /* Save the wildcard match and attribs we are using on this directory -
1031 needed as lanman2 assumes these are being saved between calls */
1033 if(!(wcard = strdup(mask))) {
1034 dptr_close(&dptr_num);
1035 return ERROR_DOS(ERRDOS,ERRnomem);
1038 dptr_set_wcard(dptr_num, wcard);
1039 dptr_set_attr(dptr_num, dirtype);
1041 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
1043 /* We don't need to check for VOL here as this is returned by
1044 a different TRANS2 call. */
1046 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1047 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1048 dont_descend = True;
1050 p = pdata;
1051 space_remaining = max_data_bytes;
1052 out_of_space = False;
1054 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1055 BOOL got_exact_match = False;
1057 /* this is a heuristic to avoid seeking the dirptr except when
1058 absolutely necessary. It allows for a filename of about 40 chars */
1059 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1060 out_of_space = True;
1061 finished = False;
1062 } else {
1063 finished = !get_lanman2_dir_entry(conn,
1064 inbuf, outbuf,
1065 mask,dirtype,info_level,
1066 requires_resume_key,dont_descend,
1067 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1068 &last_name_off);
1071 if (finished && out_of_space)
1072 finished = False;
1074 if (!finished && !out_of_space)
1075 numentries++;
1078 * As an optimisation if we know we aren't looking
1079 * for a wildcard name (ie. the name matches the wildcard exactly)
1080 * then we can finish on any (first) match.
1081 * This speeds up large directory searches. JRA.
1084 if(got_exact_match)
1085 finished = True;
1087 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1090 /* Check if we can close the dirptr */
1091 if(close_after_first || (finished && close_if_end)) {
1092 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1093 dptr_close(&dptr_num);
1097 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1098 * from observation of NT.
1101 if(numentries == 0) {
1102 dptr_close(&dptr_num);
1103 return ERROR_DOS(ERRDOS,ERRbadfile);
1106 /* At this point pdata points to numentries directory entries. */
1108 /* Set up the return parameter block */
1109 SSVAL(params,0,dptr_num);
1110 SSVAL(params,2,numentries);
1111 SSVAL(params,4,finished);
1112 SSVAL(params,6,0); /* Never an EA error */
1113 SSVAL(params,8,last_name_off);
1115 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1117 if ((! *directory) && dptr_path(dptr_num))
1118 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1120 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1121 smb_fn_name(CVAL(inbuf,smb_com)),
1122 mask, directory, dirtype, numentries ) );
1125 * Force a name mangle here to ensure that the
1126 * mask as an 8.3 name is top of the mangled cache.
1127 * The reasons for this are subtle. Don't remove
1128 * this code unless you know what you are doing
1129 * (see PR#13758). JRA.
1132 if(!mangle_is_8_3_wildcards( mask, False))
1133 mangle_map(mask, True, True, SNUM(conn));
1135 return(-1);
1138 /****************************************************************************
1139 Reply to a TRANS2_FINDNEXT.
1140 ****************************************************************************/
1142 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1143 char **pparams, int total_params, char **ppdata, int total_data)
1145 /* We must be careful here that we don't return more than the
1146 allowed number of data bytes. If this means returning fewer than
1147 maxentries then so be it. We assume that the redirector has
1148 enough room for the fixed number of parameter bytes it has
1149 requested. */
1150 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1151 char *params = *pparams;
1152 char *pdata = *ppdata;
1153 int dptr_num = SVAL(params,0);
1154 int maxentries = SVAL(params,2);
1155 uint16 info_level = SVAL(params,4);
1156 uint32 resume_key = IVAL(params,6);
1157 BOOL close_after_request = BITSETW(params+10,0);
1158 BOOL close_if_end = BITSETW(params+10,1);
1159 BOOL requires_resume_key = BITSETW(params+10,2);
1160 BOOL continue_bit = BITSETW(params+10,3);
1161 pstring resume_name;
1162 pstring mask;
1163 pstring directory;
1164 char *p;
1165 uint16 dirtype;
1166 int numentries = 0;
1167 int i, last_name_off=0;
1168 BOOL finished = False;
1169 BOOL dont_descend = False;
1170 BOOL out_of_space = False;
1171 int space_remaining;
1172 NTSTATUS ntstatus = NT_STATUS_OK;
1174 if (total_params < 12)
1175 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1177 *mask = *directory = *resume_name = 0;
1179 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus);
1180 if (!NT_STATUS_IS_OK(ntstatus)) {
1181 return ERROR_NT(ntstatus);
1184 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1185 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1186 resume_key = %d resume name = %s continue=%d level = %d\n",
1187 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1188 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1190 switch (info_level) {
1191 case SMB_INFO_STANDARD:
1192 case SMB_INFO_QUERY_EA_SIZE:
1193 case SMB_FIND_FILE_DIRECTORY_INFO:
1194 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1195 case SMB_FIND_FILE_NAMES_INFO:
1196 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1197 break;
1198 case SMB_FIND_FILE_UNIX:
1199 if (!lp_unix_extensions())
1200 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1201 break;
1202 default:
1203 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1206 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1207 if(pdata == NULL)
1208 return ERROR_DOS(ERRDOS,ERRnomem);
1210 *ppdata = pdata;
1211 memset((char *)pdata,'\0',max_data_bytes + 1024);
1213 /* Realloc the params space */
1214 params = Realloc(*pparams, 6*SIZEOFWORD);
1215 if( params == NULL )
1216 return ERROR_DOS(ERRDOS,ERRnomem);
1218 *pparams = params;
1220 /* Check that the dptr is valid */
1221 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1222 return ERROR_DOS(ERRDOS,ERRnofiles);
1224 string_set(&conn->dirpath,dptr_path(dptr_num));
1226 /* Get the wildcard mask from the dptr */
1227 if((p = dptr_wcard(dptr_num))== NULL) {
1228 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1229 return ERROR_DOS(ERRDOS,ERRnofiles);
1232 pstrcpy(mask, p);
1233 pstrcpy(directory,conn->dirpath);
1235 /* Get the attr mask from the dptr */
1236 dirtype = dptr_attr(dptr_num);
1238 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1239 dptr_num, mask, dirtype,
1240 (long)conn->dirptr,
1241 TellDir(conn->dirptr)));
1243 /* We don't need to check for VOL here as this is returned by
1244 a different TRANS2 call. */
1246 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1247 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1248 dont_descend = True;
1250 p = pdata;
1251 space_remaining = max_data_bytes;
1252 out_of_space = False;
1255 * Seek to the correct position. We no longer use the resume key but
1256 * depend on the last file name instead.
1259 if(requires_resume_key && *resume_name && !continue_bit) {
1262 * Fix for NT redirector problem triggered by resume key indexes
1263 * changing between directory scans. We now return a resume key of 0
1264 * and instead look for the filename to continue from (also given
1265 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1266 * findfirst/findnext (as is usual) then the directory pointer
1267 * should already be at the correct place. Check this by scanning
1268 * backwards looking for an exact (ie. case sensitive) filename match.
1269 * If we get to the beginning of the directory and haven't found it then scan
1270 * forwards again looking for a match. JRA.
1273 int current_pos, start_pos;
1274 const char *dname = NULL;
1275 pstring dname_pstring;
1276 void *dirptr = conn->dirptr;
1277 start_pos = TellDir(dirptr);
1278 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1279 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1281 SeekDir(dirptr, current_pos);
1282 dname = ReadDirName(dirptr);
1283 if (dname) {
1285 * Remember, mangle_map is called by
1286 * get_lanman2_dir_entry(), so the resume name
1287 * could be mangled. Ensure we do the same
1288 * here.
1291 /* make sure we get a copy that mangle_map can modify */
1293 pstrcpy(dname_pstring, dname);
1294 mangle_map( dname_pstring, False, True, SNUM(conn));
1296 if(strcsequal( resume_name, dname_pstring)) {
1297 SeekDir(dirptr, current_pos+1);
1298 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1299 break;
1305 * Scan forward from start if not found going backwards.
1308 if(current_pos < 0) {
1309 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1310 SeekDir(dirptr, start_pos);
1311 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1314 * Remember, mangle_map is called by
1315 * get_lanman2_dir_entry(), so the resume name
1316 * could be mangled. Ensure we do the same
1317 * here.
1320 if(dname) {
1321 /* make sure we get a copy that mangle_map can modify */
1323 pstrcpy(dname_pstring, dname);
1324 mangle_map(dname_pstring, False, True, SNUM(conn));
1326 if(strcsequal( resume_name, dname_pstring)) {
1327 SeekDir(dirptr, current_pos+1);
1328 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1329 break;
1332 } /* end for */
1333 } /* end if current_pos */
1334 } /* end if requires_resume_key && !continue_bit */
1336 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1337 BOOL got_exact_match = False;
1339 /* this is a heuristic to avoid seeking the dirptr except when
1340 absolutely necessary. It allows for a filename of about 40 chars */
1341 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1342 out_of_space = True;
1343 finished = False;
1344 } else {
1345 finished = !get_lanman2_dir_entry(conn,
1346 inbuf, outbuf,
1347 mask,dirtype,info_level,
1348 requires_resume_key,dont_descend,
1349 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1350 &last_name_off);
1353 if (finished && out_of_space)
1354 finished = False;
1356 if (!finished && !out_of_space)
1357 numentries++;
1360 * As an optimisation if we know we aren't looking
1361 * for a wildcard name (ie. the name matches the wildcard exactly)
1362 * then we can finish on any (first) match.
1363 * This speeds up large directory searches. JRA.
1366 if(got_exact_match)
1367 finished = True;
1369 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1372 /* Check if we can close the dirptr */
1373 if(close_after_request || (finished && close_if_end)) {
1374 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1375 dptr_close(&dptr_num); /* This frees up the saved mask */
1378 /* Set up the return parameter block */
1379 SSVAL(params,0,numentries);
1380 SSVAL(params,2,finished);
1381 SSVAL(params,4,0); /* Never an EA error */
1382 SSVAL(params,6,last_name_off);
1384 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1386 if ((! *directory) && dptr_path(dptr_num))
1387 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1389 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1390 smb_fn_name(CVAL(inbuf,smb_com)),
1391 mask, directory, dirtype, numentries ) );
1393 return(-1);
1396 /****************************************************************************
1397 Reply to a TRANS2_QFSINFO (query filesystem info).
1398 ****************************************************************************/
1400 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1401 int length, int bufsize,
1402 char **pparams, int total_params, char **ppdata, int total_data)
1404 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1405 char *pdata = *ppdata;
1406 char *params = *pparams;
1407 uint16 info_level = SVAL(params,0);
1408 int data_len, len;
1409 SMB_STRUCT_STAT st;
1410 char *vname = volume_label(SNUM(conn));
1411 int snum = SNUM(conn);
1412 char *fstype = lp_fstype(SNUM(conn));
1413 int quota_flag = 0;
1415 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1417 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1418 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1419 return ERROR_DOS(ERRSRV,ERRinvdevice);
1422 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1423 if ( pdata == NULL )
1424 return ERROR_DOS(ERRDOS,ERRnomem);
1426 *ppdata = pdata;
1427 memset((char *)pdata,'\0',max_data_bytes + 1024);
1429 switch (info_level) {
1430 case SMB_INFO_ALLOCATION:
1432 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1433 data_len = 18;
1434 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1435 block_size = lp_block_size(snum);
1436 if (bsize < block_size) {
1437 SMB_BIG_UINT factor = block_size/bsize;
1438 bsize = block_size;
1439 dsize /= factor;
1440 dfree /= factor;
1442 if (bsize > block_size) {
1443 SMB_BIG_UINT factor = bsize/block_size;
1444 bsize = block_size;
1445 dsize *= factor;
1446 dfree *= factor;
1448 bytes_per_sector = 512;
1449 sectors_per_unit = bsize/bytes_per_sector;
1451 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1452 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1453 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1455 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1456 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1457 SIVAL(pdata,l1_cUnit,dsize);
1458 SIVAL(pdata,l1_cUnitAvail,dfree);
1459 SSVAL(pdata,l1_cbSector,bytes_per_sector);
1460 break;
1463 case SMB_INFO_VOLUME:
1464 /* Return volume name */
1466 * Add volume serial number - hash of a combination of
1467 * the called hostname and the service name.
1469 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1470 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1471 SCVAL(pdata,l2_vol_cch,len);
1472 data_len = l2_vol_szVolLabel + len;
1473 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1474 (unsigned)st.st_ctime, len, vname));
1475 break;
1477 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1478 case SMB_FS_ATTRIBUTE_INFORMATION:
1481 #if defined(HAVE_SYS_QUOTAS)
1482 quota_flag = FILE_VOLUME_QUOTAS;
1483 #endif
1485 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1486 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1487 quota_flag); /* FS ATTRIBUTES */
1489 SIVAL(pdata,4,255); /* Max filename component length */
1490 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1491 and will think we can't do long filenames */
1492 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1493 SIVAL(pdata,8,len);
1494 data_len = 12 + len;
1495 break;
1497 case SMB_QUERY_FS_LABEL_INFO:
1498 case SMB_FS_LABEL_INFORMATION:
1499 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1500 data_len = 4 + len;
1501 SIVAL(pdata,0,len);
1502 break;
1504 case SMB_QUERY_FS_VOLUME_INFO:
1505 case SMB_FS_VOLUME_INFORMATION:
1508 * Add volume serial number - hash of a combination of
1509 * the called hostname and the service name.
1511 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1512 (str_checksum(local_machine)<<16));
1514 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1515 SIVAL(pdata,12,len);
1516 data_len = 18+len;
1517 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1518 (int)strlen(vname),vname, lp_servicename(snum)));
1519 break;
1521 case SMB_QUERY_FS_SIZE_INFO:
1522 case SMB_FS_SIZE_INFORMATION:
1524 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1525 data_len = 24;
1526 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1527 block_size = lp_block_size(snum);
1528 if (bsize < block_size) {
1529 SMB_BIG_UINT factor = block_size/bsize;
1530 bsize = block_size;
1531 dsize /= factor;
1532 dfree /= factor;
1534 if (bsize > block_size) {
1535 SMB_BIG_UINT factor = bsize/block_size;
1536 bsize = block_size;
1537 dsize *= factor;
1538 dfree *= factor;
1540 bytes_per_sector = 512;
1541 sectors_per_unit = bsize/bytes_per_sector;
1542 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1543 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1544 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1545 SBIG_UINT(pdata,0,dsize);
1546 SBIG_UINT(pdata,8,dfree);
1547 SIVAL(pdata,16,sectors_per_unit);
1548 SIVAL(pdata,20,bytes_per_sector);
1549 break;
1552 case SMB_FS_FULL_SIZE_INFORMATION:
1554 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1555 data_len = 32;
1556 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1557 block_size = lp_block_size(snum);
1558 if (bsize < block_size) {
1559 SMB_BIG_UINT factor = block_size/bsize;
1560 bsize = block_size;
1561 dsize /= factor;
1562 dfree /= factor;
1564 if (bsize > block_size) {
1565 SMB_BIG_UINT factor = bsize/block_size;
1566 bsize = block_size;
1567 dsize *= factor;
1568 dfree *= factor;
1570 bytes_per_sector = 512;
1571 sectors_per_unit = bsize/bytes_per_sector;
1572 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1573 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1574 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1575 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1576 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1577 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1578 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1579 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1580 break;
1583 case SMB_QUERY_FS_DEVICE_INFO:
1584 case SMB_FS_DEVICE_INFORMATION:
1585 data_len = 8;
1586 SIVAL(pdata,0,0); /* dev type */
1587 SIVAL(pdata,4,0); /* characteristics */
1588 break;
1590 #ifdef HAVE_SYS_QUOTAS
1591 case SMB_FS_QUOTA_INFORMATION:
1593 * what we have to send --metze:
1595 * Unknown1: 24 NULL bytes
1596 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1597 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
1598 * Quota Flags: 2 byte :
1599 * Unknown3: 6 NULL bytes
1601 * 48 bytes total
1603 * details for Quota Flags:
1605 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1606 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
1607 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1608 * 0x0001 Enable Quotas: enable quota for this fs
1612 /* we need to fake up a fsp here,
1613 * because its not send in this call
1615 files_struct fsp;
1616 SMB_NTQUOTA_STRUCT quotas;
1618 ZERO_STRUCT(fsp);
1619 ZERO_STRUCT(quotas);
1621 fsp.conn = conn;
1622 fsp.fnum = -1;
1623 fsp.fd = -1;
1625 /* access check */
1626 if (conn->admin_user != True) {
1627 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1628 lp_servicename(SNUM(conn)),conn->user));
1629 return ERROR_DOS(ERRDOS,ERRnoaccess);
1632 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
1633 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
1634 return ERROR_DOS(ERRSRV,ERRerror);
1637 data_len = 48;
1639 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
1641 /* Unknown1 24 NULL bytes*/
1642 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
1643 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
1644 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
1646 /* Default Soft Quota 8 bytes */
1647 SBIG_UINT(pdata,24,quotas.softlim);
1649 /* Default Hard Quota 8 bytes */
1650 SBIG_UINT(pdata,32,quotas.hardlim);
1652 /* Quota flag 2 bytes */
1653 SSVAL(pdata,40,quotas.qflags);
1655 /* Unknown3 6 NULL bytes */
1656 SSVAL(pdata,42,0);
1657 SIVAL(pdata,44,0);
1659 break;
1661 #endif /* HAVE_SYS_QUOTAS */
1662 case SMB_FS_OBJECTID_INFORMATION:
1663 data_len = 64;
1664 break;
1667 * Query the version and capabilities of the CIFS UNIX extensions
1668 * in use.
1671 case SMB_QUERY_CIFS_UNIX_INFO:
1672 if (!lp_unix_extensions())
1673 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1674 data_len = 12;
1675 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
1676 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
1677 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
1678 break;
1680 case SMB_MAC_QUERY_FS_INFO:
1682 * Thursby MAC extension... ONLY on NTFS filesystems
1683 * once we do streams then we don't need this
1685 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1686 data_len = 88;
1687 SIVAL(pdata,84,0x100); /* Don't support mac... */
1688 break;
1690 /* drop through */
1691 default:
1692 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1696 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1698 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1700 return -1;
1703 #ifdef HAVE_SYS_QUOTAS
1704 /****************************************************************************
1705 Reply to a TRANS2_SETFSINFO (set filesystem info).
1706 ****************************************************************************/
1708 static int call_trans2setfsinfo(connection_struct *conn,
1709 char *inbuf, char *outbuf, int length, int bufsize,
1710 char **pparams, int total_params, char **ppdata, int total_data)
1712 char *pdata = *ppdata;
1713 char *params = *pparams;
1714 files_struct *fsp = NULL;
1715 uint16 info_level;
1716 int outsize;
1717 SMB_NTQUOTA_STRUCT quotas;
1719 ZERO_STRUCT(quotas);
1721 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
1723 /* access check */
1724 if ((conn->admin_user != True)||!CAN_WRITE(conn)) {
1725 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
1726 lp_servicename(SNUM(conn)),conn->user));
1727 return ERROR_DOS(ERRSRV,ERRaccess);
1730 /* */
1731 if (total_params < 4) {
1732 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
1733 total_params));
1734 return ERROR_DOS(ERRDOS,ERRinvalidparam);
1737 fsp = file_fsp(params,0);
1739 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
1740 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
1741 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
1744 info_level = SVAL(params,2);
1746 switch(info_level) {
1747 case SMB_FS_QUOTA_INFORMATION:
1748 /* note: normaly there're 48 bytes,
1749 * but we didn't use the last 6 bytes for now
1750 * --metze
1752 if (total_data < 42) {
1753 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
1754 total_data));
1755 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1758 /* unknown_1 24 NULL bytes in pdata*/
1760 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
1761 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
1762 #ifdef LARGE_SMB_OFF_T
1763 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
1764 #else /* LARGE_SMB_OFF_T */
1765 if ((IVAL(pdata,28) != 0)&&
1766 ((quotas.softlim != 0xFFFFFFFF)||
1767 (IVAL(pdata,28)!=0xFFFFFFFF))) {
1768 /* more than 32 bits? */
1769 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1771 #endif /* LARGE_SMB_OFF_T */
1773 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
1774 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
1775 #ifdef LARGE_SMB_OFF_T
1776 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
1777 #else /* LARGE_SMB_OFF_T */
1778 if ((IVAL(pdata,36) != 0)&&
1779 ((quotas.hardlim != 0xFFFFFFFF)||
1780 (IVAL(pdata,36)!=0xFFFFFFFF))) {
1781 /* more than 32 bits? */
1782 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1784 #endif /* LARGE_SMB_OFF_T */
1786 /* quota_flags 2 bytes **/
1787 quotas.qflags = SVAL(pdata,40);
1789 /* unknown_2 6 NULL bytes follow*/
1791 /* now set the quotas */
1792 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
1793 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
1794 return ERROR_DOS(ERRSRV,ERRerror);
1797 break;
1798 default:
1799 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
1800 info_level));
1801 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1802 break;
1806 * sending this reply works fine,
1807 * but I'm not sure it's the same
1808 * like windows do...
1809 * --metze
1811 outsize = set_message(outbuf,10,0,True);
1813 return outsize;
1815 #endif /* HAVE_SYS_QUOTAS */
1817 /****************************************************************************
1818 * Utility function to set bad path error.
1819 ****************************************************************************/
1821 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
1823 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
1824 err, (int)bad_path ));
1826 if(err == ENOENT) {
1827 if (bad_path) {
1828 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1829 } else {
1830 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
1833 return UNIXERROR(def_class,def_code);
1836 /****************************************************************************
1837 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1838 file name or file id).
1839 ****************************************************************************/
1841 static int call_trans2qfilepathinfo(connection_struct *conn,
1842 char *inbuf, char *outbuf, int length,
1843 int bufsize,
1844 char **pparams, int total_params, char **ppdata, int total_data)
1846 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1847 char *params = *pparams;
1848 char *pdata = *ppdata;
1849 uint16 tran_call = SVAL(inbuf, smb_setup0);
1850 uint16 info_level;
1851 int mode=0;
1852 SMB_OFF_T file_size=0;
1853 SMB_BIG_UINT allocation_size=0;
1854 unsigned int data_size;
1855 unsigned int param_size = 2;
1856 SMB_STRUCT_STAT sbuf;
1857 pstring fname, dos_fname;
1858 char *fullpathname;
1859 char *base_name;
1860 char *p;
1861 SMB_OFF_T pos = 0;
1862 BOOL bad_path = False;
1863 BOOL delete_pending = False;
1864 int len;
1865 time_t c_time;
1866 files_struct *fsp = NULL;
1867 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
1869 if (!params)
1870 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1872 if (tran_call == TRANSACT2_QFILEINFO) {
1873 if (total_params < 4)
1874 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1876 fsp = file_fsp(params,0);
1877 info_level = SVAL(params,2);
1879 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1881 if(fsp && (fsp->fake_file_handle)) {
1883 * This is actually for the QUOTA_FAKE_FILE --metze
1886 pstrcpy(fname, fsp->fsp_name);
1887 unix_convert(fname,conn,0,&bad_path,&sbuf);
1888 if (!check_name(fname,conn)) {
1889 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno)));
1890 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1893 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1895 * This is actually a QFILEINFO on a directory
1896 * handle (returned from an NT SMB). NT5.0 seems
1897 * to do this call. JRA.
1899 pstrcpy(fname, fsp->fsp_name);
1900 unix_convert(fname,conn,0,&bad_path,&sbuf);
1901 if (!check_name(fname,conn)) {
1902 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1903 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1906 if (INFO_LEVEL_IS_UNIX(info_level)) {
1907 /* Always do lstat for UNIX calls. */
1908 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
1909 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
1910 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1912 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
1913 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
1914 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1917 delete_pending = fsp->directory_delete_on_close;
1918 } else {
1920 * Original code - this is an open file.
1922 CHECK_FSP(fsp,conn);
1924 pstrcpy(fname, fsp->fsp_name);
1925 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
1926 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
1927 return(UNIXERROR(ERRDOS,ERRbadfid));
1929 pos = fsp->position_information;
1930 delete_pending = fsp->delete_on_close;
1931 desired_access = fsp->desired_access;
1933 } else {
1934 NTSTATUS status = NT_STATUS_OK;
1936 /* qpathinfo */
1937 if (total_params < 6)
1938 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1940 info_level = SVAL(params,0);
1942 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1944 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
1945 if (!NT_STATUS_IS_OK(status)) {
1946 return ERROR_NT(status);
1949 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1951 unix_convert(fname,conn,0,&bad_path,&sbuf);
1952 if (!check_name(fname,conn)) {
1953 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1954 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1957 if (INFO_LEVEL_IS_UNIX(info_level)) {
1958 /* Always do lstat for UNIX calls. */
1959 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
1960 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
1961 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1963 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
1964 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
1965 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1969 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
1970 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1972 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
1973 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
1975 p = strrchr_m(fname,'/');
1976 if (!p)
1977 base_name = fname;
1978 else
1979 base_name = p+1;
1981 mode = dos_mode(conn,fname,&sbuf);
1982 if (!mode)
1983 mode = FILE_ATTRIBUTE_NORMAL;
1985 fullpathname = fname;
1986 file_size = get_file_size(sbuf);
1987 allocation_size = get_allocation_size(fsp,&sbuf);
1988 if (mode & aDIR)
1989 file_size = 0;
1991 params = Realloc(*pparams,2);
1992 if (params == NULL)
1993 return ERROR_DOS(ERRDOS,ERRnomem);
1994 *pparams = params;
1995 memset((char *)params,'\0',2);
1996 data_size = max_data_bytes + 1024;
1997 pdata = Realloc(*ppdata, data_size);
1998 if ( pdata == NULL )
1999 return ERROR_DOS(ERRDOS,ERRnomem);
2000 *ppdata = pdata;
2002 if (total_data > 0 && IVAL(pdata,0) == total_data) {
2003 /* uggh, EAs for OS2 */
2004 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2005 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2008 memset((char *)pdata,'\0',data_size);
2010 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2012 if (lp_dos_filetime_resolution(SNUM(conn))) {
2013 c_time &= ~1;
2014 sbuf.st_atime &= ~1;
2015 sbuf.st_mtime &= ~1;
2016 sbuf.st_mtime &= ~1;
2019 /* NT expects the name to be in an exact form of the *full*
2020 filename. See the trans2 torture test */
2021 if (strequal(base_name,".")) {
2022 pstrcpy(dos_fname, "\\");
2023 } else {
2024 pstr_sprintf(dos_fname, "\\%s", fname);
2025 string_replace(dos_fname, '/', '\\');
2028 switch (info_level) {
2029 case SMB_INFO_STANDARD:
2030 case SMB_INFO_QUERY_EA_SIZE:
2031 data_size = (info_level==1?22:26);
2032 put_dos_date2(pdata,l1_fdateCreation,c_time);
2033 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2034 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2035 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2036 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2037 SSVAL(pdata,l1_attrFile,mode);
2038 SIVAL(pdata,l1_attrFile+2,0); /* this is what win2003 does */
2039 break;
2041 case SMB_INFO_IS_NAME_VALID:
2042 if (tran_call == TRANSACT2_QFILEINFO) {
2043 /* os/2 needs this ? really ?*/
2044 return ERROR_DOS(ERRDOS,ERRbadfunc);
2046 data_size = 0;
2047 param_size = 0;
2048 break;
2050 case SMB_INFO_QUERY_EAS_FROM_LIST:
2051 data_size = 24;
2052 put_dos_date2(pdata,0,c_time);
2053 put_dos_date2(pdata,4,sbuf.st_atime);
2054 put_dos_date2(pdata,8,sbuf.st_mtime);
2055 SIVAL(pdata,12,(uint32)file_size);
2056 SIVAL(pdata,16,(uint32)allocation_size);
2057 SIVAL(pdata,20,mode);
2058 break;
2060 case SMB_INFO_QUERY_ALL_EAS:
2061 data_size = 4;
2062 SIVAL(pdata,0,0); /* ea size */
2063 break;
2065 case SMB_FILE_BASIC_INFORMATION:
2066 case SMB_QUERY_FILE_BASIC_INFO:
2068 if (info_level == SMB_QUERY_FILE_BASIC_INFO)
2069 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2070 else {
2071 data_size = 40;
2072 SIVAL(pdata,36,0);
2074 put_long_date(pdata,c_time);
2075 put_long_date(pdata+8,sbuf.st_atime);
2076 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2077 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2078 SIVAL(pdata,32,mode);
2080 DEBUG(5,("SMB_QFBI - "));
2082 time_t create_time = c_time;
2083 DEBUG(5,("create: %s ", ctime(&create_time)));
2085 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2086 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2087 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2088 DEBUG(5,("mode: %x\n", mode));
2090 break;
2092 case SMB_FILE_STANDARD_INFORMATION:
2093 case SMB_QUERY_FILE_STANDARD_INFO:
2095 data_size = 24;
2096 SOFF_T(pdata,0,allocation_size);
2097 SOFF_T(pdata,8,file_size);
2098 if (delete_pending & sbuf.st_nlink)
2099 SIVAL(pdata,16,sbuf.st_nlink - 1);
2100 else
2101 SIVAL(pdata,16,sbuf.st_nlink);
2102 SCVAL(pdata,20,0);
2103 SCVAL(pdata,21,(mode&aDIR)?1:0);
2104 break;
2106 case SMB_FILE_EA_INFORMATION:
2107 case SMB_QUERY_FILE_EA_INFO:
2108 data_size = 4;
2109 break;
2111 /* Get the 8.3 name - used if NT SMB was negotiated. */
2112 case SMB_QUERY_FILE_ALT_NAME_INFO:
2113 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2115 pstring short_name;
2117 pstrcpy(short_name,base_name);
2118 /* Mangle if not already 8.3 */
2119 if(!mangle_is_8_3(short_name, True)) {
2120 mangle_map(short_name,True,True,SNUM(conn));
2122 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2123 data_size = 4 + len;
2124 SIVAL(pdata,0,len);
2125 break;
2128 case SMB_QUERY_FILE_NAME_INFO:
2130 this must be *exactly* right for ACLs on mapped drives to work
2132 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2133 data_size = 4 + len;
2134 SIVAL(pdata,0,len);
2135 break;
2137 case SMB_FILE_ALLOCATION_INFORMATION:
2138 case SMB_QUERY_FILE_ALLOCATION_INFO:
2139 data_size = 8;
2140 SOFF_T(pdata,0,allocation_size);
2141 break;
2143 case SMB_FILE_END_OF_FILE_INFORMATION:
2144 case SMB_QUERY_FILE_END_OF_FILEINFO:
2145 data_size = 8;
2146 SOFF_T(pdata,0,file_size);
2147 break;
2149 case SMB_QUERY_FILE_ALL_INFO:
2150 case SMB_FILE_ALL_INFORMATION:
2151 put_long_date(pdata,c_time);
2152 put_long_date(pdata+8,sbuf.st_atime);
2153 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2154 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2155 SIVAL(pdata,32,mode);
2156 pdata += 40;
2157 SOFF_T(pdata,0,allocation_size);
2158 SOFF_T(pdata,8,file_size);
2159 if (delete_pending && sbuf.st_nlink)
2160 SIVAL(pdata,16,sbuf.st_nlink - 1);
2161 else
2162 SIVAL(pdata,16,sbuf.st_nlink);
2163 SCVAL(pdata,20,delete_pending);
2164 SCVAL(pdata,21,(mode&aDIR)?1:0);
2165 pdata += 24;
2166 pdata += 4; /* EA info */
2167 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2168 SIVAL(pdata,0,len);
2169 pdata += 4 + len;
2170 data_size = PTR_DIFF(pdata,(*ppdata));
2171 break;
2173 case SMB_FILE_INTERNAL_INFORMATION:
2174 /* This should be an index number - looks like
2175 dev/ino to me :-)
2177 I think this causes us to fail the IFSKIT
2178 BasicFileInformationTest. -tpot */
2180 SIVAL(pdata,0,sbuf.st_dev);
2181 SIVAL(pdata,4,sbuf.st_ino);
2182 data_size = 8;
2183 break;
2185 case SMB_FILE_ACCESS_INFORMATION:
2186 SIVAL(pdata,0,desired_access);
2187 data_size = 4;
2188 break;
2190 case SMB_FILE_NAME_INFORMATION:
2191 /* Pathname with leading '\'. */
2193 size_t byte_len;
2194 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2195 SIVAL(pdata,0,byte_len);
2196 data_size = 4 + byte_len;
2197 break;
2200 case SMB_FILE_DISPOSITION_INFORMATION:
2201 data_size = 1;
2202 SCVAL(pdata,0,delete_pending);
2203 break;
2205 case SMB_FILE_POSITION_INFORMATION:
2206 data_size = 8;
2207 SOFF_T(pdata,0,pos);
2208 break;
2210 case SMB_FILE_MODE_INFORMATION:
2211 SIVAL(pdata,0,mode);
2212 data_size = 4;
2213 break;
2215 case SMB_FILE_ALIGNMENT_INFORMATION:
2216 SIVAL(pdata,0,0); /* No alignment needed. */
2217 data_size = 4;
2218 break;
2220 #if 0
2222 * NT4 server just returns "invalid query" to this - if we try to answer
2223 * it then NTws gets a BSOD! (tridge).
2224 * W2K seems to want this. JRA.
2226 case SMB_QUERY_FILE_STREAM_INFO:
2227 #endif
2228 case SMB_FILE_STREAM_INFORMATION:
2229 if (mode & aDIR) {
2230 data_size = 0;
2231 } else {
2232 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2233 SIVAL(pdata,0,0); /* ??? */
2234 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2235 SOFF_T(pdata,8,file_size);
2236 SIVAL(pdata,16,allocation_size);
2237 SIVAL(pdata,20,0); /* ??? */
2238 data_size = 24 + byte_len;
2240 break;
2242 case SMB_QUERY_COMPRESSION_INFO:
2243 case SMB_FILE_COMPRESSION_INFORMATION:
2244 SOFF_T(pdata,0,file_size);
2245 SIVAL(pdata,8,0); /* ??? */
2246 SIVAL(pdata,12,0); /* ??? */
2247 data_size = 16;
2248 break;
2250 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2251 put_long_date(pdata,c_time);
2252 put_long_date(pdata+8,sbuf.st_atime);
2253 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2254 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2255 SIVAL(pdata,32,allocation_size);
2256 SOFF_T(pdata,40,file_size);
2257 SIVAL(pdata,48,mode);
2258 SIVAL(pdata,52,0); /* ??? */
2259 data_size = 56;
2260 break;
2262 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2263 SIVAL(pdata,0,mode);
2264 SIVAL(pdata,4,0);
2265 data_size = 8;
2266 break;
2269 * CIFS UNIX Extensions.
2272 case SMB_QUERY_FILE_UNIX_BASIC:
2274 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2276 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2277 pdata += 8;
2279 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2280 pdata += 8;
2282 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2283 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2284 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2285 pdata += 24;
2287 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2288 SIVAL(pdata,4,0);
2289 pdata += 8;
2291 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2292 SIVAL(pdata,4,0);
2293 pdata += 8;
2295 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2296 pdata += 4;
2298 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2299 SIVAL(pdata,4,0);
2300 pdata += 8;
2302 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2303 SIVAL(pdata,4,0);
2304 pdata += 8;
2306 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2307 pdata += 8;
2309 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2310 SIVAL(pdata,4,0);
2311 pdata += 8;
2313 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2314 SIVAL(pdata,4,0);
2315 pdata += 8+1;
2316 data_size = PTR_DIFF(pdata,(*ppdata));
2319 int i;
2320 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2322 for (i=0; i<100; i++)
2323 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2324 DEBUG(4,("\n"));
2327 break;
2329 case SMB_QUERY_FILE_UNIX_LINK:
2331 pstring buffer;
2333 #ifdef S_ISLNK
2334 if(!S_ISLNK(sbuf.st_mode))
2335 return(UNIXERROR(ERRSRV,ERRbadlink));
2336 #else
2337 return(UNIXERROR(ERRDOS,ERRbadlink));
2338 #endif
2339 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2340 if (len == -1)
2341 return(UNIXERROR(ERRDOS,ERRnoaccess));
2342 buffer[len] = 0;
2343 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2344 pdata += len;
2345 data_size = PTR_DIFF(pdata,(*ppdata));
2347 break;
2350 default:
2351 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2354 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
2356 return(-1);
2359 /****************************************************************************
2360 Deal with the internal needs of setting the delete on close flag. Note that
2361 as the tdb locking is recursive, it is safe to call this from within
2362 open_file_shared. JRA.
2363 ****************************************************************************/
2365 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2368 * Only allow delete on close for writable shares.
2371 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2372 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2373 fsp->fsp_name ));
2374 return NT_STATUS_ACCESS_DENIED;
2377 * Only allow delete on close for files/directories opened with delete intent.
2380 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2381 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2382 fsp->fsp_name ));
2383 return NT_STATUS_ACCESS_DENIED;
2386 if(fsp->is_directory) {
2387 fsp->directory_delete_on_close = delete_on_close;
2388 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2389 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2390 } else {
2391 fsp->delete_on_close = delete_on_close;
2392 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2393 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2396 return NT_STATUS_OK;
2399 /****************************************************************************
2400 Sets the delete on close flag over all share modes on this file.
2401 Modify the share mode entry for all files open
2402 on this device and inode to tell other smbds we have
2403 changed the delete on close flag. This will be noticed
2404 in the close code, the last closer will delete the file
2405 if flag is set.
2406 ****************************************************************************/
2408 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2410 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2411 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2413 if (fsp->is_directory || fsp->is_stat)
2414 return NT_STATUS_OK;
2416 if (lock_share_entry_fsp(fsp) == False)
2417 return NT_STATUS_ACCESS_DENIED;
2419 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2420 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2421 fsp->fsp_name ));
2422 unlock_share_entry_fsp(fsp);
2423 return NT_STATUS_ACCESS_DENIED;
2426 unlock_share_entry_fsp(fsp);
2427 return NT_STATUS_OK;
2430 /****************************************************************************
2431 Returns true if this pathname is within the share, and thus safe.
2432 ****************************************************************************/
2434 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2436 #ifdef PATH_MAX
2437 char resolved_name[PATH_MAX+1];
2438 #else
2439 pstring resolved_name;
2440 #endif
2441 fstring last_component;
2442 pstring link_dest;
2443 pstring link_test;
2444 char *p;
2445 BOOL bad_path = False;
2446 SMB_STRUCT_STAT sbuf;
2448 pstrcpy(link_dest, link_dest_in);
2449 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2451 /* Store the UNIX converted path. */
2452 pstrcpy(link_dest_out, link_dest);
2454 p = strrchr(link_dest, '/');
2455 if (p) {
2456 fstrcpy(last_component, p+1);
2457 *p = '\0';
2458 } else {
2459 fstrcpy(last_component, link_dest);
2460 pstrcpy(link_dest, "./");
2463 if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL)
2464 return -1;
2466 pstrcpy(link_dest, resolved_name);
2467 pstrcat(link_dest, "/");
2468 pstrcat(link_dest, last_component);
2470 if (*link_dest != '/') {
2471 /* Relative path. */
2472 pstrcpy(link_test, conn->connectpath);
2473 pstrcat(link_test, "/");
2474 pstrcat(link_test, link_dest);
2475 } else {
2476 pstrcpy(link_test, link_dest);
2480 * Check if the link is within the share.
2483 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2484 errno = EACCES;
2485 return -1;
2487 return 0;
2490 /****************************************************************************
2491 Set a hard link (called by UNIX extensions and by NT rename with HARD link
2492 code.
2493 ****************************************************************************/
2495 NTSTATUS hardlink_internals(connection_struct *conn, char *name, char *newname)
2497 BOOL bad_path_src = False;
2498 BOOL bad_path_dest = False;
2499 SMB_STRUCT_STAT sbuf1, sbuf2;
2500 BOOL rc, rcdest;
2501 pstring last_component_src;
2502 pstring last_component_dest;
2503 NTSTATUS status = NT_STATUS_OK;
2505 ZERO_STRUCT(sbuf1);
2506 ZERO_STRUCT(sbuf2);
2508 /* No wildcards. */
2509 if (ms_has_wild(name) || ms_has_wild(newname)) {
2510 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
2513 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
2514 if (!rc && bad_path_src) {
2515 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2518 /* Quick check for "." and ".." */
2519 if (last_component_src[0] == '.') {
2520 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
2521 return NT_STATUS_OBJECT_NAME_INVALID;
2525 /* source must already exist. */
2526 if (!VALID_STAT(sbuf1)) {
2527 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2530 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
2531 if (!rcdest && bad_path_dest) {
2532 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2535 /* Quick check for "." and ".." */
2536 if (last_component_dest[0] == '.') {
2537 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
2538 return NT_STATUS_OBJECT_NAME_INVALID;
2542 /* Disallow if already exists. */
2543 if (VALID_STAT(sbuf2)) {
2544 return NT_STATUS_OBJECT_NAME_COLLISION;
2547 /* No links from a directory. */
2548 if (S_ISDIR(sbuf1.st_mode)) {
2549 return NT_STATUS_FILE_IS_A_DIRECTORY;
2552 if (ensure_link_is_safe(conn, newname, newname) != 0)
2553 return NT_STATUS_ACCESS_DENIED;
2555 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", name, newname ));
2557 if (SMB_VFS_LINK(conn,name,newname) != 0) {
2558 status = map_nt_error_from_unix(errno);
2559 DEBUG(3,("hardlink_internals: Error %s link %s -> %s\n",
2560 nt_errstr(status), name,newname));
2563 return status;
2566 /****************************************************************************
2567 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2568 ****************************************************************************/
2570 static int call_trans2setfilepathinfo(connection_struct *conn,
2571 char *inbuf, char *outbuf, int length, int bufsize,
2572 char **pparams, int total_params, char **ppdata, int total_data)
2574 char *params = *pparams;
2575 char *pdata = *ppdata;
2576 uint16 tran_call = SVAL(inbuf, smb_setup0);
2577 uint16 info_level;
2578 int dosmode=0;
2579 SMB_OFF_T size=0;
2580 struct utimbuf tvs;
2581 SMB_STRUCT_STAT sbuf;
2582 pstring fname;
2583 int fd = -1;
2584 BOOL bad_path = False;
2585 files_struct *fsp = NULL;
2586 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2587 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2588 mode_t unixmode = 0;
2589 NTSTATUS status = NT_STATUS_OK;
2591 if (!params)
2592 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2594 if (tran_call == TRANSACT2_SETFILEINFO) {
2595 if (total_params < 4)
2596 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2598 fsp = file_fsp(params,0);
2599 info_level = SVAL(params,2);
2601 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2603 * This is actually a SETFILEINFO on a directory
2604 * handle (returned from an NT SMB). NT5.0 seems
2605 * to do this call. JRA.
2607 pstrcpy(fname, fsp->fsp_name);
2608 unix_convert(fname,conn,0,&bad_path,&sbuf);
2609 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2610 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2611 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2613 } else if (fsp && fsp->print_file) {
2615 * Doing a DELETE_ON_CLOSE should cancel a print job.
2617 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
2618 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2620 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
2622 SSVAL(params,0,0);
2623 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2624 return(-1);
2625 } else
2626 return (UNIXERROR(ERRDOS,ERRbadpath));
2627 } else {
2629 * Original code - this is an open file.
2631 CHECK_FSP(fsp,conn);
2633 pstrcpy(fname, fsp->fsp_name);
2634 fd = fsp->fd;
2636 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
2637 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2638 return(UNIXERROR(ERRDOS,ERRbadfid));
2641 } else {
2642 /* set path info */
2643 if (total_params < 6)
2644 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2646 info_level = SVAL(params,0);
2647 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
2648 if (!NT_STATUS_IS_OK(status)) {
2649 return ERROR_NT(status);
2651 unix_convert(fname,conn,0,&bad_path,&sbuf);
2654 * For CIFS UNIX extensions the target name may not exist.
2657 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2658 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
2659 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2662 if(!check_name(fname, conn)) {
2663 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2668 if (!CAN_WRITE(conn))
2669 return ERROR_DOS(ERRSRV,ERRaccess);
2671 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2672 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2674 if (VALID_STAT(sbuf))
2675 unixmode = sbuf.st_mode;
2677 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
2678 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
2680 /* Realloc the parameter and data sizes */
2681 params = Realloc(*pparams,2);
2682 if(params == NULL)
2683 return ERROR_DOS(ERRDOS,ERRnomem);
2684 *pparams = params;
2686 SSVAL(params,0,0);
2688 if (fsp) {
2689 /* the pending modtime overrides the current modtime */
2690 sbuf.st_mtime = fsp->pending_modtime;
2693 size = get_file_size(sbuf);
2694 tvs.modtime = sbuf.st_mtime;
2695 tvs.actime = sbuf.st_atime;
2696 dosmode = dos_mode(conn,fname,&sbuf);
2697 unixmode = sbuf.st_mode;
2699 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2700 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2702 switch (info_level) {
2703 case SMB_INFO_STANDARD:
2705 if (total_data < 12)
2706 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2708 /* access time */
2709 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2710 /* write time */
2711 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2712 break;
2715 case SMB_INFO_SET_EA:
2716 return(ERROR_DOS(ERRDOS,ERReasnotsupported));
2718 /* XXXX um, i don't think this is right.
2719 it's also not in the cifs6.txt spec.
2721 case SMB_INFO_QUERY_EAS_FROM_LIST:
2722 if (total_data < 28)
2723 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2725 tvs.actime = make_unix_date2(pdata+8);
2726 tvs.modtime = make_unix_date2(pdata+12);
2727 size = IVAL(pdata,16);
2728 dosmode = IVAL(pdata,24);
2729 break;
2731 /* XXXX nor this. not in cifs6.txt, either. */
2732 case SMB_INFO_QUERY_ALL_EAS:
2733 if (total_data < 28)
2734 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2736 tvs.actime = make_unix_date2(pdata+8);
2737 tvs.modtime = make_unix_date2(pdata+12);
2738 size = IVAL(pdata,16);
2739 dosmode = IVAL(pdata,24);
2740 break;
2742 case SMB_SET_FILE_BASIC_INFO:
2743 case SMB_FILE_BASIC_INFORMATION:
2745 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2746 time_t write_time;
2747 time_t changed_time;
2749 if (total_data < 36)
2750 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2752 /* Ignore create time at offset pdata. */
2754 /* access time */
2755 tvs.actime = interpret_long_date(pdata+8);
2757 write_time = interpret_long_date(pdata+16);
2758 changed_time = interpret_long_date(pdata+24);
2760 tvs.modtime = MIN(write_time, changed_time);
2762 if (write_time > tvs.modtime && write_time != 0xffffffff) {
2763 tvs.modtime = write_time;
2765 /* Prefer a defined time to an undefined one. */
2766 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2767 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2768 ? changed_time : write_time);
2770 /* attributes */
2771 dosmode = IVAL(pdata,32);
2772 break;
2775 case SMB_FILE_ALLOCATION_INFORMATION:
2776 case SMB_SET_FILE_ALLOCATION_INFO:
2778 int ret = -1;
2779 SMB_BIG_UINT allocation_size;
2781 if (total_data < 8)
2782 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2784 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
2785 #ifdef LARGE_SMB_OFF_T
2786 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
2787 #else /* LARGE_SMB_OFF_T */
2788 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2789 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2790 #endif /* LARGE_SMB_OFF_T */
2791 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2792 fname, (double)allocation_size ));
2794 if (allocation_size)
2795 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
2797 if(allocation_size != get_file_size(sbuf)) {
2798 SMB_STRUCT_STAT new_sbuf;
2800 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2801 fname, (double)allocation_size ));
2803 if (fd == -1) {
2804 files_struct *new_fsp = NULL;
2805 int access_mode = 0;
2806 int action = 0;
2808 if(global_oplock_break) {
2809 /* Queue this file modify as we are the process of an oplock break. */
2811 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2812 DEBUGADD(2,( "in oplock break state.\n"));
2814 push_oplock_pending_smb_message(inbuf, length);
2815 return -1;
2818 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2819 SET_OPEN_MODE(DOS_OPEN_RDWR),
2820 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2821 0, 0, &access_mode, &action);
2823 if (new_fsp == NULL)
2824 return(UNIXERROR(ERRDOS,ERRbadpath));
2825 ret = vfs_allocate_file_space(new_fsp, allocation_size);
2826 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2827 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2828 new_fsp->fnum, strerror(errno)));
2829 ret = -1;
2831 close_file(new_fsp,True);
2832 } else {
2833 ret = vfs_allocate_file_space(fsp, allocation_size);
2834 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
2835 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2836 fsp->fnum, strerror(errno)));
2837 ret = -1;
2840 if (ret == -1)
2841 return ERROR_NT(NT_STATUS_DISK_FULL);
2843 /* Allocate can truncate size... */
2844 size = get_file_size(new_sbuf);
2847 break;
2850 case SMB_FILE_END_OF_FILE_INFORMATION:
2851 case SMB_SET_FILE_END_OF_FILE_INFO:
2853 if (total_data < 8)
2854 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2856 size = IVAL(pdata,0);
2857 #ifdef LARGE_SMB_OFF_T
2858 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2859 #else /* LARGE_SMB_OFF_T */
2860 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2861 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2862 #endif /* LARGE_SMB_OFF_T */
2863 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2864 break;
2867 case SMB_FILE_DISPOSITION_INFORMATION:
2868 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2870 BOOL delete_on_close;
2872 if (total_data < 1)
2873 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2875 delete_on_close = (CVAL(pdata,0) ? True : False);
2877 /* Just ignore this set on a path. */
2878 if (tran_call != TRANSACT2_SETFILEINFO)
2879 break;
2881 if (fsp == NULL)
2882 return(UNIXERROR(ERRDOS,ERRbadfid));
2884 status = set_delete_on_close_internal(fsp, delete_on_close);
2886 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2887 return ERROR_NT(status);
2889 /* The set is across all open files on this dev/inode pair. */
2890 status =set_delete_on_close_over_all(fsp, delete_on_close);
2891 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2892 return ERROR_NT(status);
2894 break;
2897 case SMB_FILE_POSITION_INFORMATION:
2899 SMB_BIG_UINT position_information;
2901 if (total_data < 8)
2902 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2904 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
2905 #ifdef LARGE_SMB_OFF_T
2906 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
2907 #else /* LARGE_SMB_OFF_T */
2908 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2909 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2910 #endif /* LARGE_SMB_OFF_T */
2911 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
2912 fname, (double)position_information ));
2913 if (fsp)
2914 fsp->position_information = position_information;
2915 break;
2919 * CIFS UNIX extensions.
2922 case SMB_SET_FILE_UNIX_BASIC:
2924 uint32 raw_unixmode;
2926 if (total_data < 100)
2927 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2929 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
2930 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
2931 size=IVAL(pdata,0); /* first 8 Bytes are size */
2932 #ifdef LARGE_SMB_OFF_T
2933 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2934 #else /* LARGE_SMB_OFF_T */
2935 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2936 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2937 #endif /* LARGE_SMB_OFF_T */
2939 pdata+=24; /* ctime & st_blocks are not changed */
2940 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
2941 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
2942 pdata+=16;
2943 set_owner = (uid_t)IVAL(pdata,0);
2944 pdata += 8;
2945 set_grp = (gid_t)IVAL(pdata,0);
2946 pdata += 8;
2947 raw_unixmode = IVAL(pdata,28);
2948 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2949 dosmode = 0; /* Ensure dos mode change doesn't override this. */
2951 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2952 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2953 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2955 if (!VALID_STAT(sbuf)) {
2958 * The only valid use of this is to create character and block
2959 * devices, and named pipes. This is deprecated (IMHO) and
2960 * a new info level should be used for mknod. JRA.
2963 #if !defined(HAVE_MAKEDEV_FN)
2964 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2965 #else /* HAVE_MAKEDEV_FN */
2966 uint32 file_type = IVAL(pdata,0);
2967 uint32 dev_major = IVAL(pdata,4);
2968 uint32 dev_minor = IVAL(pdata,12);
2970 uid_t myuid = geteuid();
2971 gid_t mygid = getegid();
2972 SMB_DEV_T dev;
2974 if (tran_call == TRANSACT2_SETFILEINFO)
2975 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2977 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2978 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2980 dev = makedev(dev_major, dev_minor);
2982 /* We can only create as the owner/group we are. */
2984 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2985 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2986 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2987 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2989 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2990 file_type != UNIX_TYPE_FIFO)
2991 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2993 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2994 0%o for file %s\n", (double)dev, unixmode, fname ));
2996 /* Ok - do the mknod. */
2997 if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
2998 return(UNIXERROR(ERRDOS,ERRnoaccess));
3000 inherit_access_acl(conn, fname, unixmode);
3002 SSVAL(params,0,0);
3003 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3004 return(-1);
3005 #endif /* HAVE_MAKEDEV_FN */
3010 * Deal with the UNIX specific mode set.
3013 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3014 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3015 (unsigned int)unixmode, fname ));
3016 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3017 return(UNIXERROR(ERRDOS,ERRnoaccess));
3021 * Deal with the UNIX specific uid set.
3024 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3025 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3026 (unsigned int)set_owner, fname ));
3027 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3028 return(UNIXERROR(ERRDOS,ERRnoaccess));
3032 * Deal with the UNIX specific gid set.
3035 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3036 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3037 (unsigned int)set_owner, fname ));
3038 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3039 return(UNIXERROR(ERRDOS,ERRnoaccess));
3041 break;
3044 case SMB_SET_FILE_UNIX_LINK:
3046 pstring link_dest;
3047 /* Set a symbolic link. */
3048 /* Don't allow this if follow links is false. */
3050 if (!lp_symlinks(SNUM(conn)))
3051 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3053 srvstr_get_path(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE, &status);
3054 if (!NT_STATUS_IS_OK(status)) {
3055 return ERROR_NT(status);
3058 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
3059 return(UNIXERROR(ERRDOS,ERRnoaccess));
3061 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3062 fname, link_dest ));
3064 if (SMB_VFS_SYMLINK(conn,link_dest,fname) != 0)
3065 return(UNIXERROR(ERRDOS,ERRnoaccess));
3066 SSVAL(params,0,0);
3067 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3068 return(-1);
3071 case SMB_SET_FILE_UNIX_HLINK:
3073 pstring link_dest;
3075 /* Set a hard link. */
3076 srvstr_get_path(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE, &status);
3077 if (!NT_STATUS_IS_OK(status)) {
3078 return ERROR_NT(status);
3081 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3082 fname, link_dest ));
3084 status = hardlink_internals(conn, fname, link_dest);
3085 if (!NT_STATUS_IS_OK(status)) {
3086 return ERROR_NT(status);
3089 SSVAL(params,0,0);
3090 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3091 return(-1);
3094 case SMB_FILE_RENAME_INFORMATION:
3096 BOOL overwrite;
3097 uint32 root_fid;
3098 uint32 len;
3099 pstring newname;
3100 pstring base_name;
3101 char *p;
3103 if (total_data < 12)
3104 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3106 overwrite = (CVAL(pdata,0) ? True : False);
3107 root_fid = IVAL(pdata,4);
3108 len = IVAL(pdata,8);
3109 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
3110 if (!NT_STATUS_IS_OK(status)) {
3111 return ERROR_NT(status);
3114 /* Check the new name has no '/' characters. */
3115 if (strchr_m(newname, '/'))
3116 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3118 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3120 /* Create the base directory. */
3121 pstrcpy(base_name, fname);
3122 p = strrchr_m(base_name, '/');
3123 if (p)
3124 *p = '\0';
3125 /* Append the new name. */
3126 pstrcat(base_name, "/");
3127 pstrcat(base_name, newname);
3129 if (fsp) {
3130 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3131 fsp->fnum, fsp->fsp_name, base_name ));
3132 status = rename_internals_fsp(conn, fsp, base_name, overwrite);
3133 } else {
3134 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3135 fname, newname ));
3136 status = rename_internals(conn, fname, base_name, 0, overwrite);
3138 if (!NT_STATUS_IS_OK(status)) {
3139 return ERROR_NT(status);
3141 process_pending_change_notify_queue((time_t)0);
3142 SSVAL(params,0,0);
3143 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3144 return(-1);
3146 default:
3147 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3150 /* get some defaults (no modifications) if any info is zero or -1. */
3151 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
3152 tvs.actime = sbuf.st_atime;
3154 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3155 tvs.modtime = sbuf.st_mtime;
3157 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3158 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3159 DEBUG(6,("size: %.0f ", (double)size));
3161 if (dosmode) {
3162 if (S_ISDIR(sbuf.st_mode))
3163 dosmode |= aDIR;
3164 else
3165 dosmode &= ~aDIR;
3168 DEBUG(6,("dosmode: %x\n" , dosmode));
3170 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3171 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3172 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3173 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3176 * Only do this test if we are not explicitly
3177 * changing the size of a file.
3179 if (!size)
3180 size = get_file_size(sbuf);
3184 * Try and set the times, size and mode of this file -
3185 * if they are different from the current values
3187 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3188 if(fsp != NULL) {
3190 * This was a setfileinfo on an open file.
3191 * NT does this a lot. It's actually pointless
3192 * setting the time here, as it will be overwritten
3193 * on the next write, so we save the request
3194 * away and will set it on file close. JRA.
3197 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3198 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3199 fsp->pending_modtime = tvs.modtime;
3202 } else {
3204 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3206 if(file_utime(conn, fname, &tvs)!=0)
3207 return(UNIXERROR(ERRDOS,ERRnoaccess));
3211 /* check the mode isn't different, before changing it */
3212 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3214 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3216 if(file_chmod(conn, fname, dosmode, NULL)) {
3217 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
3218 return(UNIXERROR(ERRDOS,ERRnoaccess));
3222 if (size != get_file_size(sbuf)) {
3224 int ret;
3226 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3227 fname, (double)size ));
3229 if (fd == -1) {
3230 files_struct *new_fsp = NULL;
3231 int access_mode = 0;
3232 int action = 0;
3234 if(global_oplock_break) {
3235 /* Queue this file modify as we are the process of an oplock break. */
3237 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3238 DEBUGADD(2,( "in oplock break state.\n"));
3240 push_oplock_pending_smb_message(inbuf, length);
3241 return -1;
3244 new_fsp = open_file_shared(conn, fname, &sbuf,
3245 SET_OPEN_MODE(DOS_OPEN_RDWR),
3246 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3247 0, 0, &access_mode, &action);
3249 if (new_fsp == NULL)
3250 return(UNIXERROR(ERRDOS,ERRbadpath));
3251 ret = vfs_set_filelen(new_fsp, size);
3252 close_file(new_fsp,True);
3253 } else {
3254 ret = vfs_set_filelen(fsp, size);
3257 if (ret == -1)
3258 return (UNIXERROR(ERRHRD,ERRdiskfull));
3261 SSVAL(params,0,0);
3262 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3264 return(-1);
3267 /****************************************************************************
3268 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3269 ****************************************************************************/
3271 static int call_trans2mkdir(connection_struct *conn,
3272 char *inbuf, char *outbuf, int length, int bufsize,
3273 char **pparams, int total_params, char **ppdata, int total_data)
3275 char *params = *pparams;
3276 pstring directory;
3277 int ret = -1;
3278 SMB_STRUCT_STAT sbuf;
3279 BOOL bad_path = False;
3280 NTSTATUS status = NT_STATUS_OK;
3282 if (!CAN_WRITE(conn))
3283 return ERROR_DOS(ERRSRV,ERRaccess);
3285 if (total_params < 4)
3286 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3288 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status);
3289 if (!NT_STATUS_IS_OK(status)) {
3290 return ERROR_NT(status);
3293 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3295 unix_convert(directory,conn,0,&bad_path,&sbuf);
3296 if (check_name(directory,conn))
3297 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3299 if(ret < 0) {
3300 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3301 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
3304 /* Realloc the parameter and data sizes */
3305 params = Realloc(*pparams,2);
3306 if(params == NULL)
3307 return ERROR_DOS(ERRDOS,ERRnomem);
3308 *pparams = params;
3310 SSVAL(params,0,0);
3312 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3314 return(-1);
3317 /****************************************************************************
3318 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3319 We don't actually do this - we just send a null response.
3320 ****************************************************************************/
3322 static int call_trans2findnotifyfirst(connection_struct *conn,
3323 char *inbuf, char *outbuf, int length, int bufsize,
3324 char **pparams, int total_params, char **ppdata, int total_data)
3326 static uint16 fnf_handle = 257;
3327 char *params = *pparams;
3328 uint16 info_level;
3330 if (total_params < 6)
3331 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3333 info_level = SVAL(params,4);
3334 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3336 switch (info_level) {
3337 case 1:
3338 case 2:
3339 break;
3340 default:
3341 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3344 /* Realloc the parameter and data sizes */
3345 params = Realloc(*pparams,6);
3346 if(params == NULL)
3347 return ERROR_DOS(ERRDOS,ERRnomem);
3348 *pparams = params;
3350 SSVAL(params,0,fnf_handle);
3351 SSVAL(params,2,0); /* No changes */
3352 SSVAL(params,4,0); /* No EA errors */
3354 fnf_handle++;
3356 if(fnf_handle == 0)
3357 fnf_handle = 257;
3359 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3361 return(-1);
3364 /****************************************************************************
3365 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3366 changes). Currently this does nothing.
3367 ****************************************************************************/
3369 static int call_trans2findnotifynext(connection_struct *conn,
3370 char *inbuf, char *outbuf, int length, int bufsize,
3371 char **pparams, int total_params, char **ppdata, int total_data)
3373 char *params = *pparams;
3375 DEBUG(3,("call_trans2findnotifynext\n"));
3377 /* Realloc the parameter and data sizes */
3378 params = Realloc(*pparams,4);
3379 if(params == NULL)
3380 return ERROR_DOS(ERRDOS,ERRnomem);
3381 *pparams = params;
3383 SSVAL(params,0,0); /* No changes */
3384 SSVAL(params,2,0); /* No EA errors */
3386 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3388 return(-1);
3391 /****************************************************************************
3392 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3393 ****************************************************************************/
3395 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3396 char* outbuf, int length, int bufsize,
3397 char **pparams, int total_params, char **ppdata, int total_data)
3399 char *params = *pparams;
3400 pstring pathname;
3401 int reply_size = 0;
3402 int max_referral_level;
3404 DEBUG(10,("call_trans2getdfsreferral\n"));
3406 if (total_params < 2)
3407 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3409 max_referral_level = SVAL(params,0);
3411 if(!lp_host_msdfs())
3412 return ERROR_DOS(ERRDOS,ERRbadfunc);
3414 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
3415 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
3416 return UNIXERROR(ERRDOS,ERRbadfile);
3418 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3419 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3421 return(-1);
3424 #define LMCAT_SPL 0x53
3425 #define LMFUNC_GETJOBID 0x60
3427 /****************************************************************************
3428 Reply to a TRANS2_IOCTL - used for OS/2 printing.
3429 ****************************************************************************/
3431 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3432 char* outbuf, int length, int bufsize,
3433 char **pparams, int total_params, char **ppdata, int total_data)
3435 char *pdata = *ppdata;
3436 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3438 /* check for an invalid fid before proceeding */
3440 if (!fsp)
3441 return(ERROR_DOS(ERRDOS,ERRbadfid));
3443 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3444 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3445 pdata = Realloc(*ppdata, 32);
3446 if(pdata == NULL)
3447 return ERROR_DOS(ERRDOS,ERRnomem);
3448 *ppdata = pdata;
3450 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3451 CAN ACCEPT THIS IN UNICODE. JRA. */
3453 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
3454 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3455 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3456 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3457 return(-1);
3458 } else {
3459 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3460 return ERROR_DOS(ERRSRV,ERRerror);
3464 /****************************************************************************
3465 Reply to a SMBfindclose (stop trans2 directory search).
3466 ****************************************************************************/
3468 int reply_findclose(connection_struct *conn,
3469 char *inbuf,char *outbuf,int length,int bufsize)
3471 int outsize = 0;
3472 int dptr_num=SVALS(inbuf,smb_vwv0);
3473 START_PROFILE(SMBfindclose);
3475 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3477 dptr_close(&dptr_num);
3479 outsize = set_message(outbuf,0,0,True);
3481 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3483 END_PROFILE(SMBfindclose);
3484 return(outsize);
3487 /****************************************************************************
3488 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3489 ****************************************************************************/
3491 int reply_findnclose(connection_struct *conn,
3492 char *inbuf,char *outbuf,int length,int bufsize)
3494 int outsize = 0;
3495 int dptr_num= -1;
3496 START_PROFILE(SMBfindnclose);
3498 dptr_num = SVAL(inbuf,smb_vwv0);
3500 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3502 /* We never give out valid handles for a
3503 findnotifyfirst - so any dptr_num is ok here.
3504 Just ignore it. */
3506 outsize = set_message(outbuf,0,0,True);
3508 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3510 END_PROFILE(SMBfindnclose);
3511 return(outsize);
3514 /****************************************************************************
3515 Reply to a SMBtranss2 - just ignore it!
3516 ****************************************************************************/
3518 int reply_transs2(connection_struct *conn,
3519 char *inbuf,char *outbuf,int length,int bufsize)
3521 START_PROFILE(SMBtranss2);
3522 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3523 END_PROFILE(SMBtranss2);
3524 return(-1);
3527 /****************************************************************************
3528 Reply to a SMBtrans2.
3529 ****************************************************************************/
3531 int reply_trans2(connection_struct *conn,
3532 char *inbuf,char *outbuf,int length,int bufsize)
3534 int outsize = 0;
3535 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3536 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3537 #if 0
3538 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3539 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3540 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3541 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3542 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3543 int32 timeout = IVALS(inbuf,smb_timeout);
3544 #endif
3545 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3546 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3547 char *params = NULL, *data = NULL;
3548 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
3549 START_PROFILE(SMBtrans2);
3551 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3552 /* Queue this open message as we are the process of an
3553 * oplock break. */
3555 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3556 DEBUGADD(2,( "in oplock break state.\n"));
3558 push_oplock_pending_smb_message(inbuf, length);
3559 END_PROFILE(SMBtrans2);
3560 return -1;
3563 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3564 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3565 END_PROFILE(SMBtrans2);
3566 return ERROR_DOS(ERRSRV,ERRaccess);
3569 outsize = set_message(outbuf,0,0,True);
3571 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3572 is so as a sanity check */
3573 if (suwcnt != 1) {
3575 * Need to have rc=0 for ioctl to get job id for OS/2.
3576 * Network printing will fail if function is not successful.
3577 * Similar function in reply.c will be used if protocol
3578 * is LANMAN1.0 instead of LM1.2X002.
3579 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3580 * outbuf doesn't have to be set(only job id is used).
3582 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3583 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3584 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3585 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3586 } else {
3587 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
3588 DEBUG(2,("Transaction is %d\n",tran_call));
3589 END_PROFILE(SMBtrans2);
3590 ERROR_DOS(ERRDOS,ERRinvalidparam);
3594 /* Allocate the space for the maximum needed parameters and data */
3595 if (total_params > 0)
3596 params = (char *)malloc(total_params);
3597 if (total_data > 0)
3598 data = (char *)malloc(total_data);
3600 if ((total_params && !params) || (total_data && !data)) {
3601 DEBUG(2,("Out of memory in reply_trans2\n"));
3602 SAFE_FREE(params);
3603 SAFE_FREE(data);
3604 END_PROFILE(SMBtrans2);
3605 return ERROR_DOS(ERRDOS,ERRnomem);
3608 /* Copy the param and data bytes sent with this request into
3609 the params buffer */
3610 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3611 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3613 if (num_params > total_params || num_data > total_data)
3614 exit_server("invalid params in reply_trans2");
3616 if(params) {
3617 unsigned int psoff = SVAL(inbuf, smb_psoff);
3618 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
3619 goto bad_param;
3620 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
3621 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
3622 goto bad_param;
3623 memcpy( params, smb_base(inbuf) + psoff, num_params);
3625 if(data) {
3626 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
3627 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
3628 goto bad_param;
3629 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
3630 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
3631 goto bad_param;
3632 memcpy( data, smb_base(inbuf) + dsoff, num_data);
3635 srv_signing_trans_start(SVAL(inbuf,smb_mid));
3637 if(num_data_sofar < total_data || num_params_sofar < total_params) {
3638 /* We need to send an interim response then receive the rest
3639 of the parameter/data bytes */
3640 outsize = set_message(outbuf,0,0,True);
3641 srv_signing_trans_stop();
3642 if (!send_smb(smbd_server_fd(),outbuf))
3643 exit_server("reply_trans2: send_smb failed.");
3645 while (num_data_sofar < total_data ||
3646 num_params_sofar < total_params) {
3647 BOOL ret;
3648 unsigned int param_disp;
3649 unsigned int param_off;
3650 unsigned int data_disp;
3651 unsigned int data_off;
3653 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3656 * The sequence number for the trans reply is always
3657 * based on the last secondary received.
3660 srv_signing_trans_start(SVAL(inbuf,smb_mid));
3662 if ((ret &&
3663 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3664 outsize = set_message(outbuf,0,0,True);
3665 if(ret)
3666 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3667 else
3668 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3669 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3670 goto bad_param;
3673 /* Revise total_params and total_data in case
3674 they have changed downwards */
3675 if (SVAL(inbuf, smb_tpscnt) < total_params)
3676 total_params = SVAL(inbuf, smb_tpscnt);
3677 if (SVAL(inbuf, smb_tdscnt) < total_data)
3678 total_data = SVAL(inbuf, smb_tdscnt);
3680 num_params = SVAL(inbuf,smb_spscnt);
3681 param_off = SVAL(inbuf, smb_spsoff);
3682 param_disp = SVAL(inbuf, smb_spsdisp);
3683 num_params_sofar += num_params;
3685 num_data = SVAL(inbuf, smb_sdscnt);
3686 data_off = SVAL(inbuf, smb_sdsoff);
3687 data_disp = SVAL(inbuf, smb_sdsdisp);
3688 num_data_sofar += num_data;
3690 if (num_params_sofar > total_params || num_data_sofar > total_data)
3691 goto bad_param;
3693 if (num_params) {
3694 if (param_disp + num_params >= total_params)
3695 goto bad_param;
3696 if ((param_disp + num_params < param_disp) ||
3697 (param_disp + num_params < num_params))
3698 goto bad_param;
3699 if (param_disp > total_params)
3700 goto bad_param;
3701 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
3702 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
3703 goto bad_param;
3704 if (params + param_disp < params)
3705 goto bad_param;
3707 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
3709 if (num_data) {
3710 if (data_disp + num_data >= total_data)
3711 goto bad_param;
3712 if ((data_disp + num_data < data_disp) ||
3713 (data_disp + num_data < num_data))
3714 goto bad_param;
3715 if (data_disp > total_data)
3716 goto bad_param;
3717 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
3718 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
3719 goto bad_param;
3720 if (data + data_disp < data)
3721 goto bad_param;
3723 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
3728 if (Protocol >= PROTOCOL_NT1) {
3729 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
3732 /* Now we must call the relevant TRANS2 function */
3733 switch(tran_call) {
3734 case TRANSACT2_OPEN:
3735 START_PROFILE_NESTED(Trans2_open);
3736 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
3737 &params, total_params, &data, total_data);
3738 END_PROFILE_NESTED(Trans2_open);
3739 break;
3741 case TRANSACT2_FINDFIRST:
3742 START_PROFILE_NESTED(Trans2_findfirst);
3743 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3744 &params, total_params, &data, total_data);
3745 END_PROFILE_NESTED(Trans2_findfirst);
3746 break;
3748 case TRANSACT2_FINDNEXT:
3749 START_PROFILE_NESTED(Trans2_findnext);
3750 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
3751 &params, total_params, &data, total_data);
3752 END_PROFILE_NESTED(Trans2_findnext);
3753 break;
3755 case TRANSACT2_QFSINFO:
3756 START_PROFILE_NESTED(Trans2_qfsinfo);
3757 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3758 &params, total_params, &data, total_data);
3759 END_PROFILE_NESTED(Trans2_qfsinfo);
3760 break;
3762 #ifdef HAVE_SYS_QUOTAS
3763 case TRANSACT2_SETFSINFO:
3764 START_PROFILE_NESTED(Trans2_setfsinfo);
3765 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
3766 &params, total_params, &data, total_data);
3767 END_PROFILE_NESTED(Trans2_setfsinfo);
3768 break;
3769 #endif
3770 case TRANSACT2_QPATHINFO:
3771 case TRANSACT2_QFILEINFO:
3772 START_PROFILE_NESTED(Trans2_qpathinfo);
3773 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3774 &params, total_params, &data, total_data);
3775 END_PROFILE_NESTED(Trans2_qpathinfo);
3776 break;
3777 case TRANSACT2_SETPATHINFO:
3778 case TRANSACT2_SETFILEINFO:
3779 START_PROFILE_NESTED(Trans2_setpathinfo);
3780 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3781 &params, total_params, &data, total_data);
3782 END_PROFILE_NESTED(Trans2_setpathinfo);
3783 break;
3785 case TRANSACT2_FINDNOTIFYFIRST:
3786 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3787 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
3788 &params, total_params, &data, total_data);
3789 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3790 break;
3792 case TRANSACT2_FINDNOTIFYNEXT:
3793 START_PROFILE_NESTED(Trans2_findnotifynext);
3794 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
3795 &params, total_params, &data, total_data);
3796 END_PROFILE_NESTED(Trans2_findnotifynext);
3797 break;
3798 case TRANSACT2_MKDIR:
3799 START_PROFILE_NESTED(Trans2_mkdir);
3800 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3801 &params, total_params, &data, total_data);
3802 END_PROFILE_NESTED(Trans2_mkdir);
3803 break;
3805 case TRANSACT2_GET_DFS_REFERRAL:
3806 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3807 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3808 &params, total_params, &data, total_data);
3809 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3810 break;
3811 case TRANSACT2_IOCTL:
3812 START_PROFILE_NESTED(Trans2_ioctl);
3813 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3814 &params, total_params, &data, total_data);
3815 END_PROFILE_NESTED(Trans2_ioctl);
3816 break;
3817 default:
3818 /* Error in request */
3819 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3820 SAFE_FREE(params);
3821 SAFE_FREE(data);
3822 END_PROFILE(SMBtrans2);
3823 srv_signing_trans_stop();
3824 return ERROR_DOS(ERRSRV,ERRerror);
3827 /* As we do not know how many data packets will need to be
3828 returned here the various call_trans2xxxx calls
3829 must send their own. Thus a call_trans2xxx routine only
3830 returns a value other than -1 when it wants to send
3831 an error packet.
3834 srv_signing_trans_stop();
3836 SAFE_FREE(params);
3837 SAFE_FREE(data);
3838 END_PROFILE(SMBtrans2);
3839 return outsize; /* If a correct response was needed the
3840 call_trans2xxx calls have already sent
3841 it. If outsize != -1 then it is returning */
3843 bad_param:
3845 srv_signing_trans_stop();
3846 SAFE_FREE(params);
3847 SAFE_FREE(data);
3848 END_PROFILE(SMBtrans2);
3849 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);