r150: Make 3.x pass the Samba 4.x RAW-SEARCH tests - except for the
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blob16c2d83aa223f88c86a5fcc9774d748d9e5dc93f
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2003
5 Copyright (C) Stefan (metze) Metzmacher 2003
7 Extensively modified by Andrew Tridgell, 1995
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 extern int Protocol;
27 extern BOOL case_sensitive;
28 extern int smb_read_error;
29 extern fstring local_machine;
30 extern int global_oplock_break;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
34 #define get_file_size(sbuf) ((sbuf).st_size)
36 /* given a stat buffer return the allocated size on disk, taking into
37 account sparse files */
38 SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
40 SMB_BIG_UINT ret;
41 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
42 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
43 #else
44 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
45 #endif
46 if (!ret && fsp && fsp->initial_allocation_size)
47 ret = fsp->initial_allocation_size;
48 ret = SMB_ROUNDUP(ret,SMB_ROUNDUP_ALLOCATION_SIZE);
49 return ret;
52 /****************************************************************************
53 Utility functions for dealing with extended attributes.
54 ****************************************************************************/
56 static const char *prohibited_ea_names[] = {
57 SAMBA_POSIX_INHERITANCE_EA_NAME,
58 SAMBA_XATTR_DOS_ATTRIB,
59 NULL
62 /****************************************************************************
63 Refuse to allow clients to overwrite our private xattrs.
64 ****************************************************************************/
66 static BOOL samba_private_attr_name(const char *unix_ea_name)
68 int i;
70 for (i = 0; prohibited_ea_names[i]; i++) {
71 if (strequal( prohibited_ea_names[i], unix_ea_name))
72 return True;
74 return False;
77 struct ea_list {
78 struct ea_list *next, *prev;
79 struct ea_struct ea;
82 /****************************************************************************
83 Get one EA value. Fill in a struct ea_struct.
84 ****************************************************************************/
86 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
87 const char *fname, char *ea_name, struct ea_struct *pea)
89 /* Get the value of this xattr. Max size is 64k. */
90 size_t attr_size = 256;
91 char *val = NULL;
92 ssize_t sizeret;
94 again:
96 val = talloc_realloc(mem_ctx, val, attr_size);
97 if (!val) {
98 return False;
101 if (fsp && fsp->fd != -1) {
102 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
103 } else {
104 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
107 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
108 attr_size = 65536;
109 goto again;
112 if (sizeret == -1) {
113 return False;
116 DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
117 dump_data(10, val, sizeret);
119 pea->flags = 0;
120 if (strnequal(ea_name, "user.", 5)) {
121 pea->name = &ea_name[5];
122 } else {
123 pea->name = ea_name;
125 pea->value.data = val;
126 pea->value.length = (size_t)sizeret;
127 return True;
130 /****************************************************************************
131 Return a linked list of the total EA's. Plus the total size
132 ****************************************************************************/
134 static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, const char *fname, size_t *pea_total_len)
136 /* Get a list of all xattrs. Max namesize is 64k. */
137 size_t ea_namelist_size = 1024;
138 char *ea_namelist;
139 char *p;
140 ssize_t sizeret;
141 int i;
142 struct ea_list *ea_list_head = NULL;
144 *pea_total_len = 0;
146 if (!lp_ea_support(SNUM(conn))) {
147 return NULL;
150 for (i = 0, ea_namelist = talloc(mem_ctx, ea_namelist_size); i < 6;
151 ea_namelist = talloc_realloc(mem_ctx, ea_namelist, ea_namelist_size), i++) {
152 if (fsp && fsp->fd != -1) {
153 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
154 } else {
155 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
158 if (sizeret == -1 && errno == ERANGE) {
159 ea_namelist_size *= 2;
160 } else {
161 break;
165 if (sizeret == -1)
166 return NULL;
168 DEBUG(10,("get_ea_list: ea_namelist size = %d\n", sizeret ));
170 if (sizeret) {
171 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
172 struct ea_list *listp, *tmp;
174 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
175 continue;
177 listp = talloc(mem_ctx, sizeof(struct ea_list));
178 if (!listp)
179 return NULL;
181 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
182 return NULL;
186 fstring dos_ea_name;
187 push_ascii_fstring(dos_ea_name, listp->ea.name);
188 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
189 DEBUG(10,("get_ea_list: total_len = %u, %s, val len = %u\n",
190 *pea_total_len, dos_ea_name,
191 (unsigned int)listp->ea.value.length ));
193 DLIST_ADD_END(ea_list_head, listp, tmp);
195 /* Add on 4 for total length. */
196 if (*pea_total_len) {
197 *pea_total_len += 4;
201 DEBUG(10,("get_ea_list: total_len = %u\n", *pea_total_len));
202 return ea_list_head;
205 /****************************************************************************
206 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
207 that was filled.
208 ****************************************************************************/
210 static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size,
211 connection_struct *conn, files_struct *fsp, const char *fname)
213 unsigned int ret_data_size = 4;
214 char *p = pdata;
215 size_t total_ea_len;
216 TALLOC_CTX *mem_ctx;
217 struct ea_list *ea_list;
219 SMB_ASSERT(total_data_size >= 4);
221 SIVAL(pdata,0,0);
222 if (!lp_ea_support(SNUM(conn))) {
223 return 4;
225 mem_ctx = talloc_init("fill_ea_buffer");
226 if (!mem_ctx) {
227 return 4;
230 ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
231 if (!ea_list) {
232 talloc_destroy(mem_ctx);
233 return 4;
236 if (total_ea_len > total_data_size) {
237 talloc_destroy(mem_ctx);
238 return 4;
241 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
242 size_t dos_namelen;
243 fstring dos_ea_name;
244 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
245 dos_namelen = strlen(dos_ea_name);
246 if (dos_namelen > 255 || dos_namelen == 0) {
247 break;
249 if (ea_list->ea.value.length > 65535) {
250 break;
252 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
253 break;
256 /* We know we have room. */
257 SCVAL(p,0,ea_list->ea.flags);
258 SCVAL(p,1,dos_namelen);
259 SSVAL(p,2,ea_list->ea.value.length);
260 fstrcpy(p+4, dos_ea_name);
261 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
263 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
264 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
267 ret_data_size = PTR_DIFF(p, pdata);
268 DEBUG(10,("fill_ea_buffer: data_size = %u, total_ea_len = %u\n",
269 ret_data_size, total_ea_len ));
270 talloc_destroy(mem_ctx);
271 SIVAL(pdata,0,ret_data_size);
272 return ret_data_size;
275 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
277 size_t total_ea_len = 0;
278 TALLOC_CTX *mem_ctx = NULL;
280 if (!lp_ea_support(SNUM(conn))) {
281 return 0;
283 mem_ctx = talloc_init("estimate_ea_size");
284 (void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
285 talloc_destroy(mem_ctx);
286 return total_ea_len;
289 /****************************************************************************
290 Ensure the EA name is case insensitive by matching any existing EA name.
291 ****************************************************************************/
293 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
295 size_t total_ea_len;
296 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
297 struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
299 for (; ea_list; ea_list = ea_list->next) {
300 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
301 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
302 &unix_ea_name[5], ea_list->ea.name));
303 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
304 break;
307 talloc_destroy(mem_ctx);
310 /****************************************************************************
311 Set or delete an extended attribute.
312 ****************************************************************************/
314 static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname,
315 char *pdata, int total_data)
317 unsigned int namelen;
318 unsigned int ealen;
319 int ret;
320 fstring unix_ea_name;
322 if (!lp_ea_support(SNUM(conn))) {
323 return NT_STATUS_EAS_NOT_SUPPORTED;
326 if (total_data < 8) {
327 return NT_STATUS_INVALID_PARAMETER;
330 if (IVAL(pdata,0) > total_data) {
331 DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data));
332 return NT_STATUS_INVALID_PARAMETER;
335 pdata += 4;
336 namelen = CVAL(pdata,1);
337 ealen = SVAL(pdata,2);
338 pdata += 4;
339 if (total_data < 8 + namelen + 1 + ealen) {
340 DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n",
341 (unsigned int)total_data, namelen, ealen));
342 return NT_STATUS_INVALID_PARAMETER;
345 if (pdata[namelen] != '\0') {
346 DEBUG(10,("set_ea: ea name not null terminated\n"));
347 return NT_STATUS_INVALID_PARAMETER;
350 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
351 pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE);
352 pdata += (namelen + 1);
354 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
356 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen));
357 if (ealen) {
358 DEBUG(10,("set_ea: data :\n"));
359 dump_data(10, pdata, ealen);
362 if (samba_private_attr_name(unix_ea_name)) {
363 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
364 return NT_STATUS_ACCESS_DENIED;
367 if (ealen == 0) {
368 /* Remove the attribute. */
369 if (fsp && (fsp->fd != -1)) {
370 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
371 unix_ea_name, fsp->fsp_name));
372 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
373 } else {
374 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
375 unix_ea_name, fname));
376 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
378 #ifdef ENOATTR
379 /* Removing a non existent attribute always succeeds. */
380 if (ret == -1 && errno == ENOATTR) {
381 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name));
382 ret = 0;
384 #endif
385 } else {
386 if (fsp && (fsp->fd != -1)) {
387 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
388 unix_ea_name, fsp->fsp_name));
389 ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0);
390 } else {
391 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
392 unix_ea_name, fname));
393 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0);
397 if (ret == -1) {
398 if (errno == ENOTSUP) {
399 return NT_STATUS_EAS_NOT_SUPPORTED;
401 return map_nt_error_from_unix(errno);
404 return NT_STATUS_OK;
407 /****************************************************************************
408 Send the required number of replies back.
409 We assume all fields other than the data fields are
410 set correctly for the type of call.
411 HACK ! Always assumes smb_setup field is zero.
412 ****************************************************************************/
414 static int send_trans2_replies(char *outbuf,
415 int bufsize,
416 char *params,
417 int paramsize,
418 char *pdata,
419 int datasize)
421 /* As we are using a protocol > LANMAN1 then the max_send
422 variable must have been set in the sessetupX call.
423 This takes precedence over the max_xmit field in the
424 global struct. These different max_xmit variables should
425 be merged as this is now too confusing */
427 extern int max_send;
428 int data_to_send = datasize;
429 int params_to_send = paramsize;
430 int useable_space;
431 char *pp = params;
432 char *pd = pdata;
433 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
434 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
435 int data_alignment_offset = 0;
437 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
439 set_message(outbuf,10,0,True);
441 /* If there genuinely are no parameters or data to send just send the empty packet */
443 if(params_to_send == 0 && data_to_send == 0) {
444 if (!send_smb(smbd_server_fd(),outbuf))
445 exit_server("send_trans2_replies: send_smb failed.");
446 return 0;
449 /* When sending params and data ensure that both are nicely aligned */
450 /* Only do this alignment when there is also data to send - else
451 can cause NT redirector problems. */
453 if (((params_to_send % 4) != 0) && (data_to_send != 0))
454 data_alignment_offset = 4 - (params_to_send % 4);
456 /* Space is bufsize minus Netbios over TCP header minus SMB header */
457 /* The alignment_offset is to align the param bytes on an even byte
458 boundary. NT 4.0 Beta needs this to work correctly. */
460 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
462 /* useable_space can never be more than max_send minus the alignment offset. */
464 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
466 while (params_to_send || data_to_send) {
467 /* Calculate whether we will totally or partially fill this packet */
469 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
471 /* We can never send more than useable_space */
473 * Note that 'useable_space' does not include the alignment offsets,
474 * but we must include the alignment offsets in the calculation of
475 * the length of the data we send over the wire, as the alignment offsets
476 * are sent here. Fix from Marc_Jacobsen@hp.com.
479 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
481 set_message(outbuf, 10, total_sent_thistime, True);
483 /* Set total params and data to be sent */
484 SSVAL(outbuf,smb_tprcnt,paramsize);
485 SSVAL(outbuf,smb_tdrcnt,datasize);
487 /* Calculate how many parameters and data we can fit into
488 * this packet. Parameters get precedence
491 params_sent_thistime = MIN(params_to_send,useable_space);
492 data_sent_thistime = useable_space - params_sent_thistime;
493 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
495 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
497 /* smb_proff is the offset from the start of the SMB header to the
498 parameter bytes, however the first 4 bytes of outbuf are
499 the Netbios over TCP header. Thus use smb_base() to subtract
500 them from the calculation */
502 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
504 if(params_sent_thistime == 0)
505 SSVAL(outbuf,smb_prdisp,0);
506 else
507 /* Absolute displacement of param bytes sent in this packet */
508 SSVAL(outbuf,smb_prdisp,pp - params);
510 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
511 if(data_sent_thistime == 0) {
512 SSVAL(outbuf,smb_droff,0);
513 SSVAL(outbuf,smb_drdisp, 0);
514 } else {
515 /* The offset of the data bytes is the offset of the
516 parameter bytes plus the number of parameters being sent this time */
517 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
518 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
519 SSVAL(outbuf,smb_drdisp, pd - pdata);
522 /* Copy the param bytes into the packet */
524 if(params_sent_thistime)
525 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
527 /* Copy in the data bytes */
528 if(data_sent_thistime)
529 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
530 data_alignment_offset,pd,data_sent_thistime);
532 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
533 params_sent_thistime, data_sent_thistime, useable_space));
534 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
535 params_to_send, data_to_send, paramsize, datasize));
537 /* Send the packet */
538 if (!send_smb(smbd_server_fd(),outbuf))
539 exit_server("send_trans2_replies: send_smb failed.");
541 pp += params_sent_thistime;
542 pd += data_sent_thistime;
544 params_to_send -= params_sent_thistime;
545 data_to_send -= data_sent_thistime;
547 /* Sanity check */
548 if(params_to_send < 0 || data_to_send < 0) {
549 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
550 params_to_send, data_to_send));
551 return -1;
555 return 0;
558 /****************************************************************************
559 Reply to a TRANSACT2_OPEN.
560 ****************************************************************************/
562 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
563 char **pparams, int total_params, char **ppdata, int total_data)
565 char *params = *pparams;
566 int16 open_mode;
567 int16 open_attr;
568 BOOL oplock_request;
569 #if 0
570 BOOL return_additional_info;
571 int16 open_sattr;
572 time_t open_time;
573 #endif
574 int16 open_ofun;
575 int32 open_size;
576 char *pname;
577 pstring fname;
578 SMB_OFF_T size=0;
579 int fmode=0,mtime=0,rmode;
580 SMB_INO_T inode = 0;
581 SMB_STRUCT_STAT sbuf;
582 int smb_action = 0;
583 BOOL bad_path = False;
584 files_struct *fsp;
585 NTSTATUS status;
588 * Ensure we have enough parameters to perform the operation.
591 if (total_params < 29)
592 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
594 open_mode = SVAL(params, 2);
595 open_attr = SVAL(params,6);
596 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
597 #if 0
598 return_additional_info = BITSETW(params,0);
599 open_sattr = SVAL(params, 4);
600 open_time = make_unix_date3(params+8);
601 #endif
602 open_ofun = SVAL(params,12);
603 open_size = IVAL(params,14);
604 pname = &params[28];
606 if (IS_IPC(conn))
607 return(ERROR_DOS(ERRSRV,ERRaccess));
609 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);
610 if (!NT_STATUS_IS_OK(status)) {
611 return ERROR_NT(status);
614 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
615 fname,open_mode, open_attr, open_ofun, open_size));
617 /* XXXX we need to handle passed times, sattr and flags */
619 unix_convert(fname,conn,0,&bad_path,&sbuf);
621 if (!check_name(fname,conn)) {
622 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
625 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
626 oplock_request, &rmode,&smb_action);
628 if (!fsp) {
629 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
632 size = get_file_size(sbuf);
633 fmode = dos_mode(conn,fname,&sbuf);
634 mtime = sbuf.st_mtime;
635 inode = sbuf.st_ino;
636 if (fmode & aDIR) {
637 close_file(fsp,False);
638 return(ERROR_DOS(ERRDOS,ERRnoaccess));
641 /* Realloc the size of parameters and data we will return */
642 params = Realloc(*pparams, 28);
643 if( params == NULL )
644 return(ERROR_DOS(ERRDOS,ERRnomem));
645 *pparams = params;
647 memset((char *)params,'\0',28);
648 SSVAL(params,0,fsp->fnum);
649 SSVAL(params,2,fmode);
650 put_dos_date2(params,4, mtime);
651 SIVAL(params,8, (uint32)size);
652 SSVAL(params,12,rmode);
654 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
655 smb_action |= EXTENDED_OPLOCK_GRANTED;
657 SSVAL(params,18,smb_action);
660 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
662 SIVAL(params,20,inode);
664 /* Send the required number of replies */
665 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
667 return -1;
670 /*********************************************************
671 Routine to check if a given string matches exactly.
672 as a special case a mask of "." does NOT match. That
673 is required for correct wildcard semantics
674 Case can be significant or not.
675 **********************************************************/
677 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
679 if (mask[0] == '.' && mask[1] == 0)
680 return False;
681 if (case_sig)
682 return strcmp(str,mask)==0;
683 if (StrCaseCmp(str,mask) != 0) {
684 return False;
686 if (ms_has_wild(str)) {
687 return False;
689 return True;
692 /****************************************************************************
693 Return the filetype for UNIX extensions.
694 ****************************************************************************/
696 static uint32 unix_filetype(mode_t mode)
698 if(S_ISREG(mode))
699 return UNIX_TYPE_FILE;
700 else if(S_ISDIR(mode))
701 return UNIX_TYPE_DIR;
702 #ifdef S_ISLNK
703 else if(S_ISLNK(mode))
704 return UNIX_TYPE_SYMLINK;
705 #endif
706 #ifdef S_ISCHR
707 else if(S_ISCHR(mode))
708 return UNIX_TYPE_CHARDEV;
709 #endif
710 #ifdef S_ISBLK
711 else if(S_ISBLK(mode))
712 return UNIX_TYPE_BLKDEV;
713 #endif
714 #ifdef S_ISFIFO
715 else if(S_ISFIFO(mode))
716 return UNIX_TYPE_FIFO;
717 #endif
718 #ifdef S_ISSOCK
719 else if(S_ISSOCK(mode))
720 return UNIX_TYPE_SOCKET;
721 #endif
723 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
724 return UNIX_TYPE_UNKNOWN;
727 /****************************************************************************
728 Return the major devicenumber for UNIX extensions.
729 ****************************************************************************/
731 static uint32 unix_dev_major(SMB_DEV_T dev)
733 #if defined(HAVE_DEVICE_MAJOR_FN)
734 return (uint32)major(dev);
735 #else
736 return (uint32)(dev >> 8);
737 #endif
740 /****************************************************************************
741 Return the minor devicenumber for UNIX extensions.
742 ****************************************************************************/
744 static uint32 unix_dev_minor(SMB_DEV_T dev)
746 #if defined(HAVE_DEVICE_MINOR_FN)
747 return (uint32)minor(dev);
748 #else
749 return (uint32)(dev & 0xff);
750 #endif
753 /****************************************************************************
754 Map wire perms onto standard UNIX permissions. Obey share restrictions.
755 ****************************************************************************/
757 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
759 mode_t ret = 0;
761 if (perms == SMB_MODE_NO_CHANGE)
762 return pst->st_mode;
764 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
765 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
766 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
767 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
768 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
769 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
770 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
771 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
772 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
773 #ifdef S_ISVTX
774 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
775 #endif
776 #ifdef S_ISGID
777 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
778 #endif
779 #ifdef S_ISUID
780 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
781 #endif
783 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
784 ret &= lp_dir_mask(SNUM(conn));
785 /* Add in force bits */
786 ret |= lp_force_dir_mode(SNUM(conn));
787 } else {
788 /* Apply mode mask */
789 ret &= lp_create_mask(SNUM(conn));
790 /* Add in force bits */
791 ret |= lp_force_create_mode(SNUM(conn));
794 return ret;
797 /****************************************************************************
798 Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
799 ****************************************************************************/
801 time_t interpret_long_unix_date(char *p)
803 DEBUG(1,("interpret_long_unix_date\n"));
804 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
805 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
806 return -1;
807 } else {
808 return interpret_long_date(p);
812 /****************************************************************************
813 Get a level dependent lanman2 dir entry.
814 ****************************************************************************/
816 static BOOL get_lanman2_dir_entry(connection_struct *conn,
817 void *inbuf, void *outbuf,
818 char *path_mask,int dirtype,int info_level,
819 int requires_resume_key,
820 BOOL dont_descend,char **ppdata,
821 char *base_data, int space_remaining,
822 BOOL *out_of_space, BOOL *got_exact_match,
823 int *last_name_off)
825 const char *dname;
826 BOOL found = False;
827 SMB_STRUCT_STAT sbuf;
828 pstring mask;
829 pstring pathreal;
830 pstring fname;
831 char *p, *q, *pdata = *ppdata;
832 uint32 reskey=0;
833 int prev_dirpos=0;
834 int mode=0;
835 SMB_OFF_T file_size = 0;
836 SMB_BIG_UINT allocation_size = 0;
837 uint32 len;
838 time_t mdate=0, adate=0, cdate=0;
839 char *nameptr;
840 BOOL was_8_3;
841 int nt_extmode; /* Used for NT connections instead of mode */
842 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
844 *fname = 0;
845 *out_of_space = False;
846 *got_exact_match = False;
848 if (!conn->dirptr)
849 return(False);
851 p = strrchr_m(path_mask,'/');
852 if(p != NULL) {
853 if(p[1] == '\0')
854 pstrcpy(mask,"*.*");
855 else
856 pstrcpy(mask, p+1);
857 } else
858 pstrcpy(mask, path_mask);
860 while (!found) {
861 BOOL got_match;
863 /* Needed if we run out of space */
864 prev_dirpos = TellDir(conn->dirptr);
865 dname = ReadDirName(conn->dirptr);
868 * Due to bugs in NT client redirectors we are not using
869 * resume keys any more - set them to zero.
870 * Check out the related comments in findfirst/findnext.
871 * JRA.
874 reskey = 0;
876 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
877 (long)conn->dirptr,TellDir(conn->dirptr)));
879 if (!dname)
880 return(False);
882 pstrcpy(fname,dname);
884 if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
885 got_match = mask_match(fname, mask, case_sensitive);
887 if(!got_match && !mangle_is_8_3(fname, False)) {
890 * It turns out that NT matches wildcards against
891 * both long *and* short names. This may explain some
892 * of the wildcard wierdness from old DOS clients
893 * that some people have been seeing.... JRA.
896 pstring newname;
897 pstrcpy( newname, fname);
898 mangle_map( newname, True, False, SNUM(conn));
899 if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
900 got_match = mask_match(newname, mask, case_sensitive);
903 if(got_match) {
904 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
905 if (dont_descend && !isdots)
906 continue;
908 pstrcpy(pathreal,conn->dirpath);
909 if(needslash)
910 pstrcat(pathreal,"/");
911 pstrcat(pathreal,dname);
913 if (INFO_LEVEL_IS_UNIX(info_level)) {
914 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
915 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
916 pathreal,strerror(errno)));
917 continue;
919 } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
921 /* Needed to show the msdfs symlinks as
922 * directories */
924 if(lp_host_msdfs() &&
925 lp_msdfs_root(SNUM(conn)) &&
926 is_msdfs_link(conn, pathreal, NULL, NULL,
927 &sbuf)) {
929 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
930 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
932 } else {
934 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
935 pathreal,strerror(errno)));
936 continue;
940 mode = dos_mode(conn,pathreal,&sbuf);
942 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
943 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
944 continue;
947 file_size = get_file_size(sbuf);
948 allocation_size = get_allocation_size(NULL,&sbuf);
949 mdate = sbuf.st_mtime;
950 adate = sbuf.st_atime;
951 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
953 if (lp_dos_filetime_resolution(SNUM(conn))) {
954 cdate &= ~1;
955 mdate &= ~1;
956 adate &= ~1;
959 if(mode & aDIR)
960 file_size = 0;
962 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
964 found = True;
968 mangle_map(fname,False,True,SNUM(conn));
970 p = pdata;
971 nameptr = p;
973 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
975 switch (info_level) {
976 case SMB_INFO_STANDARD:
977 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_STANDARD\n"));
978 if(requires_resume_key) {
979 SIVAL(p,0,reskey);
980 p += 4;
982 put_dos_date2(p,l1_fdateCreation,cdate);
983 put_dos_date2(p,l1_fdateLastAccess,adate);
984 put_dos_date2(p,l1_fdateLastWrite,mdate);
985 SIVAL(p,l1_cbFile,(uint32)file_size);
986 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
987 SSVAL(p,l1_attrFile,mode);
988 p += l1_achName;
989 nameptr = p;
990 p += align_string(outbuf, p, 0);
991 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
992 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
993 if (len > 2) {
994 SCVAL(nameptr, -1, len - 2);
995 } else {
996 SCVAL(nameptr, -1, 0);
998 } else {
999 if (len > 1) {
1000 SCVAL(nameptr, -1, len - 1);
1001 } else {
1002 SCVAL(nameptr, -1, 0);
1005 p += len;
1006 break;
1008 case SMB_INFO_QUERY_EA_SIZE:
1009 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_QUERY_EA_SIZE\n"));
1010 if(requires_resume_key) {
1011 SIVAL(p,0,reskey);
1012 p += 4;
1014 put_dos_date2(p,l2_fdateCreation,cdate);
1015 put_dos_date2(p,l2_fdateLastAccess,adate);
1016 put_dos_date2(p,l2_fdateLastWrite,mdate);
1017 SIVAL(p,l2_cbFile,(uint32)file_size);
1018 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1019 SSVAL(p,l2_attrFile,mode);
1021 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1022 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1024 p += l2_achName;
1025 nameptr = p - 1;
1026 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1027 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1028 if (len > 2) {
1029 len -= 2;
1030 } else {
1031 len = 0;
1033 } else {
1034 if (len > 1) {
1035 len -= 1;
1036 } else {
1037 len = 0;
1040 SCVAL(nameptr,0,len);
1041 p += len;
1042 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1043 break;
1045 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1046 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1047 was_8_3 = mangle_is_8_3(fname, True);
1048 p += 4;
1049 SIVAL(p,0,reskey); p += 4;
1050 put_long_date(p,cdate); p += 8;
1051 put_long_date(p,adate); p += 8;
1052 put_long_date(p,mdate); p += 8;
1053 put_long_date(p,mdate); p += 8;
1054 SOFF_T(p,0,file_size); p += 8;
1055 SOFF_T(p,0,allocation_size); p += 8;
1056 SIVAL(p,0,nt_extmode); p += 4;
1057 q = p; p += 4; /* q is placeholder for name length. */
1059 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1060 SIVAL(p,0,ea_size); /* Extended attributes */
1061 p += 4;
1063 /* Clear the short name buffer. This is
1064 * IMPORTANT as not doing so will trigger
1065 * a Win2k client bug. JRA.
1067 memset(p,'\0',26);
1068 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1069 pstring mangled_name;
1070 pstrcpy(mangled_name, fname);
1071 mangle_map(mangled_name,True,True,SNUM(conn));
1072 mangled_name[12] = 0;
1073 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1074 SSVAL(p, 0, len);
1075 } else {
1076 SSVAL(p,0,0);
1077 *(p+2) = 0;
1079 p += 2 + 24;
1080 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1081 SIVAL(q,0,len);
1082 p += len;
1083 len = PTR_DIFF(p, pdata);
1084 len = (len + 3) & ~3;
1085 SIVAL(pdata,0,len);
1086 p = pdata + len;
1087 break;
1089 case SMB_FIND_FILE_DIRECTORY_INFO:
1090 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1091 p += 4;
1092 SIVAL(p,0,reskey); p += 4;
1093 put_long_date(p,cdate); p += 8;
1094 put_long_date(p,adate); p += 8;
1095 put_long_date(p,mdate); p += 8;
1096 put_long_date(p,mdate); p += 8;
1097 SOFF_T(p,0,file_size); p += 8;
1098 SOFF_T(p,0,allocation_size); p += 8;
1099 SIVAL(p,0,nt_extmode); p += 4;
1100 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1101 SIVAL(p,0,len);
1102 p += 4 + len;
1103 len = PTR_DIFF(p, pdata);
1104 len = (len + 3) & ~3;
1105 SIVAL(pdata,0,len);
1106 p = pdata + len;
1107 break;
1109 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1110 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1111 p += 4;
1112 SIVAL(p,0,reskey); p += 4;
1113 put_long_date(p,cdate); p += 8;
1114 put_long_date(p,adate); p += 8;
1115 put_long_date(p,mdate); p += 8;
1116 put_long_date(p,mdate); p += 8;
1117 SOFF_T(p,0,file_size); p += 8;
1118 SOFF_T(p,0,allocation_size); p += 8;
1119 SIVAL(p,0,nt_extmode); p += 4;
1120 q = p; p += 4; /* q is placeholder for name length. */
1122 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1123 SIVAL(p,0,ea_size); /* Extended attributes */
1124 p +=4;
1126 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1127 SIVAL(q, 0, len);
1128 p += len;
1130 len = PTR_DIFF(p, pdata);
1131 len = (len + 3) & ~3;
1132 SIVAL(pdata,0,len);
1133 p = pdata + len;
1134 break;
1136 case SMB_FIND_FILE_NAMES_INFO:
1137 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1138 p += 4;
1139 SIVAL(p,0,reskey); p += 4;
1140 p += 4;
1141 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1142 acl on a dir (tridge) */
1143 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1144 SIVAL(p, -4, len);
1145 p += len;
1146 len = PTR_DIFF(p, pdata);
1147 len = (len + 3) & ~3;
1148 SIVAL(pdata,0,len);
1149 p = pdata + len;
1150 break;
1152 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1153 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1154 p += 4;
1155 SIVAL(p,0,reskey); p += 4;
1156 put_long_date(p,cdate); p += 8;
1157 put_long_date(p,adate); p += 8;
1158 put_long_date(p,mdate); p += 8;
1159 put_long_date(p,mdate); p += 8;
1160 SOFF_T(p,0,file_size); p += 8;
1161 SOFF_T(p,0,allocation_size); p += 8;
1162 SIVAL(p,0,nt_extmode); p += 4;
1163 q = p; p += 4; /* q is placeholder for name length. */
1165 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1166 SIVAL(p,0,ea_size); /* Extended attributes */
1167 p +=4;
1169 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1170 SIVAL(p,0,sbuf.st_dev); p += 4;
1171 SIVAL(p,0,sbuf.st_ino); p += 4;
1172 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1173 SIVAL(q, 0, len);
1174 p += len;
1175 len = PTR_DIFF(p, pdata);
1176 len = (len + 3) & ~3;
1177 SIVAL(pdata,0,len);
1178 p = pdata + len;
1179 break;
1181 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1182 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1183 was_8_3 = mangle_is_8_3(fname, True);
1184 p += 4;
1185 SIVAL(p,0,reskey); p += 4;
1186 put_long_date(p,cdate); p += 8;
1187 put_long_date(p,adate); p += 8;
1188 put_long_date(p,mdate); p += 8;
1189 put_long_date(p,mdate); p += 8;
1190 SOFF_T(p,0,file_size); p += 8;
1191 SOFF_T(p,0,allocation_size); p += 8;
1192 SIVAL(p,0,nt_extmode); p += 4;
1193 q = p; p += 4; /* q is placeholder for name length */
1195 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1196 SIVAL(p,0,ea_size); /* Extended attributes */
1197 p +=4;
1199 /* Clear the short name buffer. This is
1200 * IMPORTANT as not doing so will trigger
1201 * a Win2k client bug. JRA.
1203 memset(p,'\0',26);
1204 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1205 pstring mangled_name;
1206 pstrcpy(mangled_name, fname);
1207 mangle_map(mangled_name,True,True,SNUM(conn));
1208 mangled_name[12] = 0;
1209 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1210 SSVAL(p, 0, len);
1211 } else {
1212 SSVAL(p,0,0);
1213 *(p+2) = 0;
1215 p += 26;
1216 SSVAL(p,0,0); p += 2; /* Reserved ? */
1217 SIVAL(p,0,sbuf.st_dev); p += 4;
1218 SIVAL(p,0,sbuf.st_ino); p += 4;
1219 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1220 SIVAL(q,0,len);
1221 p += len;
1222 len = PTR_DIFF(p, pdata);
1223 len = (len + 3) & ~3;
1224 SIVAL(pdata,0,len);
1225 p = pdata + len;
1226 break;
1228 /* CIFS UNIX Extension. */
1230 case SMB_FIND_FILE_UNIX:
1231 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1232 p+= 4;
1233 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1235 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1236 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1237 p+= 8;
1239 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1240 p+= 8;
1242 put_long_date(p,sbuf.st_ctime); /* Creation Time 64 Bit */
1243 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1244 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1245 p+= 24;
1247 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1248 SIVAL(p,4,0);
1249 p+= 8;
1251 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1252 SIVAL(p,4,0);
1253 p+= 8;
1255 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1256 p+= 4;
1258 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1259 SIVAL(p,4,0);
1260 p+= 8;
1262 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1263 SIVAL(p,4,0);
1264 p+= 8;
1266 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1267 p+= 8;
1269 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1270 SIVAL(p,4,0);
1271 p+= 8;
1273 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1274 SIVAL(p,4,0);
1275 p+= 8;
1277 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1278 p += len;
1280 len = PTR_DIFF(p, pdata);
1281 len = (len + 3) & ~3;
1282 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1283 p = pdata + len;
1284 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1286 break;
1288 default:
1289 return(False);
1293 if (PTR_DIFF(p,pdata) > space_remaining) {
1294 /* Move the dirptr back to prev_dirpos */
1295 SeekDir(conn->dirptr, prev_dirpos);
1296 *out_of_space = True;
1297 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1298 return False; /* Not finished - just out of space */
1301 /* Setup the last_filename pointer, as an offset from base_data */
1302 *last_name_off = PTR_DIFF(nameptr,base_data);
1303 /* Advance the data pointer to the next slot */
1304 *ppdata = p;
1306 return(found);
1309 /****************************************************************************
1310 Reply to a TRANS2_FINDFIRST.
1311 ****************************************************************************/
1313 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1314 char **pparams, int total_params, char **ppdata, int total_data)
1316 /* We must be careful here that we don't return more than the
1317 allowed number of data bytes. If this means returning fewer than
1318 maxentries then so be it. We assume that the redirector has
1319 enough room for the fixed number of parameter bytes it has
1320 requested. */
1321 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1322 char *params = *pparams;
1323 char *pdata = *ppdata;
1324 int dirtype = SVAL(params,0);
1325 int maxentries = SVAL(params,2);
1326 BOOL close_after_first = BITSETW(params+4,0);
1327 BOOL close_if_end = BITSETW(params+4,1);
1328 BOOL requires_resume_key = BITSETW(params+4,2);
1329 int info_level = SVAL(params,6);
1330 pstring directory;
1331 pstring mask;
1332 char *p, *wcard;
1333 int last_name_off=0;
1334 int dptr_num = -1;
1335 int numentries = 0;
1336 int i;
1337 BOOL finished = False;
1338 BOOL dont_descend = False;
1339 BOOL out_of_space = False;
1340 int space_remaining;
1341 BOOL bad_path = False;
1342 SMB_STRUCT_STAT sbuf;
1343 NTSTATUS ntstatus = NT_STATUS_OK;
1345 if (total_params < 12)
1346 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1348 *directory = *mask = 0;
1350 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1351 close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
1352 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1353 info_level, max_data_bytes));
1355 switch (info_level) {
1356 case SMB_INFO_STANDARD:
1357 case SMB_INFO_QUERY_EA_SIZE:
1358 case SMB_FIND_FILE_DIRECTORY_INFO:
1359 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1360 case SMB_FIND_FILE_NAMES_INFO:
1361 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1362 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1363 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1364 break;
1365 case SMB_FIND_FILE_UNIX:
1366 if (!lp_unix_extensions())
1367 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1368 break;
1369 default:
1370 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1373 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus);
1374 if (!NT_STATUS_IS_OK(ntstatus)) {
1375 return ERROR_NT(ntstatus);
1378 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
1380 unix_convert(directory,conn,0,&bad_path,&sbuf);
1381 if(!check_name(directory,conn)) {
1382 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1385 p = strrchr_m(directory,'/');
1386 if(p == NULL) {
1387 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1388 if((directory[0] == '.') && (directory[1] == '\0'))
1389 pstrcpy(mask,"*");
1390 else
1391 pstrcpy(mask,directory);
1392 pstrcpy(directory,"./");
1393 } else {
1394 pstrcpy(mask,p+1);
1395 *p = 0;
1398 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1400 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1401 if( pdata == NULL )
1402 return(ERROR_DOS(ERRDOS,ERRnomem));
1404 *ppdata = pdata;
1405 memset((char *)pdata,'\0',max_data_bytes + 1024);
1407 /* Realloc the params space */
1408 params = Realloc(*pparams, 10);
1409 if (params == NULL)
1410 return ERROR_DOS(ERRDOS,ERRnomem);
1411 *pparams = params;
1413 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1414 if (dptr_num < 0)
1415 return(UNIXERROR(ERRDOS,ERRbadfile));
1417 /* Save the wildcard match and attribs we are using on this directory -
1418 needed as lanman2 assumes these are being saved between calls */
1420 if(!(wcard = strdup(mask))) {
1421 dptr_close(&dptr_num);
1422 return ERROR_DOS(ERRDOS,ERRnomem);
1425 dptr_set_wcard(dptr_num, wcard);
1426 dptr_set_attr(dptr_num, dirtype);
1428 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
1430 /* We don't need to check for VOL here as this is returned by
1431 a different TRANS2 call. */
1433 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1434 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1435 dont_descend = True;
1437 p = pdata;
1438 space_remaining = max_data_bytes;
1439 out_of_space = False;
1441 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1442 BOOL got_exact_match = False;
1444 /* this is a heuristic to avoid seeking the dirptr except when
1445 absolutely necessary. It allows for a filename of about 40 chars */
1446 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1447 out_of_space = True;
1448 finished = False;
1449 } else {
1450 finished = !get_lanman2_dir_entry(conn,
1451 inbuf, outbuf,
1452 mask,dirtype,info_level,
1453 requires_resume_key,dont_descend,
1454 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1455 &last_name_off);
1458 if (finished && out_of_space)
1459 finished = False;
1461 if (!finished && !out_of_space)
1462 numentries++;
1465 * As an optimisation if we know we aren't looking
1466 * for a wildcard name (ie. the name matches the wildcard exactly)
1467 * then we can finish on any (first) match.
1468 * This speeds up large directory searches. JRA.
1471 if(got_exact_match)
1472 finished = True;
1474 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1477 /* Check if we can close the dirptr */
1478 if(close_after_first || (finished && close_if_end)) {
1479 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1480 dptr_close(&dptr_num);
1484 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1485 * from observation of NT.
1488 if(numentries == 0) {
1489 dptr_close(&dptr_num);
1490 return ERROR_DOS(ERRDOS,ERRbadfile);
1493 /* At this point pdata points to numentries directory entries. */
1495 /* Set up the return parameter block */
1496 SSVAL(params,0,dptr_num);
1497 SSVAL(params,2,numentries);
1498 SSVAL(params,4,finished);
1499 SSVAL(params,6,0); /* Never an EA error */
1500 SSVAL(params,8,last_name_off);
1502 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1504 if ((! *directory) && dptr_path(dptr_num))
1505 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1507 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1508 smb_fn_name(CVAL(inbuf,smb_com)),
1509 mask, directory, dirtype, numentries ) );
1512 * Force a name mangle here to ensure that the
1513 * mask as an 8.3 name is top of the mangled cache.
1514 * The reasons for this are subtle. Don't remove
1515 * this code unless you know what you are doing
1516 * (see PR#13758). JRA.
1519 if(!mangle_is_8_3_wildcards( mask, False))
1520 mangle_map(mask, True, True, SNUM(conn));
1522 return(-1);
1525 /****************************************************************************
1526 Reply to a TRANS2_FINDNEXT.
1527 ****************************************************************************/
1529 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1530 char **pparams, int total_params, char **ppdata, int total_data)
1532 /* We must be careful here that we don't return more than the
1533 allowed number of data bytes. If this means returning fewer than
1534 maxentries then so be it. We assume that the redirector has
1535 enough room for the fixed number of parameter bytes it has
1536 requested. */
1537 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1538 char *params = *pparams;
1539 char *pdata = *ppdata;
1540 int dptr_num = SVAL(params,0);
1541 int maxentries = SVAL(params,2);
1542 uint16 info_level = SVAL(params,4);
1543 uint32 resume_key = IVAL(params,6);
1544 BOOL close_after_request = BITSETW(params+10,0);
1545 BOOL close_if_end = BITSETW(params+10,1);
1546 BOOL requires_resume_key = BITSETW(params+10,2);
1547 BOOL continue_bit = BITSETW(params+10,3);
1548 pstring resume_name;
1549 pstring mask;
1550 pstring directory;
1551 char *p;
1552 uint16 dirtype;
1553 int numentries = 0;
1554 int i, last_name_off=0;
1555 BOOL finished = False;
1556 BOOL dont_descend = False;
1557 BOOL out_of_space = False;
1558 int space_remaining;
1559 NTSTATUS ntstatus = NT_STATUS_OK;
1561 if (total_params < 12)
1562 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1564 *mask = *directory = *resume_name = 0;
1566 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus);
1567 if (!NT_STATUS_IS_OK(ntstatus)) {
1568 return ERROR_NT(ntstatus);
1571 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1572 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1573 resume_key = %d resume name = %s continue=%d level = %d\n",
1574 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1575 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1577 switch (info_level) {
1578 case SMB_INFO_STANDARD:
1579 case SMB_INFO_QUERY_EA_SIZE:
1580 case SMB_FIND_FILE_DIRECTORY_INFO:
1581 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1582 case SMB_FIND_FILE_NAMES_INFO:
1583 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1584 break;
1585 case SMB_FIND_FILE_UNIX:
1586 if (!lp_unix_extensions())
1587 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1588 break;
1589 default:
1590 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1593 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1594 if(pdata == NULL)
1595 return ERROR_DOS(ERRDOS,ERRnomem);
1597 *ppdata = pdata;
1598 memset((char *)pdata,'\0',max_data_bytes + 1024);
1600 /* Realloc the params space */
1601 params = Realloc(*pparams, 6*SIZEOFWORD);
1602 if( params == NULL )
1603 return ERROR_DOS(ERRDOS,ERRnomem);
1605 *pparams = params;
1607 /* Check that the dptr is valid */
1608 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1609 return ERROR_DOS(ERRDOS,ERRnofiles);
1611 string_set(&conn->dirpath,dptr_path(dptr_num));
1613 /* Get the wildcard mask from the dptr */
1614 if((p = dptr_wcard(dptr_num))== NULL) {
1615 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1616 return ERROR_DOS(ERRDOS,ERRnofiles);
1619 pstrcpy(mask, p);
1620 pstrcpy(directory,conn->dirpath);
1622 /* Get the attr mask from the dptr */
1623 dirtype = dptr_attr(dptr_num);
1625 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1626 dptr_num, mask, dirtype,
1627 (long)conn->dirptr,
1628 TellDir(conn->dirptr)));
1630 /* We don't need to check for VOL here as this is returned by
1631 a different TRANS2 call. */
1633 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1634 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1635 dont_descend = True;
1637 p = pdata;
1638 space_remaining = max_data_bytes;
1639 out_of_space = False;
1642 * Seek to the correct position. We no longer use the resume key but
1643 * depend on the last file name instead.
1646 if(requires_resume_key && *resume_name && !continue_bit) {
1649 * Fix for NT redirector problem triggered by resume key indexes
1650 * changing between directory scans. We now return a resume key of 0
1651 * and instead look for the filename to continue from (also given
1652 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1653 * findfirst/findnext (as is usual) then the directory pointer
1654 * should already be at the correct place. Check this by scanning
1655 * backwards looking for an exact (ie. case sensitive) filename match.
1656 * If we get to the beginning of the directory and haven't found it then scan
1657 * forwards again looking for a match. JRA.
1660 int current_pos, start_pos;
1661 const char *dname = NULL;
1662 pstring dname_pstring;
1663 void *dirptr = conn->dirptr;
1664 start_pos = TellDir(dirptr);
1665 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1666 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1668 SeekDir(dirptr, current_pos);
1669 dname = ReadDirName(dirptr);
1670 if (dname) {
1672 * Remember, mangle_map is called by
1673 * get_lanman2_dir_entry(), so the resume name
1674 * could be mangled. Ensure we do the same
1675 * here.
1678 /* make sure we get a copy that mangle_map can modify */
1680 pstrcpy(dname_pstring, dname);
1681 mangle_map( dname_pstring, False, True, SNUM(conn));
1683 if(strcsequal( resume_name, dname_pstring)) {
1684 SeekDir(dirptr, current_pos+1);
1685 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1686 break;
1692 * Scan forward from start if not found going backwards.
1695 if(current_pos < 0) {
1696 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1697 SeekDir(dirptr, start_pos);
1698 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1701 * Remember, mangle_map is called by
1702 * get_lanman2_dir_entry(), so the resume name
1703 * could be mangled. Ensure we do the same
1704 * here.
1707 if(dname) {
1708 /* make sure we get a copy that mangle_map can modify */
1710 pstrcpy(dname_pstring, dname);
1711 mangle_map(dname_pstring, False, True, SNUM(conn));
1713 if(strcsequal( resume_name, dname_pstring)) {
1714 SeekDir(dirptr, current_pos+1);
1715 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1716 break;
1719 } /* end for */
1720 } /* end if current_pos */
1721 } /* end if requires_resume_key && !continue_bit */
1723 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1724 BOOL got_exact_match = False;
1726 /* this is a heuristic to avoid seeking the dirptr except when
1727 absolutely necessary. It allows for a filename of about 40 chars */
1728 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1729 out_of_space = True;
1730 finished = False;
1731 } else {
1732 finished = !get_lanman2_dir_entry(conn,
1733 inbuf, outbuf,
1734 mask,dirtype,info_level,
1735 requires_resume_key,dont_descend,
1736 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1737 &last_name_off);
1740 if (finished && out_of_space)
1741 finished = False;
1743 if (!finished && !out_of_space)
1744 numentries++;
1747 * As an optimisation if we know we aren't looking
1748 * for a wildcard name (ie. the name matches the wildcard exactly)
1749 * then we can finish on any (first) match.
1750 * This speeds up large directory searches. JRA.
1753 if(got_exact_match)
1754 finished = True;
1756 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1759 /* Check if we can close the dirptr */
1760 if(close_after_request || (finished && close_if_end)) {
1761 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1762 dptr_close(&dptr_num); /* This frees up the saved mask */
1765 /* Set up the return parameter block */
1766 SSVAL(params,0,numentries);
1767 SSVAL(params,2,finished);
1768 SSVAL(params,4,0); /* Never an EA error */
1769 SSVAL(params,6,last_name_off);
1771 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1773 if ((! *directory) && dptr_path(dptr_num))
1774 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1776 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1777 smb_fn_name(CVAL(inbuf,smb_com)),
1778 mask, directory, dirtype, numentries ) );
1780 return(-1);
1783 /****************************************************************************
1784 Reply to a TRANS2_QFSINFO (query filesystem info).
1785 ****************************************************************************/
1787 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1788 int length, int bufsize,
1789 char **pparams, int total_params, char **ppdata, int total_data)
1791 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1792 char *pdata = *ppdata;
1793 char *params = *pparams;
1794 uint16 info_level = SVAL(params,0);
1795 int data_len, len;
1796 SMB_STRUCT_STAT st;
1797 char *vname = volume_label(SNUM(conn));
1798 int snum = SNUM(conn);
1799 char *fstype = lp_fstype(SNUM(conn));
1800 int quota_flag = 0;
1802 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1804 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1805 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1806 return ERROR_DOS(ERRSRV,ERRinvdevice);
1809 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1810 if ( pdata == NULL )
1811 return ERROR_DOS(ERRDOS,ERRnomem);
1813 *ppdata = pdata;
1814 memset((char *)pdata,'\0',max_data_bytes + 1024);
1816 switch (info_level) {
1817 case SMB_INFO_ALLOCATION:
1819 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1820 data_len = 18;
1821 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1822 block_size = lp_block_size(snum);
1823 if (bsize < block_size) {
1824 SMB_BIG_UINT factor = block_size/bsize;
1825 bsize = block_size;
1826 dsize /= factor;
1827 dfree /= factor;
1829 if (bsize > block_size) {
1830 SMB_BIG_UINT factor = bsize/block_size;
1831 bsize = block_size;
1832 dsize *= factor;
1833 dfree *= factor;
1835 bytes_per_sector = 512;
1836 sectors_per_unit = bsize/bytes_per_sector;
1838 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1839 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1840 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1842 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1843 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1844 SIVAL(pdata,l1_cUnit,dsize);
1845 SIVAL(pdata,l1_cUnitAvail,dfree);
1846 SSVAL(pdata,l1_cbSector,bytes_per_sector);
1847 break;
1850 case SMB_INFO_VOLUME:
1851 /* Return volume name */
1853 * Add volume serial number - hash of a combination of
1854 * the called hostname and the service name.
1856 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1857 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1858 SCVAL(pdata,l2_vol_cch,len);
1859 data_len = l2_vol_szVolLabel + len;
1860 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1861 (unsigned)st.st_ctime, len, vname));
1862 break;
1864 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1865 case SMB_FS_ATTRIBUTE_INFORMATION:
1868 #if defined(HAVE_SYS_QUOTAS)
1869 quota_flag = FILE_VOLUME_QUOTAS;
1870 #endif
1872 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1873 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1874 quota_flag); /* FS ATTRIBUTES */
1876 SIVAL(pdata,4,255); /* Max filename component length */
1877 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1878 and will think we can't do long filenames */
1879 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1880 SIVAL(pdata,8,len);
1881 data_len = 12 + len;
1882 break;
1884 case SMB_QUERY_FS_LABEL_INFO:
1885 case SMB_FS_LABEL_INFORMATION:
1886 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1887 data_len = 4 + len;
1888 SIVAL(pdata,0,len);
1889 break;
1891 case SMB_QUERY_FS_VOLUME_INFO:
1892 case SMB_FS_VOLUME_INFORMATION:
1895 * Add volume serial number - hash of a combination of
1896 * the called hostname and the service name.
1898 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1899 (str_checksum(local_machine)<<16));
1901 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1902 SIVAL(pdata,12,len);
1903 data_len = 18+len;
1904 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1905 (int)strlen(vname),vname, lp_servicename(snum)));
1906 break;
1908 case SMB_QUERY_FS_SIZE_INFO:
1909 case SMB_FS_SIZE_INFORMATION:
1911 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1912 data_len = 24;
1913 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1914 block_size = lp_block_size(snum);
1915 if (bsize < block_size) {
1916 SMB_BIG_UINT factor = block_size/bsize;
1917 bsize = block_size;
1918 dsize /= factor;
1919 dfree /= factor;
1921 if (bsize > block_size) {
1922 SMB_BIG_UINT factor = bsize/block_size;
1923 bsize = block_size;
1924 dsize *= factor;
1925 dfree *= factor;
1927 bytes_per_sector = 512;
1928 sectors_per_unit = bsize/bytes_per_sector;
1929 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1930 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1931 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1932 SBIG_UINT(pdata,0,dsize);
1933 SBIG_UINT(pdata,8,dfree);
1934 SIVAL(pdata,16,sectors_per_unit);
1935 SIVAL(pdata,20,bytes_per_sector);
1936 break;
1939 case SMB_FS_FULL_SIZE_INFORMATION:
1941 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1942 data_len = 32;
1943 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1944 block_size = lp_block_size(snum);
1945 if (bsize < block_size) {
1946 SMB_BIG_UINT factor = block_size/bsize;
1947 bsize = block_size;
1948 dsize /= factor;
1949 dfree /= factor;
1951 if (bsize > block_size) {
1952 SMB_BIG_UINT factor = bsize/block_size;
1953 bsize = block_size;
1954 dsize *= factor;
1955 dfree *= factor;
1957 bytes_per_sector = 512;
1958 sectors_per_unit = bsize/bytes_per_sector;
1959 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1960 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1961 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1962 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1963 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1964 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1965 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1966 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1967 break;
1970 case SMB_QUERY_FS_DEVICE_INFO:
1971 case SMB_FS_DEVICE_INFORMATION:
1972 data_len = 8;
1973 SIVAL(pdata,0,0); /* dev type */
1974 SIVAL(pdata,4,0); /* characteristics */
1975 break;
1977 #ifdef HAVE_SYS_QUOTAS
1978 case SMB_FS_QUOTA_INFORMATION:
1980 * what we have to send --metze:
1982 * Unknown1: 24 NULL bytes
1983 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1984 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
1985 * Quota Flags: 2 byte :
1986 * Unknown3: 6 NULL bytes
1988 * 48 bytes total
1990 * details for Quota Flags:
1992 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1993 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
1994 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1995 * 0x0001 Enable Quotas: enable quota for this fs
1999 /* we need to fake up a fsp here,
2000 * because its not send in this call
2002 files_struct fsp;
2003 SMB_NTQUOTA_STRUCT quotas;
2005 ZERO_STRUCT(fsp);
2006 ZERO_STRUCT(quotas);
2008 fsp.conn = conn;
2009 fsp.fnum = -1;
2010 fsp.fd = -1;
2012 /* access check */
2013 if (conn->admin_user != True) {
2014 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2015 lp_servicename(SNUM(conn)),conn->user));
2016 return ERROR_DOS(ERRDOS,ERRnoaccess);
2019 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2020 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2021 return ERROR_DOS(ERRSRV,ERRerror);
2024 data_len = 48;
2026 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2028 /* Unknown1 24 NULL bytes*/
2029 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2030 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2031 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2033 /* Default Soft Quota 8 bytes */
2034 SBIG_UINT(pdata,24,quotas.softlim);
2036 /* Default Hard Quota 8 bytes */
2037 SBIG_UINT(pdata,32,quotas.hardlim);
2039 /* Quota flag 2 bytes */
2040 SSVAL(pdata,40,quotas.qflags);
2042 /* Unknown3 6 NULL bytes */
2043 SSVAL(pdata,42,0);
2044 SIVAL(pdata,44,0);
2046 break;
2048 #endif /* HAVE_SYS_QUOTAS */
2049 case SMB_FS_OBJECTID_INFORMATION:
2050 data_len = 64;
2051 break;
2054 * Query the version and capabilities of the CIFS UNIX extensions
2055 * in use.
2058 case SMB_QUERY_CIFS_UNIX_INFO:
2059 if (!lp_unix_extensions())
2060 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2061 data_len = 12;
2062 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2063 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2064 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
2065 break;
2067 case SMB_MAC_QUERY_FS_INFO:
2069 * Thursby MAC extension... ONLY on NTFS filesystems
2070 * once we do streams then we don't need this
2072 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2073 data_len = 88;
2074 SIVAL(pdata,84,0x100); /* Don't support mac... */
2075 break;
2077 /* drop through */
2078 default:
2079 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2083 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2085 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2087 return -1;
2090 #ifdef HAVE_SYS_QUOTAS
2091 /****************************************************************************
2092 Reply to a TRANS2_SETFSINFO (set filesystem info).
2093 ****************************************************************************/
2095 static int call_trans2setfsinfo(connection_struct *conn,
2096 char *inbuf, char *outbuf, int length, int bufsize,
2097 char **pparams, int total_params, char **ppdata, int total_data)
2099 char *pdata = *ppdata;
2100 char *params = *pparams;
2101 files_struct *fsp = NULL;
2102 uint16 info_level;
2103 int outsize;
2104 SMB_NTQUOTA_STRUCT quotas;
2106 ZERO_STRUCT(quotas);
2108 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2110 /* access check */
2111 if ((conn->admin_user != True)||!CAN_WRITE(conn)) {
2112 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2113 lp_servicename(SNUM(conn)),conn->user));
2114 return ERROR_DOS(ERRSRV,ERRaccess);
2117 /* */
2118 if (total_params < 4) {
2119 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2120 total_params));
2121 return ERROR_DOS(ERRDOS,ERRinvalidparam);
2124 fsp = file_fsp(params,0);
2126 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2127 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2128 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2131 info_level = SVAL(params,2);
2133 switch(info_level) {
2134 case SMB_FS_QUOTA_INFORMATION:
2135 /* note: normaly there're 48 bytes,
2136 * but we didn't use the last 6 bytes for now
2137 * --metze
2139 if (total_data < 42) {
2140 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2141 total_data));
2142 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2145 /* unknown_1 24 NULL bytes in pdata*/
2147 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2148 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2149 #ifdef LARGE_SMB_OFF_T
2150 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2151 #else /* LARGE_SMB_OFF_T */
2152 if ((IVAL(pdata,28) != 0)&&
2153 ((quotas.softlim != 0xFFFFFFFF)||
2154 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2155 /* more than 32 bits? */
2156 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2158 #endif /* LARGE_SMB_OFF_T */
2160 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2161 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2162 #ifdef LARGE_SMB_OFF_T
2163 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2164 #else /* LARGE_SMB_OFF_T */
2165 if ((IVAL(pdata,36) != 0)&&
2166 ((quotas.hardlim != 0xFFFFFFFF)||
2167 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2168 /* more than 32 bits? */
2169 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2171 #endif /* LARGE_SMB_OFF_T */
2173 /* quota_flags 2 bytes **/
2174 quotas.qflags = SVAL(pdata,40);
2176 /* unknown_2 6 NULL bytes follow*/
2178 /* now set the quotas */
2179 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2180 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2181 return ERROR_DOS(ERRSRV,ERRerror);
2184 break;
2185 default:
2186 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2187 info_level));
2188 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2189 break;
2193 * sending this reply works fine,
2194 * but I'm not sure it's the same
2195 * like windows do...
2196 * --metze
2198 outsize = set_message(outbuf,10,0,True);
2200 return outsize;
2202 #endif /* HAVE_SYS_QUOTAS */
2204 /****************************************************************************
2205 * Utility function to set bad path error.
2206 ****************************************************************************/
2208 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2210 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2211 err, (int)bad_path ));
2213 if(err == ENOENT) {
2214 if (bad_path) {
2215 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2216 } else {
2217 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2220 return UNIXERROR(def_class,def_code);
2223 /****************************************************************************
2224 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2225 file name or file id).
2226 ****************************************************************************/
2228 static int call_trans2qfilepathinfo(connection_struct *conn,
2229 char *inbuf, char *outbuf, int length,
2230 int bufsize,
2231 char **pparams, int total_params, char **ppdata, int total_data)
2233 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
2234 char *params = *pparams;
2235 char *pdata = *ppdata;
2236 uint16 tran_call = SVAL(inbuf, smb_setup0);
2237 uint16 info_level;
2238 int mode=0;
2239 SMB_OFF_T file_size=0;
2240 SMB_BIG_UINT allocation_size=0;
2241 unsigned int data_size;
2242 unsigned int param_size = 2;
2243 SMB_STRUCT_STAT sbuf;
2244 pstring fname, dos_fname;
2245 char *fullpathname;
2246 char *base_name;
2247 char *p;
2248 SMB_OFF_T pos = 0;
2249 BOOL bad_path = False;
2250 BOOL delete_pending = False;
2251 int len;
2252 time_t c_time;
2253 files_struct *fsp = NULL;
2254 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2256 if (!params)
2257 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2259 if (tran_call == TRANSACT2_QFILEINFO) {
2260 if (total_params < 4)
2261 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2263 fsp = file_fsp(params,0);
2264 info_level = SVAL(params,2);
2266 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2268 if(fsp && (fsp->fake_file_handle)) {
2270 * This is actually for the QUOTA_FAKE_FILE --metze
2273 pstrcpy(fname, fsp->fsp_name);
2274 unix_convert(fname,conn,0,&bad_path,&sbuf);
2275 if (!check_name(fname,conn)) {
2276 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno)));
2277 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2280 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2282 * This is actually a QFILEINFO on a directory
2283 * handle (returned from an NT SMB). NT5.0 seems
2284 * to do this call. JRA.
2286 pstrcpy(fname, fsp->fsp_name);
2287 unix_convert(fname,conn,0,&bad_path,&sbuf);
2288 if (!check_name(fname,conn)) {
2289 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2290 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2293 if (INFO_LEVEL_IS_UNIX(info_level)) {
2294 /* Always do lstat for UNIX calls. */
2295 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2296 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2297 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2299 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
2300 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2301 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2304 delete_pending = fsp->directory_delete_on_close;
2305 } else {
2307 * Original code - this is an open file.
2309 CHECK_FSP(fsp,conn);
2311 pstrcpy(fname, fsp->fsp_name);
2312 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2313 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2314 return(UNIXERROR(ERRDOS,ERRbadfid));
2316 pos = fsp->position_information;
2317 delete_pending = fsp->delete_on_close;
2318 desired_access = fsp->desired_access;
2320 } else {
2321 NTSTATUS status = NT_STATUS_OK;
2323 /* qpathinfo */
2324 if (total_params < 6)
2325 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2327 info_level = SVAL(params,0);
2329 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2331 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
2332 if (!NT_STATUS_IS_OK(status)) {
2333 return ERROR_NT(status);
2336 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2338 unix_convert(fname,conn,0,&bad_path,&sbuf);
2339 if (!check_name(fname,conn)) {
2340 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2341 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2344 if (INFO_LEVEL_IS_UNIX(info_level)) {
2345 /* Always do lstat for UNIX calls. */
2346 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2347 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2348 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2350 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2351 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2352 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2356 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2357 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2359 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2360 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2362 p = strrchr_m(fname,'/');
2363 if (!p)
2364 base_name = fname;
2365 else
2366 base_name = p+1;
2368 mode = dos_mode(conn,fname,&sbuf);
2369 if (!mode)
2370 mode = FILE_ATTRIBUTE_NORMAL;
2372 fullpathname = fname;
2373 file_size = get_file_size(sbuf);
2374 allocation_size = get_allocation_size(fsp,&sbuf);
2375 if (mode & aDIR)
2376 file_size = 0;
2378 params = Realloc(*pparams,2);
2379 if (params == NULL)
2380 return ERROR_DOS(ERRDOS,ERRnomem);
2381 *pparams = params;
2382 memset((char *)params,'\0',2);
2383 data_size = max_data_bytes + 1024;
2384 pdata = Realloc(*ppdata, data_size);
2385 if ( pdata == NULL )
2386 return ERROR_DOS(ERRDOS,ERRnomem);
2387 *ppdata = pdata;
2389 if (total_data > 0 && IVAL(pdata,0) == total_data) {
2390 /* uggh, EAs for OS2 */
2391 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2392 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2395 memset((char *)pdata,'\0',data_size);
2397 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2399 if (lp_dos_filetime_resolution(SNUM(conn))) {
2400 c_time &= ~1;
2401 sbuf.st_atime &= ~1;
2402 sbuf.st_mtime &= ~1;
2403 sbuf.st_mtime &= ~1;
2406 /* NT expects the name to be in an exact form of the *full*
2407 filename. See the trans2 torture test */
2408 if (strequal(base_name,".")) {
2409 pstrcpy(dos_fname, "\\");
2410 } else {
2411 pstr_sprintf(dos_fname, "\\%s", fname);
2412 string_replace(dos_fname, '/', '\\');
2415 switch (info_level) {
2416 case SMB_INFO_STANDARD:
2417 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2418 data_size = 22;
2419 put_dos_date2(pdata,l1_fdateCreation,c_time);
2420 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2421 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2422 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2423 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2424 SSVAL(pdata,l1_attrFile,mode);
2425 break;
2427 case SMB_INFO_QUERY_EA_SIZE:
2429 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2430 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2431 data_size = 26;
2432 put_dos_date2(pdata,l1_fdateCreation,c_time);
2433 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2434 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2435 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2436 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2437 SSVAL(pdata,l1_attrFile,mode);
2438 SIVAL(pdata,l1_attrFile+2,ea_size);
2439 break;
2442 case SMB_INFO_IS_NAME_VALID:
2443 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2444 if (tran_call == TRANSACT2_QFILEINFO) {
2445 /* os/2 needs this ? really ?*/
2446 return ERROR_DOS(ERRDOS,ERRbadfunc);
2448 data_size = 0;
2449 param_size = 0;
2450 break;
2452 case SMB_INFO_QUERY_EAS_FROM_LIST:
2453 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2454 data_size = 24;
2455 put_dos_date2(pdata,0,c_time);
2456 put_dos_date2(pdata,4,sbuf.st_atime);
2457 put_dos_date2(pdata,8,sbuf.st_mtime);
2458 SIVAL(pdata,12,(uint32)file_size);
2459 SIVAL(pdata,16,(uint32)allocation_size);
2460 SIVAL(pdata,20,mode);
2461 break;
2463 case SMB_INFO_QUERY_ALL_EAS:
2464 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2465 /* We have data_size bytes to put EA's into. */
2466 data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname);
2467 break;
2469 case SMB_FILE_BASIC_INFORMATION:
2470 case SMB_QUERY_FILE_BASIC_INFO:
2472 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2473 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2474 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2475 } else {
2476 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2477 data_size = 40;
2478 SIVAL(pdata,36,0);
2480 put_long_date(pdata,c_time);
2481 put_long_date(pdata+8,sbuf.st_atime);
2482 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2483 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2484 SIVAL(pdata,32,mode);
2486 DEBUG(5,("SMB_QFBI - "));
2488 time_t create_time = c_time;
2489 DEBUG(5,("create: %s ", ctime(&create_time)));
2491 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2492 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2493 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2494 DEBUG(5,("mode: %x\n", mode));
2496 break;
2498 case SMB_FILE_STANDARD_INFORMATION:
2499 case SMB_QUERY_FILE_STANDARD_INFO:
2501 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2502 data_size = 24;
2503 SOFF_T(pdata,0,allocation_size);
2504 SOFF_T(pdata,8,file_size);
2505 if (delete_pending & sbuf.st_nlink)
2506 SIVAL(pdata,16,sbuf.st_nlink - 1);
2507 else
2508 SIVAL(pdata,16,sbuf.st_nlink);
2509 SCVAL(pdata,20,0);
2510 SCVAL(pdata,21,(mode&aDIR)?1:0);
2511 break;
2513 case SMB_FILE_EA_INFORMATION:
2514 case SMB_QUERY_FILE_EA_INFO:
2516 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2517 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2518 data_size = 4;
2519 SIVAL(pdata,0,ea_size);
2520 break;
2523 /* Get the 8.3 name - used if NT SMB was negotiated. */
2524 case SMB_QUERY_FILE_ALT_NAME_INFO:
2525 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2527 pstring short_name;
2529 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2530 pstrcpy(short_name,base_name);
2531 /* Mangle if not already 8.3 */
2532 if(!mangle_is_8_3(short_name, True)) {
2533 mangle_map(short_name,True,True,SNUM(conn));
2535 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2536 data_size = 4 + len;
2537 SIVAL(pdata,0,len);
2538 break;
2541 case SMB_QUERY_FILE_NAME_INFO:
2543 this must be *exactly* right for ACLs on mapped drives to work
2545 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2546 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2547 data_size = 4 + len;
2548 SIVAL(pdata,0,len);
2549 break;
2551 case SMB_FILE_ALLOCATION_INFORMATION:
2552 case SMB_QUERY_FILE_ALLOCATION_INFO:
2553 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2554 data_size = 8;
2555 SOFF_T(pdata,0,allocation_size);
2556 break;
2558 case SMB_FILE_END_OF_FILE_INFORMATION:
2559 case SMB_QUERY_FILE_END_OF_FILEINFO:
2560 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2561 data_size = 8;
2562 SOFF_T(pdata,0,file_size);
2563 break;
2565 case SMB_QUERY_FILE_ALL_INFO:
2566 case SMB_FILE_ALL_INFORMATION:
2568 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2569 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2570 put_long_date(pdata,c_time);
2571 put_long_date(pdata+8,sbuf.st_atime);
2572 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2573 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2574 SIVAL(pdata,32,mode);
2575 pdata += 40;
2576 SOFF_T(pdata,0,allocation_size);
2577 SOFF_T(pdata,8,file_size);
2578 if (delete_pending && sbuf.st_nlink)
2579 SIVAL(pdata,16,sbuf.st_nlink - 1);
2580 else
2581 SIVAL(pdata,16,sbuf.st_nlink);
2582 SCVAL(pdata,20,delete_pending);
2583 SCVAL(pdata,21,(mode&aDIR)?1:0);
2584 pdata += 24;
2585 SIVAL(pdata,0,ea_size);
2586 pdata += 4; /* EA info */
2587 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2588 SIVAL(pdata,0,len);
2589 pdata += 4 + len;
2590 data_size = PTR_DIFF(pdata,(*ppdata));
2591 break;
2593 case SMB_FILE_INTERNAL_INFORMATION:
2594 /* This should be an index number - looks like
2595 dev/ino to me :-)
2597 I think this causes us to fail the IFSKIT
2598 BasicFileInformationTest. -tpot */
2600 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2601 SIVAL(pdata,0,sbuf.st_dev);
2602 SIVAL(pdata,4,sbuf.st_ino);
2603 data_size = 8;
2604 break;
2606 case SMB_FILE_ACCESS_INFORMATION:
2607 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2608 SIVAL(pdata,0,desired_access);
2609 data_size = 4;
2610 break;
2612 case SMB_FILE_NAME_INFORMATION:
2613 /* Pathname with leading '\'. */
2615 size_t byte_len;
2616 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2617 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2618 SIVAL(pdata,0,byte_len);
2619 data_size = 4 + byte_len;
2620 break;
2623 case SMB_FILE_DISPOSITION_INFORMATION:
2624 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2625 data_size = 1;
2626 SCVAL(pdata,0,delete_pending);
2627 break;
2629 case SMB_FILE_POSITION_INFORMATION:
2630 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2631 data_size = 8;
2632 SOFF_T(pdata,0,pos);
2633 break;
2635 case SMB_FILE_MODE_INFORMATION:
2636 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2637 SIVAL(pdata,0,mode);
2638 data_size = 4;
2639 break;
2641 case SMB_FILE_ALIGNMENT_INFORMATION:
2642 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2643 SIVAL(pdata,0,0); /* No alignment needed. */
2644 data_size = 4;
2645 break;
2647 #if 0
2649 * NT4 server just returns "invalid query" to this - if we try to answer
2650 * it then NTws gets a BSOD! (tridge).
2651 * W2K seems to want this. JRA.
2653 case SMB_QUERY_FILE_STREAM_INFO:
2654 #endif
2655 case SMB_FILE_STREAM_INFORMATION:
2656 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2657 if (mode & aDIR) {
2658 data_size = 0;
2659 } else {
2660 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2661 SIVAL(pdata,0,0); /* ??? */
2662 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2663 SOFF_T(pdata,8,file_size);
2664 SIVAL(pdata,16,allocation_size);
2665 SIVAL(pdata,20,0); /* ??? */
2666 data_size = 24 + byte_len;
2668 break;
2670 case SMB_QUERY_COMPRESSION_INFO:
2671 case SMB_FILE_COMPRESSION_INFORMATION:
2672 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2673 SOFF_T(pdata,0,file_size);
2674 SIVAL(pdata,8,0); /* ??? */
2675 SIVAL(pdata,12,0); /* ??? */
2676 data_size = 16;
2677 break;
2679 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2680 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2681 put_long_date(pdata,c_time);
2682 put_long_date(pdata+8,sbuf.st_atime);
2683 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2684 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2685 SIVAL(pdata,32,allocation_size);
2686 SOFF_T(pdata,40,file_size);
2687 SIVAL(pdata,48,mode);
2688 SIVAL(pdata,52,0); /* ??? */
2689 data_size = 56;
2690 break;
2692 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2693 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2694 SIVAL(pdata,0,mode);
2695 SIVAL(pdata,4,0);
2696 data_size = 8;
2697 break;
2700 * CIFS UNIX Extensions.
2703 case SMB_QUERY_FILE_UNIX_BASIC:
2705 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2706 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2708 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2709 pdata += 8;
2711 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2712 pdata += 8;
2714 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2715 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2716 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2717 pdata += 24;
2719 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2720 SIVAL(pdata,4,0);
2721 pdata += 8;
2723 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2724 SIVAL(pdata,4,0);
2725 pdata += 8;
2727 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2728 pdata += 4;
2730 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2731 SIVAL(pdata,4,0);
2732 pdata += 8;
2734 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2735 SIVAL(pdata,4,0);
2736 pdata += 8;
2738 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2739 pdata += 8;
2741 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2742 SIVAL(pdata,4,0);
2743 pdata += 8;
2745 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2746 SIVAL(pdata,4,0);
2747 pdata += 8+1;
2748 data_size = PTR_DIFF(pdata,(*ppdata));
2751 int i;
2752 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2754 for (i=0; i<100; i++)
2755 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2756 DEBUG(4,("\n"));
2759 break;
2761 case SMB_QUERY_FILE_UNIX_LINK:
2763 pstring buffer;
2765 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
2766 #ifdef S_ISLNK
2767 if(!S_ISLNK(sbuf.st_mode))
2768 return(UNIXERROR(ERRSRV,ERRbadlink));
2769 #else
2770 return(UNIXERROR(ERRDOS,ERRbadlink));
2771 #endif
2772 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2773 if (len == -1)
2774 return(UNIXERROR(ERRDOS,ERRnoaccess));
2775 buffer[len] = 0;
2776 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2777 pdata += len;
2778 data_size = PTR_DIFF(pdata,(*ppdata));
2780 break;
2783 default:
2784 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2787 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
2789 return(-1);
2792 /****************************************************************************
2793 Deal with the internal needs of setting the delete on close flag. Note that
2794 as the tdb locking is recursive, it is safe to call this from within
2795 open_file_shared. JRA.
2796 ****************************************************************************/
2798 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2801 * Only allow delete on close for writable shares.
2804 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2805 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2806 fsp->fsp_name ));
2807 return NT_STATUS_ACCESS_DENIED;
2810 * Only allow delete on close for files/directories opened with delete intent.
2813 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2814 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2815 fsp->fsp_name ));
2816 return NT_STATUS_ACCESS_DENIED;
2819 if(fsp->is_directory) {
2820 fsp->directory_delete_on_close = delete_on_close;
2821 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2822 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2823 } else {
2824 fsp->delete_on_close = delete_on_close;
2825 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2826 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2829 return NT_STATUS_OK;
2832 /****************************************************************************
2833 Sets the delete on close flag over all share modes on this file.
2834 Modify the share mode entry for all files open
2835 on this device and inode to tell other smbds we have
2836 changed the delete on close flag. This will be noticed
2837 in the close code, the last closer will delete the file
2838 if flag is set.
2839 ****************************************************************************/
2841 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2843 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2844 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2846 if (fsp->is_directory || fsp->is_stat)
2847 return NT_STATUS_OK;
2849 if (lock_share_entry_fsp(fsp) == False)
2850 return NT_STATUS_ACCESS_DENIED;
2852 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2853 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2854 fsp->fsp_name ));
2855 unlock_share_entry_fsp(fsp);
2856 return NT_STATUS_ACCESS_DENIED;
2859 unlock_share_entry_fsp(fsp);
2860 return NT_STATUS_OK;
2863 /****************************************************************************
2864 Returns true if this pathname is within the share, and thus safe.
2865 ****************************************************************************/
2867 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2869 #ifdef PATH_MAX
2870 char resolved_name[PATH_MAX+1];
2871 #else
2872 pstring resolved_name;
2873 #endif
2874 fstring last_component;
2875 pstring link_dest;
2876 pstring link_test;
2877 char *p;
2878 BOOL bad_path = False;
2879 SMB_STRUCT_STAT sbuf;
2881 pstrcpy(link_dest, link_dest_in);
2882 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2884 /* Store the UNIX converted path. */
2885 pstrcpy(link_dest_out, link_dest);
2887 p = strrchr(link_dest, '/');
2888 if (p) {
2889 fstrcpy(last_component, p+1);
2890 *p = '\0';
2891 } else {
2892 fstrcpy(last_component, link_dest);
2893 pstrcpy(link_dest, "./");
2896 if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL)
2897 return -1;
2899 pstrcpy(link_dest, resolved_name);
2900 pstrcat(link_dest, "/");
2901 pstrcat(link_dest, last_component);
2903 if (*link_dest != '/') {
2904 /* Relative path. */
2905 pstrcpy(link_test, conn->connectpath);
2906 pstrcat(link_test, "/");
2907 pstrcat(link_test, link_dest);
2908 } else {
2909 pstrcpy(link_test, link_dest);
2913 * Check if the link is within the share.
2916 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2917 errno = EACCES;
2918 return -1;
2920 return 0;
2923 /****************************************************************************
2924 Set a hard link (called by UNIX extensions and by NT rename with HARD link
2925 code.
2926 ****************************************************************************/
2928 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
2930 BOOL bad_path_oldname = False;
2931 BOOL bad_path_newname = False;
2932 SMB_STRUCT_STAT sbuf1, sbuf2;
2933 BOOL rc, rcdest;
2934 pstring last_component_oldname;
2935 pstring last_component_newname;
2936 NTSTATUS status = NT_STATUS_OK;
2938 ZERO_STRUCT(sbuf1);
2939 ZERO_STRUCT(sbuf2);
2941 /* No wildcards. */
2942 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
2943 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
2946 rc = unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
2947 if (!rc && bad_path_oldname) {
2948 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2951 /* Quick check for "." and ".." */
2952 if (last_component_oldname[0] == '.') {
2953 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
2954 return NT_STATUS_OBJECT_NAME_INVALID;
2958 /* source must already exist. */
2959 if (!VALID_STAT(sbuf1)) {
2960 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2963 rcdest = unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
2964 if (!rcdest && bad_path_newname) {
2965 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2968 /* Quick check for "." and ".." */
2969 if (last_component_newname[0] == '.') {
2970 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
2971 return NT_STATUS_OBJECT_NAME_INVALID;
2975 /* Disallow if newname already exists. */
2976 if (VALID_STAT(sbuf2)) {
2977 return NT_STATUS_OBJECT_NAME_COLLISION;
2980 /* No links from a directory. */
2981 if (S_ISDIR(sbuf1.st_mode)) {
2982 return NT_STATUS_FILE_IS_A_DIRECTORY;
2985 if (ensure_link_is_safe(conn, oldname, oldname) != 0)
2986 return NT_STATUS_ACCESS_DENIED;
2988 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
2990 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
2991 status = map_nt_error_from_unix(errno);
2992 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
2993 nt_errstr(status), newname, oldname));
2996 return status;
2999 /****************************************************************************
3000 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3001 ****************************************************************************/
3003 static int call_trans2setfilepathinfo(connection_struct *conn,
3004 char *inbuf, char *outbuf, int length, int bufsize,
3005 char **pparams, int total_params, char **ppdata, int total_data)
3007 char *params = *pparams;
3008 char *pdata = *ppdata;
3009 uint16 tran_call = SVAL(inbuf, smb_setup0);
3010 uint16 info_level;
3011 int dosmode=0;
3012 SMB_OFF_T size=0;
3013 struct utimbuf tvs;
3014 SMB_STRUCT_STAT sbuf;
3015 pstring fname;
3016 int fd = -1;
3017 BOOL bad_path = False;
3018 files_struct *fsp = NULL;
3019 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3020 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3021 mode_t unixmode = 0;
3022 NTSTATUS status = NT_STATUS_OK;
3024 if (!params)
3025 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3027 if (tran_call == TRANSACT2_SETFILEINFO) {
3028 if (total_params < 4)
3029 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3031 fsp = file_fsp(params,0);
3032 info_level = SVAL(params,2);
3034 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3036 * This is actually a SETFILEINFO on a directory
3037 * handle (returned from an NT SMB). NT5.0 seems
3038 * to do this call. JRA.
3040 pstrcpy(fname, fsp->fsp_name);
3041 unix_convert(fname,conn,0,&bad_path,&sbuf);
3042 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
3043 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3044 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3046 } else if (fsp && fsp->print_file) {
3048 * Doing a DELETE_ON_CLOSE should cancel a print job.
3050 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3051 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3053 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3055 SSVAL(params,0,0);
3056 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3057 return(-1);
3058 } else
3059 return (UNIXERROR(ERRDOS,ERRbadpath));
3060 } else {
3062 * Original code - this is an open file.
3064 CHECK_FSP(fsp,conn);
3066 pstrcpy(fname, fsp->fsp_name);
3067 fd = fsp->fd;
3069 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3070 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3071 return(UNIXERROR(ERRDOS,ERRbadfid));
3074 } else {
3075 /* set path info */
3076 if (total_params < 6)
3077 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3079 info_level = SVAL(params,0);
3080 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
3081 if (!NT_STATUS_IS_OK(status)) {
3082 return ERROR_NT(status);
3084 unix_convert(fname,conn,0,&bad_path,&sbuf);
3087 * For CIFS UNIX extensions the target name may not exist.
3090 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3091 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3092 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3095 if(!check_name(fname, conn)) {
3096 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3101 if (!CAN_WRITE(conn))
3102 return ERROR_DOS(ERRSRV,ERRaccess);
3104 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3105 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3107 if (VALID_STAT(sbuf))
3108 unixmode = sbuf.st_mode;
3110 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3111 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3113 /* Realloc the parameter and data sizes */
3114 params = Realloc(*pparams,2);
3115 if(params == NULL)
3116 return ERROR_DOS(ERRDOS,ERRnomem);
3117 *pparams = params;
3119 SSVAL(params,0,0);
3121 if (fsp) {
3122 /* the pending modtime overrides the current modtime */
3123 sbuf.st_mtime = fsp->pending_modtime;
3126 size = get_file_size(sbuf);
3127 tvs.modtime = sbuf.st_mtime;
3128 tvs.actime = sbuf.st_atime;
3129 dosmode = dos_mode(conn,fname,&sbuf);
3130 unixmode = sbuf.st_mode;
3132 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3133 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3135 switch (info_level) {
3136 case SMB_INFO_STANDARD:
3138 if (total_data < 12)
3139 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3141 /* access time */
3142 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3143 /* write time */
3144 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3145 break;
3148 case SMB_INFO_SET_EA:
3149 status = set_ea(conn, fsp, fname, pdata, total_data);
3150 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3151 return ERROR_NT(status);
3152 break;
3154 /* XXXX um, i don't think this is right.
3155 it's also not in the cifs6.txt spec.
3157 case SMB_INFO_QUERY_EAS_FROM_LIST:
3158 if (total_data < 28)
3159 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3161 tvs.actime = make_unix_date2(pdata+8);
3162 tvs.modtime = make_unix_date2(pdata+12);
3163 size = IVAL(pdata,16);
3164 dosmode = IVAL(pdata,24);
3165 break;
3167 /* XXXX nor this. not in cifs6.txt, either. */
3168 case SMB_INFO_QUERY_ALL_EAS:
3169 if (total_data < 28)
3170 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3172 tvs.actime = make_unix_date2(pdata+8);
3173 tvs.modtime = make_unix_date2(pdata+12);
3174 size = IVAL(pdata,16);
3175 dosmode = IVAL(pdata,24);
3176 break;
3178 case SMB_SET_FILE_BASIC_INFO:
3179 case SMB_FILE_BASIC_INFORMATION:
3181 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3182 time_t write_time;
3183 time_t changed_time;
3185 if (total_data < 36)
3186 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3188 /* Ignore create time at offset pdata. */
3190 /* access time */
3191 tvs.actime = interpret_long_date(pdata+8);
3193 write_time = interpret_long_date(pdata+16);
3194 changed_time = interpret_long_date(pdata+24);
3196 tvs.modtime = MIN(write_time, changed_time);
3198 if (write_time > tvs.modtime && write_time != 0xffffffff) {
3199 tvs.modtime = write_time;
3201 /* Prefer a defined time to an undefined one. */
3202 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3203 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
3204 ? changed_time : write_time);
3206 /* attributes */
3207 dosmode = IVAL(pdata,32);
3208 break;
3211 case SMB_FILE_ALLOCATION_INFORMATION:
3212 case SMB_SET_FILE_ALLOCATION_INFO:
3214 int ret = -1;
3215 SMB_BIG_UINT allocation_size;
3217 if (total_data < 8)
3218 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3220 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3221 #ifdef LARGE_SMB_OFF_T
3222 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3223 #else /* LARGE_SMB_OFF_T */
3224 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3225 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3226 #endif /* LARGE_SMB_OFF_T */
3227 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3228 fname, (double)allocation_size ));
3230 if (allocation_size)
3231 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
3233 if(allocation_size != get_file_size(sbuf)) {
3234 SMB_STRUCT_STAT new_sbuf;
3236 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3237 fname, (double)allocation_size ));
3239 if (fd == -1) {
3240 files_struct *new_fsp = NULL;
3241 int access_mode = 0;
3242 int action = 0;
3244 if(global_oplock_break) {
3245 /* Queue this file modify as we are the process of an oplock break. */
3247 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3248 DEBUGADD(2,( "in oplock break state.\n"));
3250 push_oplock_pending_smb_message(inbuf, length);
3251 return -1;
3254 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3255 SET_OPEN_MODE(DOS_OPEN_RDWR),
3256 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3257 FILE_ATTRIBUTE_NORMAL,
3258 0, &access_mode, &action);
3260 if (new_fsp == NULL)
3261 return(UNIXERROR(ERRDOS,ERRbadpath));
3262 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3263 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3264 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3265 new_fsp->fnum, strerror(errno)));
3266 ret = -1;
3268 close_file(new_fsp,True);
3269 } else {
3270 ret = vfs_allocate_file_space(fsp, allocation_size);
3271 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3272 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3273 fsp->fnum, strerror(errno)));
3274 ret = -1;
3277 if (ret == -1)
3278 return ERROR_NT(NT_STATUS_DISK_FULL);
3280 /* Allocate can truncate size... */
3281 size = get_file_size(new_sbuf);
3284 break;
3287 case SMB_FILE_END_OF_FILE_INFORMATION:
3288 case SMB_SET_FILE_END_OF_FILE_INFO:
3290 if (total_data < 8)
3291 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3293 size = IVAL(pdata,0);
3294 #ifdef LARGE_SMB_OFF_T
3295 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3296 #else /* LARGE_SMB_OFF_T */
3297 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3298 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3299 #endif /* LARGE_SMB_OFF_T */
3300 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3301 break;
3304 case SMB_FILE_DISPOSITION_INFORMATION:
3305 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3307 BOOL delete_on_close;
3309 if (total_data < 1)
3310 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3312 delete_on_close = (CVAL(pdata,0) ? True : False);
3314 /* Just ignore this set on a path. */
3315 if (tran_call != TRANSACT2_SETFILEINFO)
3316 break;
3318 if (fsp == NULL)
3319 return(UNIXERROR(ERRDOS,ERRbadfid));
3321 status = set_delete_on_close_internal(fsp, delete_on_close);
3323 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3324 return ERROR_NT(status);
3326 /* The set is across all open files on this dev/inode pair. */
3327 status =set_delete_on_close_over_all(fsp, delete_on_close);
3328 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3329 return ERROR_NT(status);
3331 break;
3334 case SMB_FILE_POSITION_INFORMATION:
3336 SMB_BIG_UINT position_information;
3338 if (total_data < 8)
3339 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3341 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3342 #ifdef LARGE_SMB_OFF_T
3343 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3344 #else /* LARGE_SMB_OFF_T */
3345 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3346 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3347 #endif /* LARGE_SMB_OFF_T */
3348 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3349 fname, (double)position_information ));
3350 if (fsp)
3351 fsp->position_information = position_information;
3352 break;
3356 * CIFS UNIX extensions.
3359 case SMB_SET_FILE_UNIX_BASIC:
3361 uint32 raw_unixmode;
3363 if (total_data < 100)
3364 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3366 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3367 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3368 size=IVAL(pdata,0); /* first 8 Bytes are size */
3369 #ifdef LARGE_SMB_OFF_T
3370 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3371 #else /* LARGE_SMB_OFF_T */
3372 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3373 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3374 #endif /* LARGE_SMB_OFF_T */
3376 pdata+=24; /* ctime & st_blocks are not changed */
3377 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
3378 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
3379 pdata+=16;
3380 set_owner = (uid_t)IVAL(pdata,0);
3381 pdata += 8;
3382 set_grp = (gid_t)IVAL(pdata,0);
3383 pdata += 8;
3384 raw_unixmode = IVAL(pdata,28);
3385 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3386 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3388 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3389 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3390 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3392 if (!VALID_STAT(sbuf)) {
3395 * The only valid use of this is to create character and block
3396 * devices, and named pipes. This is deprecated (IMHO) and
3397 * a new info level should be used for mknod. JRA.
3400 #if !defined(HAVE_MAKEDEV_FN)
3401 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3402 #else /* HAVE_MAKEDEV_FN */
3403 uint32 file_type = IVAL(pdata,0);
3404 uint32 dev_major = IVAL(pdata,4);
3405 uint32 dev_minor = IVAL(pdata,12);
3407 uid_t myuid = geteuid();
3408 gid_t mygid = getegid();
3409 SMB_DEV_T dev;
3411 if (tran_call == TRANSACT2_SETFILEINFO)
3412 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3414 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3415 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3417 dev = makedev(dev_major, dev_minor);
3419 /* We can only create as the owner/group we are. */
3421 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3422 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3423 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3424 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3426 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
3427 file_type != UNIX_TYPE_FIFO)
3428 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3430 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3431 0%o for file %s\n", (double)dev, unixmode, fname ));
3433 /* Ok - do the mknod. */
3434 if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
3435 return(UNIXERROR(ERRDOS,ERRnoaccess));
3437 inherit_access_acl(conn, fname, unixmode);
3439 SSVAL(params,0,0);
3440 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3441 return(-1);
3442 #endif /* HAVE_MAKEDEV_FN */
3447 * Deal with the UNIX specific mode set.
3450 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3451 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3452 (unsigned int)unixmode, fname ));
3453 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3454 return(UNIXERROR(ERRDOS,ERRnoaccess));
3458 * Deal with the UNIX specific uid set.
3461 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3462 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3463 (unsigned int)set_owner, fname ));
3464 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3465 return(UNIXERROR(ERRDOS,ERRnoaccess));
3469 * Deal with the UNIX specific gid set.
3472 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3473 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3474 (unsigned int)set_owner, fname ));
3475 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3476 return(UNIXERROR(ERRDOS,ERRnoaccess));
3478 break;
3481 case SMB_SET_FILE_UNIX_LINK:
3483 pstring oldname;
3484 char *newname = fname;
3486 /* Set a symbolic link. */
3487 /* Don't allow this if follow links is false. */
3489 if (!lp_symlinks(SNUM(conn)))
3490 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3492 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
3493 if (!NT_STATUS_IS_OK(status)) {
3494 return ERROR_NT(status);
3497 if (ensure_link_is_safe(conn, oldname, oldname) != 0)
3498 return(UNIXERROR(ERRDOS,ERRnoaccess));
3500 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3501 fname, oldname ));
3503 if (SMB_VFS_SYMLINK(conn,oldname,newname) != 0)
3504 return(UNIXERROR(ERRDOS,ERRnoaccess));
3505 SSVAL(params,0,0);
3506 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3507 return(-1);
3510 case SMB_SET_FILE_UNIX_HLINK:
3512 pstring oldname;
3513 char *newname = fname;
3515 /* Set a hard link. */
3516 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
3517 if (!NT_STATUS_IS_OK(status)) {
3518 return ERROR_NT(status);
3521 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3522 fname, oldname));
3524 status = hardlink_internals(conn, oldname, newname);
3525 if (!NT_STATUS_IS_OK(status)) {
3526 return ERROR_NT(status);
3529 SSVAL(params,0,0);
3530 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3531 return(-1);
3534 case SMB_FILE_RENAME_INFORMATION:
3536 BOOL overwrite;
3537 uint32 root_fid;
3538 uint32 len;
3539 pstring newname;
3540 pstring base_name;
3541 char *p;
3543 if (total_data < 12)
3544 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3546 overwrite = (CVAL(pdata,0) ? True : False);
3547 root_fid = IVAL(pdata,4);
3548 len = IVAL(pdata,8);
3549 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
3550 if (!NT_STATUS_IS_OK(status)) {
3551 return ERROR_NT(status);
3554 /* Check the new name has no '/' characters. */
3555 if (strchr_m(newname, '/'))
3556 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3558 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3560 /* Create the base directory. */
3561 pstrcpy(base_name, fname);
3562 p = strrchr_m(base_name, '/');
3563 if (p)
3564 *p = '\0';
3565 /* Append the new name. */
3566 pstrcat(base_name, "/");
3567 pstrcat(base_name, newname);
3569 if (fsp) {
3570 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3571 fsp->fnum, fsp->fsp_name, base_name ));
3572 status = rename_internals_fsp(conn, fsp, base_name, overwrite);
3573 } else {
3574 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3575 fname, newname ));
3576 status = rename_internals(conn, fname, base_name, 0, overwrite);
3578 if (!NT_STATUS_IS_OK(status)) {
3579 return ERROR_NT(status);
3581 process_pending_change_notify_queue((time_t)0);
3582 SSVAL(params,0,0);
3583 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3584 return(-1);
3586 default:
3587 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3590 /* get some defaults (no modifications) if any info is zero or -1. */
3591 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
3592 tvs.actime = sbuf.st_atime;
3594 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3595 tvs.modtime = sbuf.st_mtime;
3597 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3598 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3599 DEBUG(6,("size: %.0f ", (double)size));
3601 if (dosmode) {
3602 if (S_ISDIR(sbuf.st_mode))
3603 dosmode |= aDIR;
3604 else
3605 dosmode &= ~aDIR;
3608 DEBUG(6,("dosmode: %x\n" , dosmode));
3610 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3611 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3612 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3613 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3616 * Only do this test if we are not explicitly
3617 * changing the size of a file.
3619 if (!size)
3620 size = get_file_size(sbuf);
3624 * Try and set the times, size and mode of this file -
3625 * if they are different from the current values
3627 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3628 if(fsp != NULL) {
3630 * This was a setfileinfo on an open file.
3631 * NT does this a lot. It's actually pointless
3632 * setting the time here, as it will be overwritten
3633 * on the next write, so we save the request
3634 * away and will set it on file close. JRA.
3637 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3638 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3639 fsp->pending_modtime = tvs.modtime;
3642 } else {
3644 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3646 if(file_utime(conn, fname, &tvs)!=0)
3647 return(UNIXERROR(ERRDOS,ERRnoaccess));
3651 /* check the mode isn't different, before changing it */
3652 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3654 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3656 if(file_set_dosmode(conn, fname, dosmode, NULL)) {
3657 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
3658 return(UNIXERROR(ERRDOS,ERRnoaccess));
3662 if (size != get_file_size(sbuf)) {
3664 int ret;
3666 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3667 fname, (double)size ));
3669 if (fd == -1) {
3670 files_struct *new_fsp = NULL;
3671 int access_mode = 0;
3672 int action = 0;
3674 if(global_oplock_break) {
3675 /* Queue this file modify as we are the process of an oplock break. */
3677 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3678 DEBUGADD(2,( "in oplock break state.\n"));
3680 push_oplock_pending_smb_message(inbuf, length);
3681 return -1;
3684 new_fsp = open_file_shared(conn, fname, &sbuf,
3685 SET_OPEN_MODE(DOS_OPEN_RDWR),
3686 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3687 FILE_ATTRIBUTE_NORMAL,
3688 0, &access_mode, &action);
3690 if (new_fsp == NULL)
3691 return(UNIXERROR(ERRDOS,ERRbadpath));
3692 ret = vfs_set_filelen(new_fsp, size);
3693 close_file(new_fsp,True);
3694 } else {
3695 ret = vfs_set_filelen(fsp, size);
3698 if (ret == -1)
3699 return (UNIXERROR(ERRHRD,ERRdiskfull));
3702 SSVAL(params,0,0);
3703 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3705 return(-1);
3708 /****************************************************************************
3709 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3710 ****************************************************************************/
3712 static int call_trans2mkdir(connection_struct *conn,
3713 char *inbuf, char *outbuf, int length, int bufsize,
3714 char **pparams, int total_params, char **ppdata, int total_data)
3716 char *params = *pparams;
3717 pstring directory;
3718 int ret = -1;
3719 SMB_STRUCT_STAT sbuf;
3720 BOOL bad_path = False;
3721 NTSTATUS status = NT_STATUS_OK;
3723 if (!CAN_WRITE(conn))
3724 return ERROR_DOS(ERRSRV,ERRaccess);
3726 if (total_params < 4)
3727 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3729 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status);
3730 if (!NT_STATUS_IS_OK(status)) {
3731 return ERROR_NT(status);
3734 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3736 unix_convert(directory,conn,0,&bad_path,&sbuf);
3737 if (check_name(directory,conn))
3738 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3740 if(ret < 0) {
3741 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3742 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
3745 /* Realloc the parameter and data sizes */
3746 params = Realloc(*pparams,2);
3747 if(params == NULL)
3748 return ERROR_DOS(ERRDOS,ERRnomem);
3749 *pparams = params;
3751 SSVAL(params,0,0);
3753 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3755 return(-1);
3758 /****************************************************************************
3759 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3760 We don't actually do this - we just send a null response.
3761 ****************************************************************************/
3763 static int call_trans2findnotifyfirst(connection_struct *conn,
3764 char *inbuf, char *outbuf, int length, int bufsize,
3765 char **pparams, int total_params, char **ppdata, int total_data)
3767 static uint16 fnf_handle = 257;
3768 char *params = *pparams;
3769 uint16 info_level;
3771 if (total_params < 6)
3772 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3774 info_level = SVAL(params,4);
3775 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3777 switch (info_level) {
3778 case 1:
3779 case 2:
3780 break;
3781 default:
3782 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3785 /* Realloc the parameter and data sizes */
3786 params = Realloc(*pparams,6);
3787 if(params == NULL)
3788 return ERROR_DOS(ERRDOS,ERRnomem);
3789 *pparams = params;
3791 SSVAL(params,0,fnf_handle);
3792 SSVAL(params,2,0); /* No changes */
3793 SSVAL(params,4,0); /* No EA errors */
3795 fnf_handle++;
3797 if(fnf_handle == 0)
3798 fnf_handle = 257;
3800 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3802 return(-1);
3805 /****************************************************************************
3806 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3807 changes). Currently this does nothing.
3808 ****************************************************************************/
3810 static int call_trans2findnotifynext(connection_struct *conn,
3811 char *inbuf, char *outbuf, int length, int bufsize,
3812 char **pparams, int total_params, char **ppdata, int total_data)
3814 char *params = *pparams;
3816 DEBUG(3,("call_trans2findnotifynext\n"));
3818 /* Realloc the parameter and data sizes */
3819 params = Realloc(*pparams,4);
3820 if(params == NULL)
3821 return ERROR_DOS(ERRDOS,ERRnomem);
3822 *pparams = params;
3824 SSVAL(params,0,0); /* No changes */
3825 SSVAL(params,2,0); /* No EA errors */
3827 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3829 return(-1);
3832 /****************************************************************************
3833 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3834 ****************************************************************************/
3836 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3837 char* outbuf, int length, int bufsize,
3838 char **pparams, int total_params, char **ppdata, int total_data)
3840 char *params = *pparams;
3841 pstring pathname;
3842 int reply_size = 0;
3843 int max_referral_level;
3845 DEBUG(10,("call_trans2getdfsreferral\n"));
3847 if (total_params < 2)
3848 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3850 max_referral_level = SVAL(params,0);
3852 if(!lp_host_msdfs())
3853 return ERROR_DOS(ERRDOS,ERRbadfunc);
3855 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
3856 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
3857 return UNIXERROR(ERRDOS,ERRbadfile);
3859 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3860 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3862 return(-1);
3865 #define LMCAT_SPL 0x53
3866 #define LMFUNC_GETJOBID 0x60
3868 /****************************************************************************
3869 Reply to a TRANS2_IOCTL - used for OS/2 printing.
3870 ****************************************************************************/
3872 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3873 char* outbuf, int length, int bufsize,
3874 char **pparams, int total_params, char **ppdata, int total_data)
3876 char *pdata = *ppdata;
3877 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3879 /* check for an invalid fid before proceeding */
3881 if (!fsp)
3882 return(ERROR_DOS(ERRDOS,ERRbadfid));
3884 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3885 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3886 pdata = Realloc(*ppdata, 32);
3887 if(pdata == NULL)
3888 return ERROR_DOS(ERRDOS,ERRnomem);
3889 *ppdata = pdata;
3891 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3892 CAN ACCEPT THIS IN UNICODE. JRA. */
3894 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
3895 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3896 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3897 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3898 return(-1);
3899 } else {
3900 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3901 return ERROR_DOS(ERRSRV,ERRerror);
3905 /****************************************************************************
3906 Reply to a SMBfindclose (stop trans2 directory search).
3907 ****************************************************************************/
3909 int reply_findclose(connection_struct *conn,
3910 char *inbuf,char *outbuf,int length,int bufsize)
3912 int outsize = 0;
3913 int dptr_num=SVALS(inbuf,smb_vwv0);
3914 START_PROFILE(SMBfindclose);
3916 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3918 dptr_close(&dptr_num);
3920 outsize = set_message(outbuf,0,0,True);
3922 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3924 END_PROFILE(SMBfindclose);
3925 return(outsize);
3928 /****************************************************************************
3929 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3930 ****************************************************************************/
3932 int reply_findnclose(connection_struct *conn,
3933 char *inbuf,char *outbuf,int length,int bufsize)
3935 int outsize = 0;
3936 int dptr_num= -1;
3937 START_PROFILE(SMBfindnclose);
3939 dptr_num = SVAL(inbuf,smb_vwv0);
3941 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3943 /* We never give out valid handles for a
3944 findnotifyfirst - so any dptr_num is ok here.
3945 Just ignore it. */
3947 outsize = set_message(outbuf,0,0,True);
3949 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3951 END_PROFILE(SMBfindnclose);
3952 return(outsize);
3955 /****************************************************************************
3956 Reply to a SMBtranss2 - just ignore it!
3957 ****************************************************************************/
3959 int reply_transs2(connection_struct *conn,
3960 char *inbuf,char *outbuf,int length,int bufsize)
3962 START_PROFILE(SMBtranss2);
3963 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3964 END_PROFILE(SMBtranss2);
3965 return(-1);
3968 /****************************************************************************
3969 Reply to a SMBtrans2.
3970 ****************************************************************************/
3972 int reply_trans2(connection_struct *conn,
3973 char *inbuf,char *outbuf,int length,int bufsize)
3975 int outsize = 0;
3976 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3977 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3978 #if 0
3979 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3980 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3981 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3982 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3983 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3984 int32 timeout = IVALS(inbuf,smb_timeout);
3985 #endif
3986 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3987 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3988 char *params = NULL, *data = NULL;
3989 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
3990 START_PROFILE(SMBtrans2);
3992 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3993 /* Queue this open message as we are the process of an
3994 * oplock break. */
3996 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3997 DEBUGADD(2,( "in oplock break state.\n"));
3999 push_oplock_pending_smb_message(inbuf, length);
4000 END_PROFILE(SMBtrans2);
4001 return -1;
4004 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4005 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4006 END_PROFILE(SMBtrans2);
4007 return ERROR_DOS(ERRSRV,ERRaccess);
4010 outsize = set_message(outbuf,0,0,True);
4012 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4013 is so as a sanity check */
4014 if (suwcnt != 1) {
4016 * Need to have rc=0 for ioctl to get job id for OS/2.
4017 * Network printing will fail if function is not successful.
4018 * Similar function in reply.c will be used if protocol
4019 * is LANMAN1.0 instead of LM1.2X002.
4020 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4021 * outbuf doesn't have to be set(only job id is used).
4023 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4024 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4025 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4026 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4027 } else {
4028 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4029 DEBUG(2,("Transaction is %d\n",tran_call));
4030 END_PROFILE(SMBtrans2);
4031 ERROR_DOS(ERRDOS,ERRinvalidparam);
4035 /* Allocate the space for the maximum needed parameters and data */
4036 if (total_params > 0)
4037 params = (char *)malloc(total_params);
4038 if (total_data > 0)
4039 data = (char *)malloc(total_data);
4041 if ((total_params && !params) || (total_data && !data)) {
4042 DEBUG(2,("Out of memory in reply_trans2\n"));
4043 SAFE_FREE(params);
4044 SAFE_FREE(data);
4045 END_PROFILE(SMBtrans2);
4046 return ERROR_DOS(ERRDOS,ERRnomem);
4049 /* Copy the param and data bytes sent with this request into
4050 the params buffer */
4051 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4052 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4054 if (num_params > total_params || num_data > total_data)
4055 exit_server("invalid params in reply_trans2");
4057 if(params) {
4058 unsigned int psoff = SVAL(inbuf, smb_psoff);
4059 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4060 goto bad_param;
4061 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4062 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4063 goto bad_param;
4064 memcpy( params, smb_base(inbuf) + psoff, num_params);
4066 if(data) {
4067 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4068 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4069 goto bad_param;
4070 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4071 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4072 goto bad_param;
4073 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4076 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4078 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4079 /* We need to send an interim response then receive the rest
4080 of the parameter/data bytes */
4081 outsize = set_message(outbuf,0,0,True);
4082 srv_signing_trans_stop();
4083 if (!send_smb(smbd_server_fd(),outbuf))
4084 exit_server("reply_trans2: send_smb failed.");
4086 while (num_data_sofar < total_data ||
4087 num_params_sofar < total_params) {
4088 BOOL ret;
4089 unsigned int param_disp;
4090 unsigned int param_off;
4091 unsigned int data_disp;
4092 unsigned int data_off;
4094 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4097 * The sequence number for the trans reply is always
4098 * based on the last secondary received.
4101 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4103 if ((ret &&
4104 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4105 outsize = set_message(outbuf,0,0,True);
4106 if(ret)
4107 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4108 else
4109 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4110 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4111 goto bad_param;
4114 /* Revise total_params and total_data in case
4115 they have changed downwards */
4116 if (SVAL(inbuf, smb_tpscnt) < total_params)
4117 total_params = SVAL(inbuf, smb_tpscnt);
4118 if (SVAL(inbuf, smb_tdscnt) < total_data)
4119 total_data = SVAL(inbuf, smb_tdscnt);
4121 num_params = SVAL(inbuf,smb_spscnt);
4122 param_off = SVAL(inbuf, smb_spsoff);
4123 param_disp = SVAL(inbuf, smb_spsdisp);
4124 num_params_sofar += num_params;
4126 num_data = SVAL(inbuf, smb_sdscnt);
4127 data_off = SVAL(inbuf, smb_sdsoff);
4128 data_disp = SVAL(inbuf, smb_sdsdisp);
4129 num_data_sofar += num_data;
4131 if (num_params_sofar > total_params || num_data_sofar > total_data)
4132 goto bad_param;
4134 if (num_params) {
4135 if (param_disp + num_params >= total_params)
4136 goto bad_param;
4137 if ((param_disp + num_params < param_disp) ||
4138 (param_disp + num_params < num_params))
4139 goto bad_param;
4140 if (param_disp > total_params)
4141 goto bad_param;
4142 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4143 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4144 goto bad_param;
4145 if (params + param_disp < params)
4146 goto bad_param;
4148 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4150 if (num_data) {
4151 if (data_disp + num_data >= total_data)
4152 goto bad_param;
4153 if ((data_disp + num_data < data_disp) ||
4154 (data_disp + num_data < num_data))
4155 goto bad_param;
4156 if (data_disp > total_data)
4157 goto bad_param;
4158 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4159 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4160 goto bad_param;
4161 if (data + data_disp < data)
4162 goto bad_param;
4164 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4169 if (Protocol >= PROTOCOL_NT1) {
4170 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4173 /* Now we must call the relevant TRANS2 function */
4174 switch(tran_call) {
4175 case TRANSACT2_OPEN:
4176 START_PROFILE_NESTED(Trans2_open);
4177 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4178 &params, total_params, &data, total_data);
4179 END_PROFILE_NESTED(Trans2_open);
4180 break;
4182 case TRANSACT2_FINDFIRST:
4183 START_PROFILE_NESTED(Trans2_findfirst);
4184 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4185 &params, total_params, &data, total_data);
4186 END_PROFILE_NESTED(Trans2_findfirst);
4187 break;
4189 case TRANSACT2_FINDNEXT:
4190 START_PROFILE_NESTED(Trans2_findnext);
4191 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4192 &params, total_params, &data, total_data);
4193 END_PROFILE_NESTED(Trans2_findnext);
4194 break;
4196 case TRANSACT2_QFSINFO:
4197 START_PROFILE_NESTED(Trans2_qfsinfo);
4198 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4199 &params, total_params, &data, total_data);
4200 END_PROFILE_NESTED(Trans2_qfsinfo);
4201 break;
4203 #ifdef HAVE_SYS_QUOTAS
4204 case TRANSACT2_SETFSINFO:
4205 START_PROFILE_NESTED(Trans2_setfsinfo);
4206 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4207 &params, total_params, &data, total_data);
4208 END_PROFILE_NESTED(Trans2_setfsinfo);
4209 break;
4210 #endif
4211 case TRANSACT2_QPATHINFO:
4212 case TRANSACT2_QFILEINFO:
4213 START_PROFILE_NESTED(Trans2_qpathinfo);
4214 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4215 &params, total_params, &data, total_data);
4216 END_PROFILE_NESTED(Trans2_qpathinfo);
4217 break;
4218 case TRANSACT2_SETPATHINFO:
4219 case TRANSACT2_SETFILEINFO:
4220 START_PROFILE_NESTED(Trans2_setpathinfo);
4221 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4222 &params, total_params, &data, total_data);
4223 END_PROFILE_NESTED(Trans2_setpathinfo);
4224 break;
4226 case TRANSACT2_FINDNOTIFYFIRST:
4227 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4228 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4229 &params, total_params, &data, total_data);
4230 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4231 break;
4233 case TRANSACT2_FINDNOTIFYNEXT:
4234 START_PROFILE_NESTED(Trans2_findnotifynext);
4235 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4236 &params, total_params, &data, total_data);
4237 END_PROFILE_NESTED(Trans2_findnotifynext);
4238 break;
4239 case TRANSACT2_MKDIR:
4240 START_PROFILE_NESTED(Trans2_mkdir);
4241 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4242 &params, total_params, &data, total_data);
4243 END_PROFILE_NESTED(Trans2_mkdir);
4244 break;
4246 case TRANSACT2_GET_DFS_REFERRAL:
4247 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4248 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4249 &params, total_params, &data, total_data);
4250 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4251 break;
4252 case TRANSACT2_IOCTL:
4253 START_PROFILE_NESTED(Trans2_ioctl);
4254 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4255 &params, total_params, &data, total_data);
4256 END_PROFILE_NESTED(Trans2_ioctl);
4257 break;
4258 default:
4259 /* Error in request */
4260 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4261 SAFE_FREE(params);
4262 SAFE_FREE(data);
4263 END_PROFILE(SMBtrans2);
4264 srv_signing_trans_stop();
4265 return ERROR_DOS(ERRSRV,ERRerror);
4268 /* As we do not know how many data packets will need to be
4269 returned here the various call_trans2xxxx calls
4270 must send their own. Thus a call_trans2xxx routine only
4271 returns a value other than -1 when it wants to send
4272 an error packet.
4275 srv_signing_trans_stop();
4277 SAFE_FREE(params);
4278 SAFE_FREE(data);
4279 END_PROFILE(SMBtrans2);
4280 return outsize; /* If a correct response was needed the
4281 call_trans2xxx calls have already sent
4282 it. If outsize != -1 then it is returning */
4284 bad_param:
4286 srv_signing_trans_stop();
4287 SAFE_FREE(params);
4288 SAFE_FREE(data);
4289 END_PROFILE(SMBtrans2);
4290 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);