must add one to the extra_data size to transfer the 0 string terminator.
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blobde65cda2d09b21d958a0a4359fef8efde3c0a294
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2001
6 Extensively modified by Andrew Tridgell, 1995
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
25 extern int Protocol;
26 extern BOOL case_sensitive;
27 extern int smb_read_error;
28 extern fstring local_machine;
29 extern int global_oplock_break;
30 extern uint32 global_client_caps;
31 extern pstring global_myname;
33 #define get_file_size(sbuf) (sbuf.st_size)
35 /* given a stat buffer return the allocated size on disk, taking into
36 account sparse files */
37 SMB_OFF_T get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
39 SMB_OFF_T ret;
40 #if defined(HAVE_STAT_ST_BLKSIZE) && defined(HAVE_STAT_ST_BLOCKS)
41 ret = sbuf->st_blksize * (SMB_OFF_T)sbuf->st_blocks;
42 #elif defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
43 ret = (SMB_OFF_T)STAT_ST_BLOCKSIZE * (SMB_OFF_T)sbuf->st_blocks;
44 #else
45 ret = get_file_size(*sbuf);
46 #endif
47 if (!ret && fsp && fsp->initial_allocation_size)
48 ret = fsp->initial_allocation_size;
49 ret = SMB_ROUNDUP(ret,SMB_ROUNDUP_ALLOCATION_SIZE);
50 return ret;
53 /****************************************************************************
54 Send the required number of replies back.
55 We assume all fields other than the data fields are
56 set correctly for the type of call.
57 HACK ! Always assumes smb_setup field is zero.
58 ****************************************************************************/
60 static int send_trans2_replies(char *outbuf,
61 int bufsize,
62 char *params,
63 int paramsize,
64 char *pdata,
65 int datasize)
67 /* As we are using a protocol > LANMAN1 then the max_send
68 variable must have been set in the sessetupX call.
69 This takes precedence over the max_xmit field in the
70 global struct. These different max_xmit variables should
71 be merged as this is now too confusing */
73 extern int max_send;
74 int data_to_send = datasize;
75 int params_to_send = paramsize;
76 int useable_space;
77 char *pp = params;
78 char *pd = pdata;
79 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
80 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
81 int data_alignment_offset = 0;
83 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
85 set_message(outbuf,10,0,True);
87 /* If there genuinely are no parameters or data to send just send the empty packet */
89 if(params_to_send == 0 && data_to_send == 0) {
90 if (!send_smb(smbd_server_fd(),outbuf))
91 exit_server("send_trans2_replies: send_smb failed.");
92 return 0;
95 /* When sending params and data ensure that both are nicely aligned */
96 /* Only do this alignment when there is also data to send - else
97 can cause NT redirector problems. */
99 if (((params_to_send % 4) != 0) && (data_to_send != 0))
100 data_alignment_offset = 4 - (params_to_send % 4);
102 /* Space is bufsize minus Netbios over TCP header minus SMB header */
103 /* The alignment_offset is to align the param bytes on an even byte
104 boundary. NT 4.0 Beta needs this to work correctly. */
106 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
108 /* useable_space can never be more than max_send minus the alignment offset. */
110 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
112 while (params_to_send || data_to_send) {
113 /* Calculate whether we will totally or partially fill this packet */
115 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
117 /* We can never send more than useable_space */
119 * Note that 'useable_space' does not include the alignment offsets,
120 * but we must include the alignment offsets in the calculation of
121 * the length of the data we send over the wire, as the alignment offsets
122 * are sent here. Fix from Marc_Jacobsen@hp.com.
125 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
127 set_message(outbuf, 10, total_sent_thistime, True);
129 /* Set total params and data to be sent */
130 SSVAL(outbuf,smb_tprcnt,paramsize);
131 SSVAL(outbuf,smb_tdrcnt,datasize);
133 /* Calculate how many parameters and data we can fit into
134 * this packet. Parameters get precedence
137 params_sent_thistime = MIN(params_to_send,useable_space);
138 data_sent_thistime = useable_space - params_sent_thistime;
139 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
141 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
143 /* smb_proff is the offset from the start of the SMB header to the
144 parameter bytes, however the first 4 bytes of outbuf are
145 the Netbios over TCP header. Thus use smb_base() to subtract
146 them from the calculation */
148 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
150 if(params_sent_thistime == 0)
151 SSVAL(outbuf,smb_prdisp,0);
152 else
153 /* Absolute displacement of param bytes sent in this packet */
154 SSVAL(outbuf,smb_prdisp,pp - params);
156 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
157 if(data_sent_thistime == 0) {
158 SSVAL(outbuf,smb_droff,0);
159 SSVAL(outbuf,smb_drdisp, 0);
160 } else {
161 /* The offset of the data bytes is the offset of the
162 parameter bytes plus the number of parameters being sent this time */
163 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
164 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
165 SSVAL(outbuf,smb_drdisp, pd - pdata);
168 /* Copy the param bytes into the packet */
170 if(params_sent_thistime)
171 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
173 /* Copy in the data bytes */
174 if(data_sent_thistime)
175 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
176 data_alignment_offset,pd,data_sent_thistime);
178 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
179 params_sent_thistime, data_sent_thistime, useable_space));
180 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
181 params_to_send, data_to_send, paramsize, datasize));
183 /* Send the packet */
184 if (!send_smb(smbd_server_fd(),outbuf))
185 exit_server("send_trans2_replies: send_smb failed.");
187 pp += params_sent_thistime;
188 pd += data_sent_thistime;
190 params_to_send -= params_sent_thistime;
191 data_to_send -= data_sent_thistime;
193 /* Sanity check */
194 if(params_to_send < 0 || data_to_send < 0) {
195 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
196 params_to_send, data_to_send));
197 return -1;
201 return 0;
204 /****************************************************************************
205 Reply to a TRANSACT2_OPEN.
206 ****************************************************************************/
208 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
209 char **pparams, int total_params, char **ppdata, int total_data)
211 char *params = *pparams;
212 int16 open_mode;
213 int16 open_attr;
214 BOOL oplock_request;
215 #if 0
216 BOOL return_additional_info;
217 int16 open_sattr;
218 time_t open_time;
219 #endif
220 int16 open_ofun;
221 int32 open_size;
222 char *pname;
223 pstring fname;
224 mode_t unixmode;
225 SMB_OFF_T size=0;
226 int fmode=0,mtime=0,rmode;
227 SMB_INO_T inode = 0;
228 SMB_STRUCT_STAT sbuf;
229 int smb_action = 0;
230 BOOL bad_path = False;
231 files_struct *fsp;
234 * Ensure we have enough parameters to perform the operation.
237 if (total_params < 29)
238 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
240 open_mode = SVAL(params, 2);
241 open_attr = SVAL(params,6);
242 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
243 #if 0
244 return_additional_info = BITSETW(params,0);
245 open_sattr = SVAL(params, 4);
246 open_time = make_unix_date3(params+8);
247 #endif
248 open_ofun = SVAL(params,12);
249 open_size = IVAL(params,14);
250 pname = &params[28];
252 srvstr_pull(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE);
254 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
255 fname,open_mode, open_attr, open_ofun, open_size));
257 if (IS_IPC(conn))
258 return(ERROR_DOS(ERRSRV,ERRaccess));
260 /* XXXX we need to handle passed times, sattr and flags */
262 unix_convert(fname,conn,0,&bad_path,&sbuf);
264 if (!check_name(fname,conn)) {
265 set_bad_path_error(errno, bad_path);
266 return(UNIXERROR(ERRDOS,ERRnoaccess));
269 unixmode = unix_mode(conn,open_attr | aARCH, fname);
271 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode,
272 oplock_request, &rmode,&smb_action);
274 if (!fsp) {
275 set_bad_path_error(errno, bad_path);
276 return(UNIXERROR(ERRDOS,ERRnoaccess));
279 size = get_file_size(sbuf);
280 fmode = dos_mode(conn,fname,&sbuf);
281 mtime = sbuf.st_mtime;
282 inode = sbuf.st_ino;
283 if (fmode & aDIR) {
284 close_file(fsp,False);
285 return(ERROR_DOS(ERRDOS,ERRnoaccess));
288 /* Realloc the size of parameters and data we will return */
289 params = Realloc(*pparams, 28);
290 if( params == NULL )
291 return(ERROR_DOS(ERRDOS,ERRnomem));
292 *pparams = params;
294 memset((char *)params,'\0',28);
295 SSVAL(params,0,fsp->fnum);
296 SSVAL(params,2,fmode);
297 put_dos_date2(params,4, mtime);
298 SIVAL(params,8, (uint32)size);
299 SSVAL(params,12,rmode);
301 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
302 smb_action |= EXTENDED_OPLOCK_GRANTED;
304 SSVAL(params,18,smb_action);
307 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
309 SIVAL(params,20,inode);
311 /* Send the required number of replies */
312 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
314 return -1;
317 /*********************************************************
318 Routine to check if a given string matches exactly.
319 as a special case a mask of "." does NOT match. That
320 is required for correct wildcard semantics
321 Case can be significant or not.
322 **********************************************************/
324 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
326 if (mask[0] == '.' && mask[1] == 0)
327 return False;
328 if (case_sig)
329 return strcmp(str,mask)==0;
330 return strcasecmp(str,mask) == 0;
333 /****************************************************************************
334 Return the filetype for UNIX extensions.
335 ****************************************************************************/
337 static uint32 unix_filetype(mode_t mode)
339 if(S_ISREG(mode))
340 return UNIX_TYPE_FILE;
341 else if(S_ISDIR(mode))
342 return UNIX_TYPE_DIR;
343 #ifdef S_ISLNK
344 else if(S_ISLNK(mode))
345 return UNIX_TYPE_SYMLINK;
346 #endif
347 #ifdef S_ISCHR
348 else if(S_ISCHR(mode))
349 return UNIX_TYPE_CHARDEV;
350 #endif
351 #ifdef S_ISBLK
352 else if(S_ISBLK(mode))
353 return UNIX_TYPE_BLKDEV;
354 #endif
355 #ifdef S_ISFIFO
356 else if(S_ISFIFO(mode))
357 return UNIX_TYPE_FIFO;
358 #endif
359 #ifdef S_ISSOCK
360 else if(S_ISSOCK(mode))
361 return UNIX_TYPE_SOCKET;
362 #endif
364 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
365 return UNIX_TYPE_UNKNOWN;
368 /****************************************************************************
369 Return the major devicenumber for UNIX extensions.
370 ****************************************************************************/
372 static uint32 unix_dev_major(SMB_DEV_T dev)
374 #if defined(HAVE_DEVICE_MAJOR_FN)
375 return (uint32)major(dev);
376 #else
377 return (uint32)(dev >> 8);
378 #endif
381 /****************************************************************************
382 Return the minor devicenumber for UNIX extensions.
383 ****************************************************************************/
385 static uint32 unix_dev_minor(SMB_DEV_T dev)
387 #if defined(HAVE_DEVICE_MINOR_FN)
388 return (uint32)minor(dev);
389 #else
390 return (uint32)(dev & 0xff);
391 #endif
394 /****************************************************************************
395 Map wire perms onto standard UNIX permissions. Obey share restrictions.
396 ****************************************************************************/
398 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
400 mode_t ret = 0;
402 if (perms == SMB_MODE_NO_CHANGE)
403 return pst->st_mode;
405 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
406 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
407 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
408 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
409 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
410 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
411 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
412 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
413 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
414 #ifdef S_ISVTX
415 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
416 #endif
417 #ifdef S_ISGID
418 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
419 #endif
420 #ifdef S_ISUID
421 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
422 #endif
424 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
425 ret &= lp_dir_mask(SNUM(conn));
426 /* Add in force bits */
427 ret |= lp_force_dir_mode(SNUM(conn));
428 } else {
429 /* Apply mode mask */
430 ret &= lp_create_mask(SNUM(conn));
431 /* Add in force bits */
432 ret |= lp_force_create_mode(SNUM(conn));
435 return ret;
438 /****************************************************************************
439 checks for SMB_TIME_NO_CHANGE and if not found
440 calls interpret_long_date
441 ****************************************************************************/
442 time_t interpret_long_unix_date(char *p)
444 DEBUG(1,("interpret_long_unix_date\n"));
445 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
446 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
447 return -1;
448 } else {
449 return interpret_long_date(p);
453 /****************************************************************************
454 Get a level dependent lanman2 dir entry.
455 ****************************************************************************/
457 static BOOL get_lanman2_dir_entry(connection_struct *conn,
458 void *inbuf, void *outbuf,
459 char *path_mask,int dirtype,int info_level,
460 int requires_resume_key,
461 BOOL dont_descend,char **ppdata,
462 char *base_data, int space_remaining,
463 BOOL *out_of_space, BOOL *got_exact_match,
464 int *last_name_off)
466 char *dname;
467 BOOL found = False;
468 SMB_STRUCT_STAT sbuf;
469 pstring mask;
470 pstring pathreal;
471 pstring fname;
472 char *p, *q, *pdata = *ppdata;
473 uint32 reskey=0;
474 int prev_dirpos=0;
475 int mode=0;
476 SMB_OFF_T file_size = 0;
477 SMB_OFF_T allocation_size = 0;
478 uint32 len;
479 time_t mdate=0, adate=0, cdate=0;
480 char *nameptr;
481 BOOL was_8_3;
482 int nt_extmode; /* Used for NT connections instead of mode */
483 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
485 *fname = 0;
486 *out_of_space = False;
487 *got_exact_match = False;
489 if (!conn->dirptr)
490 return(False);
492 p = strrchr_m(path_mask,'/');
493 if(p != NULL) {
494 if(p[1] == '\0')
495 pstrcpy(mask,"*.*");
496 else
497 pstrcpy(mask, p+1);
498 } else
499 pstrcpy(mask, path_mask);
501 while (!found) {
502 BOOL got_match;
504 /* Needed if we run out of space */
505 prev_dirpos = TellDir(conn->dirptr);
506 dname = ReadDirName(conn->dirptr);
509 * Due to bugs in NT client redirectors we are not using
510 * resume keys any more - set them to zero.
511 * Check out the related comments in findfirst/findnext.
512 * JRA.
515 reskey = 0;
517 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
518 (long)conn->dirptr,TellDir(conn->dirptr)));
520 if (!dname)
521 return(False);
523 pstrcpy(fname,dname);
525 if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
526 got_match = mask_match(fname, mask, case_sensitive);
528 if(!got_match && !mangle_is_8_3(fname, False)) {
531 * It turns out that NT matches wildcards against
532 * both long *and* short names. This may explain some
533 * of the wildcard wierdness from old DOS clients
534 * that some people have been seeing.... JRA.
537 pstring newname;
538 pstrcpy( newname, fname);
539 mangle_map( newname, True, False, SNUM(conn));
540 if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
541 got_match = mask_match(newname, mask, case_sensitive);
544 if(got_match) {
545 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
546 if (dont_descend && !isdots)
547 continue;
549 pstrcpy(pathreal,conn->dirpath);
550 if(needslash)
551 pstrcat(pathreal,"/");
552 pstrcat(pathreal,dname);
554 if (INFO_LEVEL_IS_UNIX(info_level)) {
555 if (vfs_lstat(conn,pathreal,&sbuf) != 0) {
556 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
557 pathreal,strerror(errno)));
558 continue;
560 } else if (vfs_stat(conn,pathreal,&sbuf) != 0) {
562 /* Needed to show the msdfs symlinks as
563 * directories */
565 if(lp_host_msdfs() &&
566 lp_msdfs_root(SNUM(conn)) &&
567 is_msdfs_link(conn, pathreal, NULL, NULL,
568 &sbuf)) {
570 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
571 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
573 } else {
575 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
576 pathreal,strerror(errno)));
577 continue;
581 mode = dos_mode(conn,pathreal,&sbuf);
583 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
584 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
585 continue;
588 file_size = get_file_size(sbuf);
589 allocation_size = get_allocation_size(NULL,&sbuf);
590 mdate = sbuf.st_mtime;
591 adate = sbuf.st_atime;
592 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
594 if (lp_dos_filetime_resolution(SNUM(conn))) {
595 cdate &= ~1;
596 mdate &= ~1;
597 adate &= ~1;
600 if(mode & aDIR)
601 file_size = 0;
603 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
605 found = True;
609 mangle_map(fname,False,True,SNUM(conn));
611 p = pdata;
612 nameptr = p;
614 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
616 switch (info_level) {
617 case SMB_INFO_STANDARD:
618 if(requires_resume_key) {
619 SIVAL(p,0,reskey);
620 p += 4;
622 put_dos_date2(p,l1_fdateCreation,cdate);
623 put_dos_date2(p,l1_fdateLastAccess,adate);
624 put_dos_date2(p,l1_fdateLastWrite,mdate);
625 SIVAL(p,l1_cbFile,(uint32)file_size);
626 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
627 SSVAL(p,l1_attrFile,mode);
628 p += l1_achName;
629 nameptr = p;
630 p += align_string(outbuf, p, 0);
631 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
632 SCVAL(nameptr, -1, len);
633 p += len;
634 break;
636 case SMB_INFO_QUERY_EA_SIZE:
637 if(requires_resume_key) {
638 SIVAL(p,0,reskey);
639 p += 4;
641 put_dos_date2(p,l2_fdateCreation,cdate);
642 put_dos_date2(p,l2_fdateLastAccess,adate);
643 put_dos_date2(p,l2_fdateLastWrite,mdate);
644 SIVAL(p,l2_cbFile,(uint32)file_size);
645 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
646 SSVAL(p,l2_attrFile,mode);
647 SIVAL(p,l2_cbList,0); /* No extended attributes */
648 p += l2_achName;
649 nameptr = p;
650 len = srvstr_push(outbuf, p, fname, -1, STR_NOALIGN);
651 SCVAL(p, -1, len);
652 p += len;
653 *p++ = 0; /* craig from unisys pointed out we need this */
654 break;
656 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
657 was_8_3 = mangle_is_8_3(fname, True);
658 p += 4;
659 SIVAL(p,0,reskey); p += 4;
660 put_long_date(p,cdate); p += 8;
661 put_long_date(p,adate); p += 8;
662 put_long_date(p,mdate); p += 8;
663 put_long_date(p,mdate); p += 8;
664 SOFF_T(p,0,file_size);
665 SOFF_T(p,8,allocation_size);
666 p += 16;
667 SIVAL(p,0,nt_extmode); p += 4;
668 q = p; p += 4;
669 SIVAL(p,0,0); p += 4;
670 /* Clear the short name buffer. This is
671 * IMPORTANT as not doing so will trigger
672 * a Win2k client bug. JRA.
674 memset(p,'\0',26);
675 if (!was_8_3) {
676 pstring mangled_name;
677 pstrcpy(mangled_name, fname);
678 mangle_map(mangled_name,True,True,SNUM(conn));
679 mangled_name[12] = 0;
680 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER);
681 SSVAL(p, 0, len);
682 } else {
683 SSVAL(p,0,0);
684 *(p+2) = 0;
686 p += 2 + 24;
687 len = srvstr_push(outbuf, p, fname, -1, 0);
688 SIVAL(q,0,len);
689 p += len;
690 len = PTR_DIFF(p, pdata);
691 len = (len + 3) & ~3;
692 SIVAL(pdata,0,len);
693 p = pdata + len;
694 break;
696 case SMB_FIND_FILE_DIRECTORY_INFO:
697 p += 4;
698 SIVAL(p,0,reskey); p += 4;
699 put_long_date(p,cdate); p += 8;
700 put_long_date(p,adate); p += 8;
701 put_long_date(p,mdate); p += 8;
702 put_long_date(p,mdate); p += 8;
703 SOFF_T(p,0,file_size);
704 SOFF_T(p,8,allocation_size);
705 p += 16;
706 SIVAL(p,0,nt_extmode); p += 4;
707 p += 4;
708 len = srvstr_push(outbuf, p, fname, -1, 0);
709 SIVAL(p, -4, len);
710 p += len;
711 len = PTR_DIFF(p, pdata);
712 len = (len + 3) & ~3;
713 SIVAL(pdata,0,len);
714 p = pdata + len;
715 break;
717 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
718 p += 4;
719 SIVAL(p,0,reskey); p += 4;
720 put_long_date(p,cdate); p += 8;
721 put_long_date(p,adate); p += 8;
722 put_long_date(p,mdate); p += 8;
723 put_long_date(p,mdate); p += 8;
724 SOFF_T(p,0,file_size);
725 SOFF_T(p,8,allocation_size);
726 p += 16;
727 SIVAL(p,0,nt_extmode); p += 4;
728 p += 4;
729 SIVAL(p,0,0); p += 4;
731 len = srvstr_push(outbuf, p, fname, -1, 0);
732 SIVAL(p, -4, len);
733 p += len;
735 len = PTR_DIFF(p, pdata);
736 len = (len + 3) & ~3;
737 SIVAL(pdata,0,len);
738 p = pdata + len;
739 break;
741 case SMB_FIND_FILE_NAMES_INFO:
742 p += 4;
743 SIVAL(p,0,reskey); p += 4;
744 p += 4;
745 /* this must *not* be null terminated or w2k gets in a loop trying to set an
746 acl on a dir (tridge) */
747 len = srvstr_push(outbuf, p, fname, -1, 0);
748 SIVAL(p, -4, len);
749 p += len;
750 len = PTR_DIFF(p, pdata);
751 len = (len + 3) & ~3;
752 SIVAL(pdata,0,len);
753 p = pdata + len;
754 break;
756 /* CIFS UNIX Extension. */
758 case SMB_FIND_FILE_UNIX:
759 p+= 4;
760 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
762 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
763 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
764 p+= 8;
766 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
767 p+= 8;
769 put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */
770 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
771 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
772 p+= 24;
774 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
775 SIVAL(p,4,0);
776 p+= 8;
778 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
779 SIVAL(p,4,0);
780 p+= 8;
782 SIVAL(p,0,unix_filetype(sbuf.st_mode));
783 p+= 4;
785 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
786 SIVAL(p,4,0);
787 p+= 8;
789 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
790 SIVAL(p,4,0);
791 p+= 8;
793 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
794 p+= 8;
796 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
797 SIVAL(p,4,0);
798 p+= 8;
800 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
801 SIVAL(p,4,0);
802 p+= 8;
804 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
805 p += len;
807 len = PTR_DIFF(p, pdata);
808 len = (len + 3) & ~3;
809 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
810 p = pdata + len;
811 /* End of SMB_QUERY_FILE_UNIX_BASIC */
813 break;
815 default:
816 return(False);
820 if (PTR_DIFF(p,pdata) > space_remaining) {
821 /* Move the dirptr back to prev_dirpos */
822 SeekDir(conn->dirptr, prev_dirpos);
823 *out_of_space = True;
824 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
825 return False; /* Not finished - just out of space */
828 /* Setup the last_filename pointer, as an offset from base_data */
829 *last_name_off = PTR_DIFF(nameptr,base_data);
830 /* Advance the data pointer to the next slot */
831 *ppdata = p;
833 return(found);
836 /****************************************************************************
837 Reply to a TRANS2_FINDFIRST.
838 ****************************************************************************/
840 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
841 char **pparams, int total_params, char **ppdata, int total_data)
843 /* We must be careful here that we don't return more than the
844 allowed number of data bytes. If this means returning fewer than
845 maxentries then so be it. We assume that the redirector has
846 enough room for the fixed number of parameter bytes it has
847 requested. */
848 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
849 char *params = *pparams;
850 char *pdata = *ppdata;
851 int dirtype = SVAL(params,0);
852 int maxentries = SVAL(params,2);
853 BOOL close_after_first = BITSETW(params+4,0);
854 BOOL close_if_end = BITSETW(params+4,1);
855 BOOL requires_resume_key = BITSETW(params+4,2);
856 int info_level = SVAL(params,6);
857 pstring directory;
858 pstring mask;
859 char *p, *wcard;
860 int last_name_off=0;
861 int dptr_num = -1;
862 int numentries = 0;
863 int i;
864 BOOL finished = False;
865 BOOL dont_descend = False;
866 BOOL out_of_space = False;
867 int space_remaining;
868 BOOL bad_path = False;
869 SMB_STRUCT_STAT sbuf;
871 if (total_params < 12)
872 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
874 *directory = *mask = 0;
876 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
877 close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
878 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
879 info_level, max_data_bytes));
881 switch (info_level) {
882 case SMB_INFO_STANDARD:
883 case SMB_INFO_QUERY_EA_SIZE:
884 case SMB_FIND_FILE_DIRECTORY_INFO:
885 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
886 case SMB_FIND_FILE_NAMES_INFO:
887 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
888 break;
889 case SMB_FIND_FILE_UNIX:
890 if (!lp_unix_extensions())
891 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
892 break;
893 default:
894 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
897 srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE);
899 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
901 unix_convert(directory,conn,0,&bad_path,&sbuf);
902 if(!check_name(directory,conn)) {
903 set_bad_path_error(errno, bad_path);
904 return(UNIXERROR(ERRDOS,ERRbadpath));
907 p = strrchr_m(directory,'/');
908 if(p == NULL) {
909 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
910 if((directory[0] == '.') && (directory[1] == '\0'))
911 pstrcpy(mask,"*");
912 else
913 pstrcpy(mask,directory);
914 pstrcpy(directory,"./");
915 } else {
916 pstrcpy(mask,p+1);
917 *p = 0;
920 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
922 pdata = Realloc(*ppdata, max_data_bytes + 1024);
923 if( pdata == NULL )
924 return(ERROR_DOS(ERRDOS,ERRnomem));
926 *ppdata = pdata;
927 memset((char *)pdata,'\0',max_data_bytes + 1024);
929 /* Realloc the params space */
930 params = Realloc(*pparams, 10);
931 if (params == NULL)
932 return ERROR_DOS(ERRDOS,ERRnomem);
933 *pparams = params;
935 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
936 if (dptr_num < 0)
937 return(UNIXERROR(ERRDOS,ERRbadfile));
939 /* Save the wildcard match and attribs we are using on this directory -
940 needed as lanman2 assumes these are being saved between calls */
942 if(!(wcard = strdup(mask))) {
943 dptr_close(&dptr_num);
944 return ERROR_DOS(ERRDOS,ERRnomem);
947 dptr_set_wcard(dptr_num, wcard);
948 dptr_set_attr(dptr_num, dirtype);
950 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
952 /* We don't need to check for VOL here as this is returned by
953 a different TRANS2 call. */
955 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
956 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
957 dont_descend = True;
959 p = pdata;
960 space_remaining = max_data_bytes;
961 out_of_space = False;
963 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
964 BOOL got_exact_match = False;
966 /* this is a heuristic to avoid seeking the dirptr except when
967 absolutely necessary. It allows for a filename of about 40 chars */
968 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
969 out_of_space = True;
970 finished = False;
971 } else {
972 finished = !get_lanman2_dir_entry(conn,
973 inbuf, outbuf,
974 mask,dirtype,info_level,
975 requires_resume_key,dont_descend,
976 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
977 &last_name_off);
980 if (finished && out_of_space)
981 finished = False;
983 if (!finished && !out_of_space)
984 numentries++;
987 * As an optimisation if we know we aren't looking
988 * for a wildcard name (ie. the name matches the wildcard exactly)
989 * then we can finish on any (first) match.
990 * This speeds up large directory searches. JRA.
993 if(got_exact_match)
994 finished = True;
996 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
999 /* Check if we can close the dirptr */
1000 if(close_after_first || (finished && close_if_end)) {
1001 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1002 dptr_close(&dptr_num);
1006 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1007 * from observation of NT.
1010 if(numentries == 0) {
1011 dptr_close(&dptr_num);
1012 return ERROR_DOS(ERRDOS,ERRbadfile);
1015 /* At this point pdata points to numentries directory entries. */
1017 /* Set up the return parameter block */
1018 SSVAL(params,0,dptr_num);
1019 SSVAL(params,2,numentries);
1020 SSVAL(params,4,finished);
1021 SSVAL(params,6,0); /* Never an EA error */
1022 SSVAL(params,8,last_name_off);
1024 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1026 if ((! *directory) && dptr_path(dptr_num))
1027 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1029 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1030 smb_fn_name(CVAL(inbuf,smb_com)),
1031 mask, directory, dirtype, numentries ) );
1034 * Force a name mangle here to ensure that the
1035 * mask as an 8.3 name is top of the mangled cache.
1036 * The reasons for this are subtle. Don't remove
1037 * this code unless you know what you are doing
1038 * (see PR#13758). JRA.
1041 if(!mangle_is_8_3_wildcards( mask, False))
1042 mangle_map(mask, True, True, SNUM(conn));
1044 return(-1);
1047 /****************************************************************************
1048 Reply to a TRANS2_FINDNEXT.
1049 ****************************************************************************/
1051 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1052 char **pparams, int total_params, char **ppdata, int total_data)
1054 /* We must be careful here that we don't return more than the
1055 allowed number of data bytes. If this means returning fewer than
1056 maxentries then so be it. We assume that the redirector has
1057 enough room for the fixed number of parameter bytes it has
1058 requested. */
1059 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1060 char *params = *pparams;
1061 char *pdata = *ppdata;
1062 int dptr_num = SVAL(params,0);
1063 int maxentries = SVAL(params,2);
1064 uint16 info_level = SVAL(params,4);
1065 uint32 resume_key = IVAL(params,6);
1066 BOOL close_after_request = BITSETW(params+10,0);
1067 BOOL close_if_end = BITSETW(params+10,1);
1068 BOOL requires_resume_key = BITSETW(params+10,2);
1069 BOOL continue_bit = BITSETW(params+10,3);
1070 pstring resume_name;
1071 pstring mask;
1072 pstring directory;
1073 char *p;
1074 uint16 dirtype;
1075 int numentries = 0;
1076 int i, last_name_off=0;
1077 BOOL finished = False;
1078 BOOL dont_descend = False;
1079 BOOL out_of_space = False;
1080 int space_remaining;
1082 if (total_params < 12)
1083 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1085 *mask = *directory = *resume_name = 0;
1087 srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE);
1089 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1090 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1091 resume_key = %d resume name = %s continue=%d level = %d\n",
1092 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1093 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1095 switch (info_level) {
1096 case SMB_INFO_STANDARD:
1097 case SMB_INFO_QUERY_EA_SIZE:
1098 case SMB_FIND_FILE_DIRECTORY_INFO:
1099 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1100 case SMB_FIND_FILE_NAMES_INFO:
1101 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1102 break;
1103 case SMB_FIND_FILE_UNIX:
1104 if (!lp_unix_extensions())
1105 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1106 break;
1107 default:
1108 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1111 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1112 if(pdata == NULL)
1113 return ERROR_DOS(ERRDOS,ERRnomem);
1115 *ppdata = pdata;
1116 memset((char *)pdata,'\0',max_data_bytes + 1024);
1118 /* Realloc the params space */
1119 params = Realloc(*pparams, 6*SIZEOFWORD);
1120 if( params == NULL )
1121 return ERROR_DOS(ERRDOS,ERRnomem);
1123 *pparams = params;
1125 /* Check that the dptr is valid */
1126 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1127 return ERROR_DOS(ERRDOS,ERRnofiles);
1129 string_set(&conn->dirpath,dptr_path(dptr_num));
1131 /* Get the wildcard mask from the dptr */
1132 if((p = dptr_wcard(dptr_num))== NULL) {
1133 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1134 return ERROR_DOS(ERRDOS,ERRnofiles);
1137 pstrcpy(mask, p);
1138 pstrcpy(directory,conn->dirpath);
1140 /* Get the attr mask from the dptr */
1141 dirtype = dptr_attr(dptr_num);
1143 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1144 dptr_num, mask, dirtype,
1145 (long)conn->dirptr,
1146 TellDir(conn->dirptr)));
1148 /* We don't need to check for VOL here as this is returned by
1149 a different TRANS2 call. */
1151 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1152 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1153 dont_descend = True;
1155 p = pdata;
1156 space_remaining = max_data_bytes;
1157 out_of_space = False;
1160 * Seek to the correct position. We no longer use the resume key but
1161 * depend on the last file name instead.
1164 if(requires_resume_key && *resume_name && !continue_bit) {
1167 * Fix for NT redirector problem triggered by resume key indexes
1168 * changing between directory scans. We now return a resume key of 0
1169 * and instead look for the filename to continue from (also given
1170 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1171 * findfirst/findnext (as is usual) then the directory pointer
1172 * should already be at the correct place. Check this by scanning
1173 * backwards looking for an exact (ie. case sensitive) filename match.
1174 * If we get to the beginning of the directory and haven't found it then scan
1175 * forwards again looking for a match. JRA.
1178 int current_pos, start_pos;
1179 char *dname = NULL;
1180 void *dirptr = conn->dirptr;
1181 start_pos = TellDir(dirptr);
1182 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1183 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1185 SeekDir(dirptr, current_pos);
1186 dname = ReadDirName(dirptr);
1189 * Remember, mangle_map is called by
1190 * get_lanman2_dir_entry(), so the resume name
1191 * could be mangled. Ensure we do the same
1192 * here.
1195 if(dname != NULL)
1196 mangle_map( dname, False, True, SNUM(conn));
1198 if(dname && strcsequal( resume_name, dname)) {
1199 SeekDir(dirptr, current_pos+1);
1200 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1201 break;
1206 * Scan forward from start if not found going backwards.
1209 if(current_pos < 0) {
1210 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1211 SeekDir(dirptr, start_pos);
1212 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1215 * Remember, mangle_map is called by
1216 * get_lanman2_dir_entry(), so the resume name
1217 * could be mangled. Ensure we do the same
1218 * here.
1221 if(dname != NULL)
1222 mangle_map( dname, False, True, SNUM(conn));
1224 if(dname && strcsequal( resume_name, dname)) {
1225 SeekDir(dirptr, current_pos+1);
1226 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1227 break;
1229 } /* end for */
1230 } /* end if current_pos */
1231 } /* end if requires_resume_key && !continue_bit */
1233 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1234 BOOL got_exact_match = False;
1236 /* this is a heuristic to avoid seeking the dirptr except when
1237 absolutely necessary. It allows for a filename of about 40 chars */
1238 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1239 out_of_space = True;
1240 finished = False;
1241 } else {
1242 finished = !get_lanman2_dir_entry(conn,
1243 inbuf, outbuf,
1244 mask,dirtype,info_level,
1245 requires_resume_key,dont_descend,
1246 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1247 &last_name_off);
1250 if (finished && out_of_space)
1251 finished = False;
1253 if (!finished && !out_of_space)
1254 numentries++;
1257 * As an optimisation if we know we aren't looking
1258 * for a wildcard name (ie. the name matches the wildcard exactly)
1259 * then we can finish on any (first) match.
1260 * This speeds up large directory searches. JRA.
1263 if(got_exact_match)
1264 finished = True;
1266 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1269 /* Check if we can close the dirptr */
1270 if(close_after_request || (finished && close_if_end)) {
1271 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1272 dptr_close(&dptr_num); /* This frees up the saved mask */
1276 /* Set up the return parameter block */
1277 SSVAL(params,0,numentries);
1278 SSVAL(params,2,finished);
1279 SSVAL(params,4,0); /* Never an EA error */
1280 SSVAL(params,6,last_name_off);
1282 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1284 if ((! *directory) && dptr_path(dptr_num))
1285 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1287 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1288 smb_fn_name(CVAL(inbuf,smb_com)),
1289 mask, directory, dirtype, numentries ) );
1291 return(-1);
1294 /****************************************************************************
1295 Reply to a TRANS2_QFSINFO (query filesystem info).
1296 ****************************************************************************/
1298 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1299 int length, int bufsize,
1300 char **pparams, int total_params, char **ppdata, int total_data)
1302 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1303 char *pdata = *ppdata;
1304 char *params = *pparams;
1305 uint16 info_level = SVAL(params,0);
1306 int data_len, len;
1307 SMB_STRUCT_STAT st;
1308 char *vname = volume_label(SNUM(conn));
1309 int snum = SNUM(conn);
1310 char *fstype = lp_fstype(SNUM(conn));
1312 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1314 if(vfs_stat(conn,".",&st)!=0) {
1315 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1316 return ERROR_DOS(ERRSRV,ERRinvdevice);
1319 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1320 if ( pdata == NULL )
1321 return ERROR_DOS(ERRDOS,ERRnomem);
1323 *ppdata = pdata;
1324 memset((char *)pdata,'\0',max_data_bytes + 1024);
1326 switch (info_level) {
1327 case SMB_INFO_ALLOCATION:
1329 SMB_BIG_UINT dfree,dsize,bsize;
1330 data_len = 18;
1331 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1332 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1333 SIVAL(pdata,l1_cSectorUnit,bsize/512);
1334 SIVAL(pdata,l1_cUnit,dsize);
1335 SIVAL(pdata,l1_cUnitAvail,dfree);
1336 SSVAL(pdata,l1_cbSector,512);
1337 DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
1338 (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
1339 (unsigned int)dfree, 512));
1340 break;
1343 case SMB_INFO_VOLUME:
1344 /* Return volume name */
1346 * Add volume serial number - hash of a combination of
1347 * the called hostname and the service name.
1349 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1350 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_TERMINATE);
1351 SCVAL(pdata,l2_vol_cch,len);
1352 data_len = l2_vol_szVolLabel + len;
1353 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1354 (unsigned)st.st_ctime, len, vname));
1355 break;
1357 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1358 case SMB_FS_ATTRIBUTE_INFORMATION:
1360 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1361 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */
1362 SIVAL(pdata,4,255); /* Max filename component length */
1363 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1364 and will think we can't do long filenames */
1365 len = srvstr_push(outbuf, pdata+12, fstype, -1, 0);
1366 SIVAL(pdata,8,len);
1367 data_len = 12 + len;
1368 break;
1370 case SMB_QUERY_FS_LABEL_INFO:
1371 case SMB_FS_LABEL_INFORMATION:
1372 len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE);
1373 data_len = 4 + len;
1374 SIVAL(pdata,0,len);
1375 break;
1377 case SMB_QUERY_FS_VOLUME_INFO:
1378 case SMB_FS_VOLUME_INFORMATION:
1381 * Add volume serial number - hash of a combination of
1382 * the called hostname and the service name.
1384 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1385 (str_checksum(local_machine)<<16));
1387 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE);
1388 SIVAL(pdata,12,len);
1389 data_len = 18+len;
1390 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1391 (int)strlen(vname),vname, lp_servicename(snum)));
1392 break;
1394 case SMB_QUERY_FS_SIZE_INFO:
1395 case SMB_FS_SIZE_INFORMATION:
1397 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1398 data_len = 24;
1399 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1400 block_size = lp_block_size(snum);
1401 if (bsize < block_size) {
1402 SMB_BIG_UINT factor = block_size/bsize;
1403 bsize = block_size;
1404 dsize /= factor;
1405 dfree /= factor;
1407 if (bsize > block_size) {
1408 SMB_BIG_UINT factor = bsize/block_size;
1409 bsize = block_size;
1410 dsize *= factor;
1411 dfree *= factor;
1413 bytes_per_sector = 512;
1414 sectors_per_unit = bsize/bytes_per_sector;
1415 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1416 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1417 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1418 SBIG_UINT(pdata,0,dsize);
1419 SBIG_UINT(pdata,8,dfree);
1420 SIVAL(pdata,16,sectors_per_unit);
1421 SIVAL(pdata,20,bytes_per_sector);
1422 break;
1425 case SMB_FS_FULL_SIZE_INFORMATION:
1427 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1428 data_len = 32;
1429 conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
1430 block_size = lp_block_size(snum);
1431 if (bsize < block_size) {
1432 SMB_BIG_UINT factor = block_size/bsize;
1433 bsize = block_size;
1434 dsize /= factor;
1435 dfree /= factor;
1437 if (bsize > block_size) {
1438 SMB_BIG_UINT factor = bsize/block_size;
1439 bsize = block_size;
1440 dsize *= factor;
1441 dfree *= factor;
1443 bytes_per_sector = 512;
1444 sectors_per_unit = bsize/bytes_per_sector;
1445 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1446 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1447 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1448 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1449 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1450 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1451 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1452 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1453 break;
1456 case SMB_QUERY_FS_DEVICE_INFO:
1457 case SMB_FS_DEVICE_INFORMATION:
1458 data_len = 8;
1459 SIVAL(pdata,0,0); /* dev type */
1460 SIVAL(pdata,4,0); /* characteristics */
1461 break;
1463 case SMB_FS_OBJECTID_INFORMATION:
1464 data_len = 64;
1465 break;
1468 * Query the version and capabilities of the CIFS UNIX extensions
1469 * in use.
1472 case SMB_QUERY_CIFS_UNIX_INFO:
1473 if (!lp_unix_extensions())
1474 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1475 data_len = 12;
1476 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
1477 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
1478 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
1479 break;
1481 case SMB_MAC_QUERY_FS_INFO:
1483 * Thursby MAC extension... ONLY on NTFS filesystems
1484 * once we do streams then we don't need this
1486 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
1487 data_len = 88;
1488 SIVAL(pdata,84,0x100); /* Don't support mac... */
1489 break;
1491 /* drop through */
1492 default:
1493 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1497 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
1499 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
1501 return -1;
1504 /****************************************************************************
1505 Reply to a TRANS2_SETFSINFO (set filesystem info).
1506 ****************************************************************************/
1508 static int call_trans2setfsinfo(connection_struct *conn,
1509 char *inbuf, char *outbuf, int length, int bufsize,
1510 char **pparams, int total_params, char **ppdata, int total_data)
1512 /* Just say yes we did it - there is nothing that
1513 can be set here so it doesn't matter. */
1514 int outsize;
1515 DEBUG(3,("call_trans2setfsinfo\n"));
1517 if (!CAN_WRITE(conn))
1518 return ERROR_DOS(ERRSRV,ERRaccess);
1520 outsize = set_message(outbuf,10,0,True);
1522 return outsize;
1525 /****************************************************************************
1526 * Utility function to set bad path error.
1527 ****************************************************************************/
1529 NTSTATUS set_bad_path_error(int err, BOOL bad_path)
1531 if((err == ENOENT) && bad_path) {
1532 unix_ERR_class = ERRDOS;
1533 unix_ERR_code = ERRbadpath;
1534 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1536 return NT_STATUS_OK;
1539 /****************************************************************************
1540 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
1541 file name or file id).
1542 ****************************************************************************/
1544 static int call_trans2qfilepathinfo(connection_struct *conn,
1545 char *inbuf, char *outbuf, int length,
1546 int bufsize,
1547 char **pparams, int total_params, char **ppdata, int total_data)
1549 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1550 char *params = *pparams;
1551 char *pdata = *ppdata;
1552 uint16 tran_call = SVAL(inbuf, smb_setup0);
1553 uint16 info_level;
1554 int mode=0;
1555 SMB_OFF_T file_size=0;
1556 SMB_OFF_T allocation_size=0;
1557 unsigned int data_size;
1558 SMB_STRUCT_STAT sbuf;
1559 pstring fname, dos_fname;
1560 char *fullpathname;
1561 char *base_name;
1562 char *p;
1563 SMB_OFF_T pos = 0;
1564 BOOL bad_path = False;
1565 BOOL delete_pending = False;
1566 int len;
1567 time_t c_time;
1568 files_struct *fsp = NULL;
1570 if (!params)
1571 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1573 if (tran_call == TRANSACT2_QFILEINFO) {
1574 if (total_params < 4)
1575 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1577 fsp = file_fsp(params,0);
1578 info_level = SVAL(params,2);
1580 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
1582 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
1584 * This is actually a QFILEINFO on a directory
1585 * handle (returned from an NT SMB). NT5.0 seems
1586 * to do this call. JRA.
1588 pstrcpy(fname, fsp->fsp_name);
1589 unix_convert(fname,conn,0,&bad_path,&sbuf);
1590 if (!check_name(fname,conn)) {
1591 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1592 set_bad_path_error(errno, bad_path);
1593 return(UNIXERROR(ERRDOS,ERRbadpath));
1596 if (INFO_LEVEL_IS_UNIX(info_level)) {
1597 /* Always do lstat for UNIX calls. */
1598 if (vfs_lstat(conn,fname,&sbuf)) {
1599 DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
1600 set_bad_path_error(errno, bad_path);
1601 return(UNIXERROR(ERRDOS,ERRbadpath));
1603 } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
1604 DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
1605 set_bad_path_error(errno, bad_path);
1606 return(UNIXERROR(ERRDOS,ERRbadpath));
1609 delete_pending = fsp->directory_delete_on_close;
1610 } else {
1612 * Original code - this is an open file.
1614 CHECK_FSP(fsp,conn);
1616 pstrcpy(fname, fsp->fsp_name);
1617 if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) {
1618 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
1619 return(UNIXERROR(ERRDOS,ERRbadfid));
1621 if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1)
1622 return(UNIXERROR(ERRDOS,ERRnoaccess));
1624 delete_pending = fsp->delete_on_close;
1626 } else {
1627 /* qpathinfo */
1628 if (total_params < 6)
1629 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1631 info_level = SVAL(params,0);
1633 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
1635 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
1637 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1639 unix_convert(fname,conn,0,&bad_path,&sbuf);
1640 if (!check_name(fname,conn)) {
1641 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
1642 set_bad_path_error(errno, bad_path);
1643 return(UNIXERROR(ERRDOS,ERRbadpath));
1646 if (INFO_LEVEL_IS_UNIX(info_level)) {
1647 /* Always do lstat for UNIX calls. */
1648 if (vfs_lstat(conn,fname,&sbuf)) {
1649 DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
1650 set_bad_path_error(errno, bad_path);
1651 return(UNIXERROR(ERRDOS,ERRbadpath));
1653 } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
1654 DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
1655 set_bad_path_error(errno, bad_path);
1656 return(UNIXERROR(ERRDOS,ERRbadpath));
1660 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
1661 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1663 DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
1664 fname,info_level,tran_call,total_data));
1666 p = strrchr_m(fname,'/');
1667 if (!p)
1668 base_name = fname;
1669 else
1670 base_name = p+1;
1672 mode = dos_mode(conn,fname,&sbuf);
1673 fullpathname = fname;
1674 file_size = get_file_size(sbuf);
1675 allocation_size = get_allocation_size(fsp,&sbuf);
1676 if (mode & aDIR)
1677 file_size = 0;
1679 params = Realloc(*pparams,2);
1680 if (params == NULL)
1681 return ERROR_DOS(ERRDOS,ERRnomem);
1682 *pparams = params;
1683 memset((char *)params,'\0',2);
1684 data_size = max_data_bytes + 1024;
1685 pdata = Realloc(*ppdata, data_size);
1686 if ( pdata == NULL )
1687 return ERROR_DOS(ERRDOS,ERRnomem);
1688 *ppdata = pdata;
1690 if (total_data > 0 && IVAL(pdata,0) == total_data) {
1691 /* uggh, EAs for OS2 */
1692 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
1693 return ERROR_DOS(ERRDOS,ERReasnotsupported);
1696 memset((char *)pdata,'\0',data_size);
1698 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1700 if (lp_dos_filetime_resolution(SNUM(conn))) {
1701 c_time &= ~1;
1702 sbuf.st_atime &= ~1;
1703 sbuf.st_mtime &= ~1;
1704 sbuf.st_mtime &= ~1;
1707 /* NT expects the name to be in an exact form of the *full*
1708 filename. See the trans2 torture test */
1709 if (strequal(base_name,".")) {
1710 pstrcpy(dos_fname, "\\");
1711 } else {
1712 snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname);
1713 string_replace(dos_fname, '/', '\\');
1716 switch (info_level) {
1717 case SMB_INFO_STANDARD:
1718 case SMB_INFO_QUERY_EA_SIZE:
1719 data_size = (info_level==1?22:26);
1720 put_dos_date2(pdata,l1_fdateCreation,c_time);
1721 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
1722 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
1723 SIVAL(pdata,l1_cbFile,(uint32)file_size);
1724 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
1725 SSVAL(pdata,l1_attrFile,mode);
1726 SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
1727 break;
1729 case SMB_INFO_QUERY_EAS_FROM_LIST:
1730 data_size = 24;
1731 put_dos_date2(pdata,0,c_time);
1732 put_dos_date2(pdata,4,sbuf.st_atime);
1733 put_dos_date2(pdata,8,sbuf.st_mtime);
1734 SIVAL(pdata,12,(uint32)file_size);
1735 SIVAL(pdata,16,(uint32)allocation_size);
1736 SIVAL(pdata,20,mode);
1737 break;
1739 case SMB_INFO_QUERY_ALL_EAS:
1740 data_size = 4;
1741 SIVAL(pdata,0,data_size);
1742 break;
1744 case 6:
1745 return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */
1747 case SMB_FILE_BASIC_INFORMATION:
1748 case SMB_QUERY_FILE_BASIC_INFO:
1750 if (info_level == SMB_QUERY_FILE_BASIC_INFO)
1751 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
1752 else {
1753 data_size = 40;
1754 SIVAL(pdata,36,0);
1756 put_long_date(pdata,c_time);
1757 put_long_date(pdata+8,sbuf.st_atime);
1758 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1759 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1760 SIVAL(pdata,32,mode);
1762 DEBUG(5,("SMB_QFBI - "));
1764 time_t create_time = c_time;
1765 DEBUG(5,("create: %s ", ctime(&create_time)));
1767 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
1768 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
1769 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
1770 DEBUG(5,("mode: %x\n", mode));
1772 break;
1774 case SMB_FILE_STANDARD_INFORMATION:
1775 case SMB_QUERY_FILE_STANDARD_INFO:
1777 data_size = 24;
1778 SOFF_T(pdata,0,allocation_size);
1779 SOFF_T(pdata,8,file_size);
1780 SIVAL(pdata,16,sbuf.st_nlink);
1781 SCVAL(pdata,20,0);
1782 SCVAL(pdata,21,(mode&aDIR)?1:0);
1783 break;
1785 case SMB_FILE_EA_INFORMATION:
1786 case SMB_QUERY_FILE_EA_INFO:
1787 data_size = 4;
1788 break;
1790 /* Get the 8.3 name - used if NT SMB was negotiated. */
1791 case SMB_QUERY_FILE_ALT_NAME_INFO:
1793 pstring short_name;
1795 pstrcpy(short_name,base_name);
1796 /* Mangle if not already 8.3 */
1797 if(!mangle_is_8_3(short_name, True)) {
1798 mangle_map(short_name,True,True,SNUM(conn));
1800 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_TERMINATE|STR_UPPER);
1801 data_size = 4 + len;
1802 SIVAL(pdata,0,len);
1803 break;
1806 case SMB_QUERY_FILE_NAME_INFO:
1808 this must be *exactly* right for ACLs on mapped drives to work
1810 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
1811 data_size = 4 + len;
1812 SIVAL(pdata,0,len);
1813 break;
1815 case SMB_FILE_ALLOCATION_INFORMATION:
1816 case SMB_QUERY_FILE_ALLOCATION_INFO:
1817 data_size = 8;
1818 SOFF_T(pdata,0,allocation_size);
1819 break;
1821 case SMB_FILE_END_OF_FILE_INFORMATION:
1822 case SMB_QUERY_FILE_END_OF_FILEINFO:
1823 data_size = 8;
1824 SOFF_T(pdata,0,file_size);
1825 break;
1827 case SMB_QUERY_FILE_ALL_INFO:
1828 put_long_date(pdata,c_time);
1829 put_long_date(pdata+8,sbuf.st_atime);
1830 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1831 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1832 SIVAL(pdata,32,mode);
1833 pdata += 40;
1834 SOFF_T(pdata,0,allocation_size);
1835 SOFF_T(pdata,8,file_size);
1836 SIVAL(pdata,16,sbuf.st_nlink);
1837 SCVAL(pdata,20,delete_pending);
1838 SCVAL(pdata,21,(mode&aDIR)?1:0);
1839 pdata += 24;
1840 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);
1841 pdata += 8; /* index number */
1842 pdata += 4; /* EA info */
1843 if (mode & aRONLY)
1844 SIVAL(pdata,0,0xA9);
1845 else
1846 SIVAL(pdata,0,0xd01BF);
1847 pdata += 4;
1848 SOFF_T(pdata,0,pos); /* current offset */
1849 pdata += 8;
1850 SIVAL(pdata,0,mode); /* is this the right sort of mode info? */
1851 pdata += 4;
1852 pdata += 4; /* alignment */
1853 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_TERMINATE);
1854 SIVAL(pdata,0,len);
1855 pdata += 4 + len;
1856 data_size = PTR_DIFF(pdata,(*ppdata));
1857 break;
1859 case SMB_FILE_INTERNAL_INFORMATION:
1860 /* This should be an index number - looks like
1861 dev/ino to me :-)
1863 I think this causes us to fail the IFSKIT
1864 BasicFileInformationTest. -tpot */
1866 SIVAL(pdata,0,sbuf.st_dev);
1867 SIVAL(pdata,4,sbuf.st_ino);
1868 data_size = 8;
1869 break;
1871 case SMB_FILE_ACCESS_INFORMATION:
1872 SIVAL(pdata,0,0x12019F); /* ??? */
1873 data_size = 4;
1874 break;
1876 case SMB_FILE_NAME_INFORMATION:
1877 /* Pathname with leading '\'. */
1879 size_t byte_len;
1880 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
1881 SIVAL(pdata,0,byte_len);
1882 data_size = 4 + byte_len;
1883 break;
1886 case SMB_FILE_DISPOSITION_INFORMATION:
1887 data_size = 1;
1888 SCVAL(pdata,0,delete_pending);
1889 break;
1891 case SMB_FILE_POSITION_INFORMATION:
1892 data_size = 8;
1893 SOFF_T(pdata,0,pos);
1894 break;
1896 case SMB_FILE_MODE_INFORMATION:
1897 SIVAL(pdata,0,mode);
1898 data_size = 4;
1899 break;
1901 case SMB_FILE_ALIGNMENT_INFORMATION:
1902 SIVAL(pdata,0,0); /* No alignment needed. */
1903 data_size = 4;
1904 break;
1906 #if 0
1907 /* Not yet finished... JRA */
1908 case 1018:
1910 put_long_date(pdata,c_time);
1911 put_long_date(pdata+8,sbuf.st_atime);
1912 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1913 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1914 SIVAL(pdata,32,mode);
1915 SIVAL(pdata,36,0); /* ??? */
1916 SIVAL(pdata,40,0x20); /* ??? */
1917 SIVAL(pdata,44,0); /* ??? */
1918 SOFF_T(pdata,48,size);
1919 SIVAL(pdata,56,0x1); /* ??? */
1920 SIVAL(pdata,60,0); /* ??? */
1921 SIVAL(pdata,64,0); /* ??? */
1922 SIVAL(pdata,68,length); /* Following string length in bytes. */
1923 dos_PutUniCode(pdata+72,,False);
1924 break;
1926 #endif
1928 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
1929 /* Last component of pathname. */
1931 size_t byte_len = dos_PutUniCode(pdata+4,fname,max_data_bytes,False);
1932 SIVAL(pdata,0,byte_len);
1933 data_size = 4 + byte_len;
1934 break;
1937 #if 0
1939 * NT4 server just returns "invalid query" to this - if we try to answer
1940 * it then NTws gets a BSOD! (tridge).
1941 * W2K seems to want this. JRA.
1943 case SMB_QUERY_FILE_STREAM_INFO:
1944 #endif
1945 case SMB_FILE_STREAM_INFORMATION:
1946 if (mode & aDIR) {
1947 data_size = 0;
1948 } else {
1949 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
1950 SIVAL(pdata,0,0); /* ??? */
1951 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
1952 SOFF_T(pdata,8,file_size);
1953 SIVAL(pdata,16,allocation_size);
1954 SIVAL(pdata,20,0); /* ??? */
1955 data_size = 24 + byte_len;
1957 break;
1959 case SMB_FILE_COMPRESSION_INFORMATION:
1960 SOFF_T(pdata,0,allocation_size);
1961 SIVAL(pdata,8,0); /* ??? */
1962 SIVAL(pdata,12,0); /* ??? */
1963 data_size = 16;
1964 break;
1966 case SMB_FILE_NETWORK_OPEN_INFORMATION:
1967 put_long_date(pdata,c_time);
1968 put_long_date(pdata+8,sbuf.st_atime);
1969 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
1970 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
1971 SIVAL(pdata,32,allocation_size);
1972 SOFF_T(pdata,40,file_size);
1973 SIVAL(pdata,48,mode);
1974 SIVAL(pdata,52,0); /* ??? */
1975 data_size = 56;
1976 break;
1978 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
1979 SIVAL(pdata,0,mode);
1980 SIVAL(pdata,4,0);
1981 data_size = 8;
1982 break;
1985 * CIFS UNIX Extensions.
1988 case SMB_QUERY_FILE_UNIX_BASIC:
1990 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
1992 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
1993 pdata += 8;
1995 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1996 pdata += 8;
1998 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
1999 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2000 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2001 pdata += 24;
2003 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2004 SIVAL(pdata,4,0);
2005 pdata += 8;
2007 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2008 SIVAL(pdata,4,0);
2009 pdata += 8;
2011 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2012 pdata += 4;
2014 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2015 SIVAL(pdata,4,0);
2016 pdata += 8;
2018 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2019 SIVAL(pdata,4,0);
2020 pdata += 8;
2022 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2023 pdata += 8;
2025 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2026 SIVAL(pdata,4,0);
2027 pdata += 8;
2029 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2030 SIVAL(pdata,4,0);
2031 pdata += 8+1;
2032 data_size = PTR_DIFF(pdata,(*ppdata));
2035 int i;
2036 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2038 for (i=0; i<100; i++)
2039 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2040 DEBUG(4,("\n"));
2043 break;
2045 case SMB_QUERY_FILE_UNIX_LINK:
2047 pstring buffer;
2049 #ifdef S_ISLNK
2050 if(!S_ISLNK(sbuf.st_mode))
2051 return(UNIXERROR(ERRSRV,ERRbadlink));
2052 #else
2053 return(UNIXERROR(ERRDOS,ERRbadlink));
2054 #endif
2055 len = conn->vfs_ops.readlink(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2056 if (len == -1)
2057 return(UNIXERROR(ERRDOS,ERRnoaccess));
2058 buffer[len] = 0;
2059 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2060 pdata += len;
2061 data_size = PTR_DIFF(pdata,(*ppdata));
2063 break;
2066 default:
2067 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2070 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_size);
2072 return(-1);
2075 /****************************************************************************
2076 Deal with the internal needs of setting the delete on close flag. Note that
2077 as the tdb locking is recursive, it is safe to call this from within
2078 open_file_shared. JRA.
2079 ****************************************************************************/
2081 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2084 * Only allow delete on close for writable shares.
2087 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2088 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2089 fsp->fsp_name ));
2090 return NT_STATUS_ACCESS_DENIED;
2093 * Only allow delete on close for files/directories opened with delete intent.
2096 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2097 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2098 fsp->fsp_name ));
2099 return NT_STATUS_ACCESS_DENIED;
2102 if(fsp->is_directory) {
2103 fsp->directory_delete_on_close = delete_on_close;
2104 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2105 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2106 } else {
2108 files_struct *iterate_fsp;
2111 * Modify the share mode entry for all files open
2112 * on this device and inode to tell other smbds we have
2113 * changed the delete on close flag. This will be noticed
2114 * in the close code, the last closer will delete the file
2115 * if flag is set.
2118 DEBUG(10,("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2119 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2121 if (lock_share_entry_fsp(fsp) == False)
2122 return NT_STATUS_ACCESS_DENIED;
2124 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2125 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2126 fsp->fsp_name ));
2127 unlock_share_entry_fsp(fsp);
2128 return NT_STATUS_ACCESS_DENIED;
2132 * Release the lock.
2135 unlock_share_entry_fsp(fsp);
2138 * Go through all files we have open on the same device and
2139 * inode (hanging off the same hash bucket) and set the DELETE_ON_CLOSE_FLAG.
2140 * Other smbd's that have this file open will look in the share_mode on close.
2141 * take care of this (rare) case in close_file(). See the comment there.
2142 * NB. JRA. We don't really need to do this anymore - all should be taken
2143 * care of in the share_mode changes in the tdb.
2146 for(iterate_fsp = file_find_di_first(fsp->dev, fsp->inode);
2147 iterate_fsp; iterate_fsp = file_find_di_next(iterate_fsp))
2148 fsp->delete_on_close = delete_on_close;
2151 * Set the delete on close flag in the fsp.
2153 fsp->delete_on_close = delete_on_close;
2155 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2156 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2160 return NT_STATUS_OK;
2163 /****************************************************************************
2164 Returns true if this pathname is within the share, and thus safe.
2165 ****************************************************************************/
2167 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2169 #ifdef PATH_MAX
2170 char resolved_name[PATH_MAX+1];
2171 #else
2172 pstring resolved_name;
2173 #endif
2174 fstring last_component;
2175 pstring link_dest;
2176 pstring link_test;
2177 char *p;
2178 BOOL bad_path = False;
2179 SMB_STRUCT_STAT sbuf;
2181 pstrcpy(link_dest, link_dest_in);
2182 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2184 /* Store the UNIX converted path. */
2185 pstrcpy(link_dest_out, link_dest);
2187 p = strrchr(link_dest, '/');
2188 if (p) {
2189 fstrcpy(last_component, p+1);
2190 *p = '\0';
2191 } else {
2192 fstrcpy(last_component, link_dest);
2193 pstrcpy(link_dest, "./");
2196 if (conn->vfs_ops.realpath(conn,link_dest,resolved_name) == NULL)
2197 return -1;
2199 pstrcpy(link_dest, resolved_name);
2200 pstrcat(link_dest, "/");
2201 pstrcat(link_dest, last_component);
2203 if (*link_dest != '/') {
2204 /* Relative path. */
2205 pstrcpy(link_test, conn->connectpath);
2206 pstrcat(link_test, "/");
2207 pstrcat(link_test, link_dest);
2208 } else {
2209 pstrcpy(link_test, link_dest);
2213 * Check if the link is within the share.
2216 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2217 errno = EACCES;
2218 return -1;
2220 return 0;
2223 /****************************************************************************
2224 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
2225 ****************************************************************************/
2227 static int call_trans2setfilepathinfo(connection_struct *conn,
2228 char *inbuf, char *outbuf, int length, int bufsize,
2229 char **pparams, int total_params, char **ppdata, int total_data)
2231 char *params = *pparams;
2232 char *pdata = *ppdata;
2233 uint16 tran_call = SVAL(inbuf, smb_setup0);
2234 uint16 info_level;
2235 int dosmode=0;
2236 SMB_OFF_T size=0;
2237 struct utimbuf tvs;
2238 SMB_STRUCT_STAT sbuf;
2239 pstring fname;
2240 int fd = -1;
2241 BOOL bad_path = False;
2242 files_struct *fsp = NULL;
2243 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
2244 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
2245 mode_t unixmode = 0;
2247 if (tran_call == TRANSACT2_SETFILEINFO) {
2248 fsp = file_fsp(params,0);
2249 info_level = SVAL(params,2);
2251 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2253 * This is actually a SETFILEINFO on a directory
2254 * handle (returned from an NT SMB). NT5.0 seems
2255 * to do this call. JRA.
2257 pstrcpy(fname, fsp->fsp_name);
2258 unix_convert(fname,conn,0,&bad_path,&sbuf);
2259 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
2260 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2261 set_bad_path_error(errno, bad_path);
2262 return(UNIXERROR(ERRDOS,ERRbadpath));
2264 } else if (fsp && fsp->print_file) {
2266 * Doing a DELETE_ON_CLOSE should cancel a print job.
2268 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
2269 fsp->share_mode = FILE_DELETE_ON_CLOSE;
2271 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
2273 SSVAL(params,0,0);
2274 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2275 return(-1);
2276 } else
2277 return (UNIXERROR(ERRDOS,ERRbadpath));
2278 } else {
2280 * Original code - this is an open file.
2282 CHECK_FSP(fsp,conn);
2284 pstrcpy(fname, fsp->fsp_name);
2285 fd = fsp->fd;
2287 if (vfs_fstat(fsp,fd,&sbuf) != 0) {
2288 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
2289 return(UNIXERROR(ERRDOS,ERRbadfid));
2292 } else {
2293 /* set path info */
2294 if (total_params < 6)
2295 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2297 info_level = SVAL(params,0);
2298 srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
2299 unix_convert(fname,conn,0,&bad_path,&sbuf);
2300 if(!check_name(fname, conn)) {
2301 set_bad_path_error(errno, bad_path);
2302 return(UNIXERROR(ERRDOS,ERRbadpath));
2306 * For CIFS UNIX extensions the target name may not exist.
2309 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
2310 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
2311 set_bad_path_error(errno, bad_path);
2312 return(UNIXERROR(ERRDOS,ERRbadpath));
2316 if (!CAN_WRITE(conn))
2317 return ERROR_DOS(ERRSRV,ERRaccess);
2319 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2320 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2322 if (VALID_STAT(sbuf))
2323 unixmode = sbuf.st_mode;
2325 DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
2326 tran_call,fname,info_level,total_data));
2328 /* Realloc the parameter and data sizes */
2329 params = Realloc(*pparams,2);
2330 if(params == NULL)
2331 return ERROR_DOS(ERRDOS,ERRnomem);
2332 *pparams = params;
2334 SSVAL(params,0,0);
2336 if (fsp) {
2337 /* the pending modtime overrides the current modtime */
2338 sbuf.st_mtime = fsp->pending_modtime;
2341 size = get_file_size(sbuf);
2342 tvs.modtime = sbuf.st_mtime;
2343 tvs.actime = sbuf.st_atime;
2344 dosmode = dos_mode(conn,fname,&sbuf);
2345 unixmode = sbuf.st_mode;
2347 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
2348 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
2350 switch (info_level) {
2351 case SMB_INFO_STANDARD:
2353 if (total_data < l1_cbFile+4)
2354 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2356 /* access time */
2357 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
2359 /* write time */
2360 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
2362 dosmode = SVAL(pdata,l1_attrFile);
2363 size = IVAL(pdata,l1_cbFile);
2365 break;
2368 case SMB_INFO_SET_EA:
2369 return(ERROR_DOS(ERRDOS,ERReasnotsupported));
2371 /* XXXX um, i don't think this is right.
2372 it's also not in the cifs6.txt spec.
2374 case SMB_INFO_QUERY_EAS_FROM_LIST:
2375 if (total_data < 28)
2376 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2378 tvs.actime = make_unix_date2(pdata+8);
2379 tvs.modtime = make_unix_date2(pdata+12);
2380 size = IVAL(pdata,16);
2381 dosmode = IVAL(pdata,24);
2382 break;
2384 /* XXXX nor this. not in cifs6.txt, either. */
2385 case SMB_INFO_QUERY_ALL_EAS:
2386 if (total_data < 28)
2387 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2389 tvs.actime = make_unix_date2(pdata+8);
2390 tvs.modtime = make_unix_date2(pdata+12);
2391 size = IVAL(pdata,16);
2392 dosmode = IVAL(pdata,24);
2393 break;
2395 case SMB_SET_FILE_BASIC_INFO:
2396 case SMB_FILE_BASIC_INFORMATION:
2398 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
2399 time_t write_time;
2400 time_t changed_time;
2402 if (total_data < 36)
2403 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2405 /* Ignore create time at offset pdata. */
2407 /* access time */
2408 tvs.actime = interpret_long_date(pdata+8);
2410 write_time = interpret_long_date(pdata+16);
2411 changed_time = interpret_long_date(pdata+24);
2413 tvs.modtime = MIN(write_time, changed_time);
2415 if (write_time > tvs.modtime && write_time != 0xffffffff) {
2416 tvs.modtime = write_time;
2418 /* Prefer a defined time to an undefined one. */
2419 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2420 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
2421 ? changed_time : write_time);
2423 /* attributes */
2424 dosmode = IVAL(pdata,32);
2425 break;
2428 case SMB_FILE_ALLOCATION_INFORMATION:
2429 case SMB_SET_FILE_ALLOCATION_INFO:
2431 int ret = -1;
2432 SMB_OFF_T allocation_size;
2434 if (total_data < 8)
2435 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2437 allocation_size = IVAL(pdata,0);
2438 #ifdef LARGE_SMB_OFF_T
2439 allocation_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2440 #else /* LARGE_SMB_OFF_T */
2441 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2442 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2443 #endif /* LARGE_SMB_OFF_T */
2444 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
2445 fname, (double)allocation_size ));
2447 if (allocation_size)
2448 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
2450 if(allocation_size != get_file_size(sbuf)) {
2451 SMB_STRUCT_STAT new_sbuf;
2453 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
2454 fname, (double)allocation_size ));
2456 if (fd == -1) {
2457 files_struct *new_fsp = NULL;
2458 int access_mode = 0;
2459 int action = 0;
2461 if(global_oplock_break) {
2462 /* Queue this file modify as we are the process of an oplock break. */
2464 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2465 DEBUGADD(2,( "in oplock break state.\n"));
2467 push_oplock_pending_smb_message(inbuf, length);
2468 return -1;
2471 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
2472 SET_OPEN_MODE(DOS_OPEN_RDWR),
2473 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2474 0, 0, &access_mode, &action);
2476 if (new_fsp == NULL)
2477 return(UNIXERROR(ERRDOS,ERRbadpath));
2478 ret = vfs_allocate_file_space(new_fsp, allocation_size);
2479 if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
2480 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2481 new_fsp->fnum, strerror(errno)));
2482 ret = -1;
2484 close_file(new_fsp,True);
2485 } else {
2486 ret = vfs_allocate_file_space(fsp, allocation_size);
2487 if (vfs_fstat(fsp,fd,&new_sbuf) != 0) {
2488 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
2489 fsp->fnum, strerror(errno)));
2490 ret = -1;
2493 if (ret == -1)
2494 return ERROR_NT(NT_STATUS_DISK_FULL);
2496 /* Allocate can truncate size... */
2497 size = get_file_size(new_sbuf);
2500 break;
2503 case SMB_FILE_END_OF_FILE_INFORMATION:
2504 case SMB_SET_FILE_END_OF_FILE_INFO:
2506 if (total_data < 8)
2507 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2509 size = IVAL(pdata,0);
2510 #ifdef LARGE_SMB_OFF_T
2511 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2512 #else /* LARGE_SMB_OFF_T */
2513 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2514 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2515 #endif /* LARGE_SMB_OFF_T */
2516 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
2517 break;
2520 case SMB_FILE_DISPOSITION_INFORMATION:
2521 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
2523 BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
2524 NTSTATUS status;
2526 if (total_data < 1)
2527 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2529 if (tran_call != TRANSACT2_SETFILEINFO)
2530 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2532 if (fsp == NULL)
2533 return(UNIXERROR(ERRDOS,ERRbadfid));
2535 status = set_delete_on_close_internal(fsp, delete_on_close);
2537 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
2538 return ERROR_NT(status);
2540 break;
2544 * CIFS UNIX extensions.
2547 case SMB_SET_FILE_UNIX_BASIC:
2549 uint32 raw_unixmode;
2551 if (total_data < 100)
2552 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2554 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
2555 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
2556 size=IVAL(pdata,0); /* first 8 Bytes are size */
2557 #ifdef LARGE_SMB_OFF_T
2558 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
2559 #else /* LARGE_SMB_OFF_T */
2560 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
2561 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2562 #endif /* LARGE_SMB_OFF_T */
2564 pdata+=24; /* ctime & st_blocks are not changed */
2565 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
2566 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
2567 pdata+=16;
2568 set_owner = (uid_t)IVAL(pdata,0);
2569 pdata += 8;
2570 set_grp = (gid_t)IVAL(pdata,0);
2571 pdata += 8;
2572 raw_unixmode = IVAL(pdata,28);
2573 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
2574 dosmode = 0; /* Ensure dos mode change doesn't override this. */
2576 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
2577 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
2578 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
2580 if (!VALID_STAT(sbuf)) {
2583 * The only valid use of this is to create character and block
2584 * devices, and named pipes. This is deprecated (IMHO) and
2585 * a new info level should be used for mknod. JRA.
2588 #if !defined(HAVE_MAKEDEV_FN)
2589 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2590 #else /* HAVE_MAKEDEV_FN */
2591 uint32 file_type = IVAL(pdata,0);
2592 uint32 dev_major = IVAL(pdata,4);
2593 uint32 dev_minor = IVAL(pdata,12);
2595 uid_t myuid = geteuid();
2596 gid_t mygid = getegid();
2597 SMB_DEV_T dev;
2599 if (tran_call == TRANSACT2_SETFILEINFO)
2600 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2602 if (raw_unixmode == SMB_MODE_NO_CHANGE)
2603 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2605 dev = makedev(dev_major, dev_minor);
2607 /* We can only create as the owner/group we are. */
2609 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
2610 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2611 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
2612 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2614 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
2615 file_type != UNIX_TYPE_FIFO)
2616 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2618 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
2619 0%o for file %s\n", (double)dev, unixmode, fname ));
2621 /* Ok - do the mknod. */
2622 if (conn->vfs_ops.mknod(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
2623 return(UNIXERROR(ERRDOS,ERRnoaccess));
2625 SSVAL(params,0,0);
2626 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2627 return(-1);
2628 #endif /* HAVE_MAKEDEV_FN */
2633 * Deal with the UNIX specific mode set.
2636 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
2637 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
2638 (unsigned int)unixmode, fname ));
2639 if (vfs_chmod(conn,fname,unixmode) != 0)
2640 return(UNIXERROR(ERRDOS,ERRnoaccess));
2644 * Deal with the UNIX specific uid set.
2647 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
2648 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
2649 (unsigned int)set_owner, fname ));
2650 if (vfs_chown(conn,fname,set_owner, (gid_t)-1) != 0)
2651 return(UNIXERROR(ERRDOS,ERRnoaccess));
2655 * Deal with the UNIX specific gid set.
2658 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
2659 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
2660 (unsigned int)set_owner, fname ));
2661 if (vfs_chown(conn,fname,(uid_t)-1, set_grp) != 0)
2662 return(UNIXERROR(ERRDOS,ERRnoaccess));
2664 break;
2667 case SMB_SET_FILE_UNIX_LINK:
2669 pstring link_dest;
2670 /* Set a symbolic link. */
2671 /* Don't allow this if follow links is false. */
2673 if (!lp_symlinks(SNUM(conn)))
2674 return(ERROR_DOS(ERRDOS,ERRnoaccess));
2676 /* Disallow if already exists. */
2677 if (VALID_STAT(sbuf))
2678 return(ERROR_DOS(ERRDOS,ERRbadpath));
2680 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2682 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2683 return(UNIXERROR(ERRDOS,ERRnoaccess));
2685 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
2686 fname, link_dest ));
2688 if (conn->vfs_ops.symlink(conn,link_dest,fname) != 0)
2689 return(UNIXERROR(ERRDOS,ERRnoaccess));
2690 SSVAL(params,0,0);
2691 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2692 return(-1);
2695 case SMB_SET_FILE_UNIX_HLINK:
2697 pstring link_dest;
2699 /* Set a hard link. */
2701 /* Disallow if already exists. */
2702 if (VALID_STAT(sbuf))
2703 return(ERROR_DOS(ERRDOS,ERRbadpath));
2705 srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
2707 if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
2708 return(UNIXERROR(ERRDOS,ERRnoaccess));
2710 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
2711 fname, link_dest ));
2713 if (conn->vfs_ops.link(conn,link_dest,fname) != 0)
2714 return(UNIXERROR(ERRDOS,ERRnoaccess));
2715 SSVAL(params,0,0);
2716 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2717 return(-1);
2720 default:
2721 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2724 /* get some defaults (no modifications) if any info is zero or -1. */
2725 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
2726 tvs.actime = sbuf.st_atime;
2728 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
2729 tvs.modtime = sbuf.st_mtime;
2731 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
2732 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
2733 DEBUG(6,("size: %.0f ", (double)size));
2735 if (S_ISDIR(sbuf.st_mode))
2736 dosmode |= aDIR;
2737 else
2738 dosmode &= ~aDIR;
2740 DEBUG(6,("dosmode: %x\n" , dosmode));
2742 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
2743 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
2744 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
2745 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
2748 * Only do this test if we are not explicitly
2749 * changing the size of a file.
2751 if (!size)
2752 size = get_file_size(sbuf);
2756 * Try and set the times, size and mode of this file -
2757 * if they are different from the current values
2759 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
2760 if(fsp != NULL) {
2762 * This was a setfileinfo on an open file.
2763 * NT does this a lot. It's actually pointless
2764 * setting the time here, as it will be overwritten
2765 * on the next write, so we save the request
2766 * away and will set it on file close. JRA.
2769 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
2770 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
2771 fsp->pending_modtime = tvs.modtime;
2774 } else {
2776 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
2778 if(file_utime(conn, fname, &tvs)!=0)
2779 return(UNIXERROR(ERRDOS,ERRnoaccess));
2783 /* check the mode isn't different, before changing it */
2784 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
2786 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
2788 if(file_chmod(conn, fname, dosmode, NULL)) {
2789 DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
2790 return(UNIXERROR(ERRDOS,ERRnoaccess));
2794 if (size != get_file_size(sbuf)) {
2796 int ret;
2798 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
2799 fname, (double)size ));
2801 if (fd == -1) {
2802 files_struct *new_fsp = NULL;
2803 int access_mode = 0;
2804 int action = 0;
2806 if(global_oplock_break) {
2807 /* Queue this file modify as we are the process of an oplock break. */
2809 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
2810 DEBUGADD(2,( "in oplock break state.\n"));
2812 push_oplock_pending_smb_message(inbuf, length);
2813 return -1;
2816 new_fsp = open_file_shared(conn, fname, &sbuf,
2817 SET_OPEN_MODE(DOS_OPEN_RDWR),
2818 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
2819 0, 0, &access_mode, &action);
2821 if (new_fsp == NULL)
2822 return(UNIXERROR(ERRDOS,ERRbadpath));
2823 ret = vfs_set_filelen(new_fsp, size);
2824 close_file(new_fsp,True);
2825 } else {
2826 ret = vfs_set_filelen(fsp, size);
2829 if (ret == -1)
2830 return (UNIXERROR(ERRHRD,ERRdiskfull));
2833 SSVAL(params,0,0);
2834 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2836 return(-1);
2839 /****************************************************************************
2840 Reply to a TRANS2_MKDIR (make directory with extended attributes).
2841 ****************************************************************************/
2843 static int call_trans2mkdir(connection_struct *conn,
2844 char *inbuf, char *outbuf, int length, int bufsize,
2845 char **pparams, int total_params, char **ppdata, int total_data)
2847 char *params = *pparams;
2848 pstring directory;
2849 int ret = -1;
2850 SMB_STRUCT_STAT sbuf;
2851 BOOL bad_path = False;
2853 if (!CAN_WRITE(conn))
2854 return ERROR_DOS(ERRSRV,ERRaccess);
2856 if (total_params < 4)
2857 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2859 srvstr_pull(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE);
2861 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
2863 unix_convert(directory,conn,0,&bad_path,&sbuf);
2864 if (check_name(directory,conn))
2865 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2867 if(ret < 0) {
2868 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
2869 set_bad_path_error(errno, bad_path);
2870 return(UNIXERROR(ERRDOS,ERRnoaccess));
2873 /* Realloc the parameter and data sizes */
2874 params = Realloc(*pparams,2);
2875 if(params == NULL)
2876 return ERROR_DOS(ERRDOS,ERRnomem);
2877 *pparams = params;
2879 SSVAL(params,0,0);
2881 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
2883 return(-1);
2886 /****************************************************************************
2887 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
2888 We don't actually do this - we just send a null response.
2889 ****************************************************************************/
2891 static int call_trans2findnotifyfirst(connection_struct *conn,
2892 char *inbuf, char *outbuf, int length, int bufsize,
2893 char **pparams, int total_params, char **ppdata, int total_data)
2895 static uint16 fnf_handle = 257;
2896 char *params = *pparams;
2897 uint16 info_level;
2899 if (total_params < 6)
2900 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2902 info_level = SVAL(params,4);
2903 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
2905 switch (info_level) {
2906 case 1:
2907 case 2:
2908 break;
2909 default:
2910 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2913 /* Realloc the parameter and data sizes */
2914 params = Realloc(*pparams,6);
2915 if(params == NULL)
2916 return ERROR_DOS(ERRDOS,ERRnomem);
2917 *pparams = params;
2919 SSVAL(params,0,fnf_handle);
2920 SSVAL(params,2,0); /* No changes */
2921 SSVAL(params,4,0); /* No EA errors */
2923 fnf_handle++;
2925 if(fnf_handle == 0)
2926 fnf_handle = 257;
2928 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
2930 return(-1);
2933 /****************************************************************************
2934 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
2935 changes). Currently this does nothing.
2936 ****************************************************************************/
2938 static int call_trans2findnotifynext(connection_struct *conn,
2939 char *inbuf, char *outbuf, int length, int bufsize,
2940 char **pparams, int total_params, char **ppdata, int total_data)
2942 char *params = *pparams;
2944 DEBUG(3,("call_trans2findnotifynext\n"));
2946 /* Realloc the parameter and data sizes */
2947 params = Realloc(*pparams,4);
2948 if(params == NULL)
2949 return ERROR_DOS(ERRDOS,ERRnomem);
2950 *pparams = params;
2952 SSVAL(params,0,0); /* No changes */
2953 SSVAL(params,2,0); /* No EA errors */
2955 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
2957 return(-1);
2960 /****************************************************************************
2961 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
2962 ****************************************************************************/
2964 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
2965 char* outbuf, int length, int bufsize,
2966 char **pparams, int total_params, char **ppdata, int total_data)
2968 char *params = *pparams;
2969 pstring pathname;
2970 int reply_size = 0;
2971 int max_referral_level;
2973 DEBUG(10,("call_trans2getdfsreferral\n"));
2975 if (total_params < 2)
2976 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2978 max_referral_level = SVAL(params,0);
2980 if(!lp_host_msdfs())
2981 return ERROR_DOS(ERRDOS,ERRbadfunc);
2983 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
2985 if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
2986 return ERROR_DOS(ERRDOS,ERRbadfile);
2988 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
2989 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
2991 return(-1);
2994 #define LMCAT_SPL 0x53
2995 #define LMFUNC_GETJOBID 0x60
2997 /****************************************************************************
2998 Reply to a TRANS2_IOCTL - used for OS/2 printing.
2999 ****************************************************************************/
3001 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3002 char* outbuf, int length, int bufsize,
3003 char **pparams, int total_params, char **ppdata, int total_data)
3005 char *pdata = *ppdata;
3006 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3008 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3009 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3010 uint16 rap_jobid;
3012 pdata = Realloc(*ppdata, 32);
3013 if(pdata == NULL)
3014 return ERROR_DOS(ERRDOS,ERRnomem);
3015 *ppdata = pdata;
3017 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3018 CAN ACCEPT THIS IN UNICODE. JRA. */
3020 rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid); /* Job number */
3021 SSVAL(pdata,0,rap_jobid); /* Job number */
3022 srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3023 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3024 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3025 return(-1);
3026 } else {
3027 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3028 return ERROR_DOS(ERRSRV,ERRerror);
3032 /****************************************************************************
3033 Reply to a SMBfindclose (stop trans2 directory search).
3034 ****************************************************************************/
3036 int reply_findclose(connection_struct *conn,
3037 char *inbuf,char *outbuf,int length,int bufsize)
3039 int outsize = 0;
3040 int dptr_num=SVALS(inbuf,smb_vwv0);
3041 START_PROFILE(SMBfindclose);
3043 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3045 dptr_close(&dptr_num);
3047 outsize = set_message(outbuf,0,0,True);
3049 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3051 END_PROFILE(SMBfindclose);
3052 return(outsize);
3055 /****************************************************************************
3056 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3057 ****************************************************************************/
3059 int reply_findnclose(connection_struct *conn,
3060 char *inbuf,char *outbuf,int length,int bufsize)
3062 int outsize = 0;
3063 int dptr_num= -1;
3064 START_PROFILE(SMBfindnclose);
3066 dptr_num = SVAL(inbuf,smb_vwv0);
3068 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3070 /* We never give out valid handles for a
3071 findnotifyfirst - so any dptr_num is ok here.
3072 Just ignore it. */
3074 outsize = set_message(outbuf,0,0,True);
3076 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3078 END_PROFILE(SMBfindnclose);
3079 return(outsize);
3082 /****************************************************************************
3083 Reply to a SMBtranss2 - just ignore it!
3084 ****************************************************************************/
3086 int reply_transs2(connection_struct *conn,
3087 char *inbuf,char *outbuf,int length,int bufsize)
3089 START_PROFILE(SMBtranss2);
3090 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3091 END_PROFILE(SMBtranss2);
3092 return(-1);
3095 /****************************************************************************
3096 Reply to a SMBtrans2.
3097 ****************************************************************************/
3099 int reply_trans2(connection_struct *conn,
3100 char *inbuf,char *outbuf,int length,int bufsize)
3102 int outsize = 0;
3103 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3104 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3105 #if 0
3106 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3107 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3108 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3109 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3110 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3111 int32 timeout = IVALS(inbuf,smb_timeout);
3112 #endif
3113 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3114 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3115 char *params = NULL, *data = NULL;
3116 int num_params, num_params_sofar, num_data, num_data_sofar;
3117 START_PROFILE(SMBtrans2);
3119 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3120 /* Queue this open message as we are the process of an
3121 * oplock break. */
3123 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3124 DEBUGADD(2,( "in oplock break state.\n"));
3126 push_oplock_pending_smb_message(inbuf, length);
3127 END_PROFILE(SMBtrans2);
3128 return -1;
3131 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
3132 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
3133 END_PROFILE(SMBtrans2);
3134 return ERROR_DOS(ERRSRV,ERRaccess);
3137 outsize = set_message(outbuf,0,0,True);
3139 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
3140 is so as a sanity check */
3141 if (suwcnt != 1) {
3143 * Need to have rc=0 for ioctl to get job id for OS/2.
3144 * Network printing will fail if function is not successful.
3145 * Similar function in reply.c will be used if protocol
3146 * is LANMAN1.0 instead of LM1.2X002.
3147 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
3148 * outbuf doesn't have to be set(only job id is used).
3150 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
3151 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3152 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3153 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
3154 } else {
3155 DEBUG(2,("Invalid smb_sucnt in trans2 call(%d)\n",suwcnt));
3156 DEBUG(2,("Transaction is %d\n",tran_call));
3157 END_PROFILE(SMBtrans2);
3158 return ERROR_DOS(ERRSRV,ERRerror);
3162 /* Allocate the space for the maximum needed parameters and data */
3163 if (total_params > 0)
3164 params = (char *)malloc(total_params);
3165 if (total_data > 0)
3166 data = (char *)malloc(total_data);
3168 if ((total_params && !params) || (total_data && !data)) {
3169 DEBUG(2,("Out of memory in reply_trans2\n"));
3170 SAFE_FREE(params);
3171 SAFE_FREE(data);
3172 END_PROFILE(SMBtrans2);
3173 return ERROR_DOS(ERRDOS,ERRnomem);
3176 /* Copy the param and data bytes sent with this request into
3177 the params buffer */
3178 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
3179 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
3181 if (num_params > total_params || num_data > total_data)
3182 exit_server("invalid params in reply_trans2");
3184 if(params)
3185 memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
3186 if(data)
3187 memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
3189 if(num_data_sofar < total_data || num_params_sofar < total_params) {
3190 /* We need to send an interim response then receive the rest
3191 of the parameter/data bytes */
3192 outsize = set_message(outbuf,0,0,True);
3193 if (!send_smb(smbd_server_fd(),outbuf))
3194 exit_server("reply_trans2: send_smb failed.");
3196 while (num_data_sofar < total_data ||
3197 num_params_sofar < total_params) {
3198 BOOL ret;
3200 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3202 if ((ret &&
3203 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
3204 outsize = set_message(outbuf,0,0,True);
3205 if(ret)
3206 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
3207 else
3208 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
3209 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3210 SAFE_FREE(params);
3211 SAFE_FREE(data);
3212 END_PROFILE(SMBtrans2);
3213 return ERROR_DOS(ERRSRV,ERRerror);
3216 /* Revise total_params and total_data in case
3217 they have changed downwards */
3218 total_params = SVAL(inbuf, smb_tpscnt);
3219 total_data = SVAL(inbuf, smb_tdscnt);
3220 num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
3221 num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
3222 if (num_params_sofar > total_params || num_data_sofar > total_data)
3223 exit_server("data overflow in trans2");
3225 memcpy( &params[ SVAL(inbuf, smb_spsdisp)],
3226 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
3227 memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
3228 smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
3232 if (Protocol >= PROTOCOL_NT1) {
3233 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
3236 /* Now we must call the relevant TRANS2 function */
3237 switch(tran_call) {
3238 case TRANSACT2_OPEN:
3239 START_PROFILE_NESTED(Trans2_open);
3240 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
3241 &params, total_params, &data, total_data);
3242 END_PROFILE_NESTED(Trans2_open);
3243 break;
3245 case TRANSACT2_FINDFIRST:
3246 START_PROFILE_NESTED(Trans2_findfirst);
3247 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
3248 &params, total_params, &data, total_data);
3249 END_PROFILE_NESTED(Trans2_findfirst);
3250 break;
3252 case TRANSACT2_FINDNEXT:
3253 START_PROFILE_NESTED(Trans2_findnext);
3254 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
3255 &params, total_params, &data, total_data);
3256 END_PROFILE_NESTED(Trans2_findnext);
3257 break;
3259 case TRANSACT2_QFSINFO:
3260 START_PROFILE_NESTED(Trans2_qfsinfo);
3261 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
3262 &params, total_params, &data, total_data);
3263 END_PROFILE_NESTED(Trans2_qfsinfo);
3264 break;
3266 case TRANSACT2_SETFSINFO:
3267 START_PROFILE_NESTED(Trans2_setfsinfo);
3268 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
3269 &params, total_params, &data, total_data);
3270 END_PROFILE_NESTED(Trans2_setfsinfo);
3271 break;
3273 case TRANSACT2_QPATHINFO:
3274 case TRANSACT2_QFILEINFO:
3275 START_PROFILE_NESTED(Trans2_qpathinfo);
3276 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3277 &params, total_params, &data, total_data);
3278 END_PROFILE_NESTED(Trans2_qpathinfo);
3279 break;
3280 case TRANSACT2_SETPATHINFO:
3281 case TRANSACT2_SETFILEINFO:
3282 START_PROFILE_NESTED(Trans2_setpathinfo);
3283 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
3284 &params, total_params, &data, total_data);
3285 END_PROFILE_NESTED(Trans2_setpathinfo);
3286 break;
3288 case TRANSACT2_FINDNOTIFYFIRST:
3289 START_PROFILE_NESTED(Trans2_findnotifyfirst);
3290 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
3291 &params, total_params, &data, total_data);
3292 END_PROFILE_NESTED(Trans2_findnotifyfirst);
3293 break;
3295 case TRANSACT2_FINDNOTIFYNEXT:
3296 START_PROFILE_NESTED(Trans2_findnotifynext);
3297 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
3298 &params, total_params, &data, total_data);
3299 END_PROFILE_NESTED(Trans2_findnotifynext);
3300 break;
3301 case TRANSACT2_MKDIR:
3302 START_PROFILE_NESTED(Trans2_mkdir);
3303 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
3304 &params, total_params, &data, total_data);
3305 END_PROFILE_NESTED(Trans2_mkdir);
3306 break;
3308 case TRANSACT2_GET_DFS_REFERRAL:
3309 START_PROFILE_NESTED(Trans2_get_dfs_referral);
3310 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
3311 &params, total_params, &data, total_data);
3312 END_PROFILE_NESTED(Trans2_get_dfs_referral);
3313 break;
3314 case TRANSACT2_IOCTL:
3315 START_PROFILE_NESTED(Trans2_ioctl);
3316 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
3317 &params, total_params, &data, total_data);
3318 END_PROFILE_NESTED(Trans2_ioctl);
3319 break;
3320 default:
3321 /* Error in request */
3322 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
3323 SAFE_FREE(params);
3324 SAFE_FREE(data);
3325 END_PROFILE(SMBtrans2);
3326 return ERROR_DOS(ERRSRV,ERRerror);
3329 /* As we do not know how many data packets will need to be
3330 returned here the various call_trans2xxxx calls
3331 must send their own. Thus a call_trans2xxx routine only
3332 returns a value other than -1 when it wants to send
3333 an error packet.
3336 SAFE_FREE(params);
3337 SAFE_FREE(data);
3338 END_PROFILE(SMBtrans2);
3339 return outsize; /* If a correct response was needed the
3340 call_trans2xxx calls have already sent
3341 it. If outsize != -1 then it is returning */