r560: Fix bugzilla 1279: cannot control individual print jobs using cups
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blob0c6026392c4d7587b7e712f7d436723b1c819859
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 #ifdef ENOTSUP
399 if (errno == ENOTSUP) {
400 return NT_STATUS_EAS_NOT_SUPPORTED;
402 #endif
403 return map_nt_error_from_unix(errno);
406 return NT_STATUS_OK;
409 /****************************************************************************
410 Send the required number of replies back.
411 We assume all fields other than the data fields are
412 set correctly for the type of call.
413 HACK ! Always assumes smb_setup field is zero.
414 ****************************************************************************/
416 static int send_trans2_replies(char *outbuf,
417 int bufsize,
418 char *params,
419 int paramsize,
420 char *pdata,
421 int datasize)
423 /* As we are using a protocol > LANMAN1 then the max_send
424 variable must have been set in the sessetupX call.
425 This takes precedence over the max_xmit field in the
426 global struct. These different max_xmit variables should
427 be merged as this is now too confusing */
429 extern int max_send;
430 int data_to_send = datasize;
431 int params_to_send = paramsize;
432 int useable_space;
433 char *pp = params;
434 char *pd = pdata;
435 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
436 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
437 int data_alignment_offset = 0;
439 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
441 set_message(outbuf,10,0,True);
443 /* If there genuinely are no parameters or data to send just send the empty packet */
445 if(params_to_send == 0 && data_to_send == 0) {
446 if (!send_smb(smbd_server_fd(),outbuf))
447 exit_server("send_trans2_replies: send_smb failed.");
448 return 0;
451 /* When sending params and data ensure that both are nicely aligned */
452 /* Only do this alignment when there is also data to send - else
453 can cause NT redirector problems. */
455 if (((params_to_send % 4) != 0) && (data_to_send != 0))
456 data_alignment_offset = 4 - (params_to_send % 4);
458 /* Space is bufsize minus Netbios over TCP header minus SMB header */
459 /* The alignment_offset is to align the param bytes on an even byte
460 boundary. NT 4.0 Beta needs this to work correctly. */
462 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
464 /* useable_space can never be more than max_send minus the alignment offset. */
466 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
468 while (params_to_send || data_to_send) {
469 /* Calculate whether we will totally or partially fill this packet */
471 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
473 /* We can never send more than useable_space */
475 * Note that 'useable_space' does not include the alignment offsets,
476 * but we must include the alignment offsets in the calculation of
477 * the length of the data we send over the wire, as the alignment offsets
478 * are sent here. Fix from Marc_Jacobsen@hp.com.
481 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
483 set_message(outbuf, 10, total_sent_thistime, True);
485 /* Set total params and data to be sent */
486 SSVAL(outbuf,smb_tprcnt,paramsize);
487 SSVAL(outbuf,smb_tdrcnt,datasize);
489 /* Calculate how many parameters and data we can fit into
490 * this packet. Parameters get precedence
493 params_sent_thistime = MIN(params_to_send,useable_space);
494 data_sent_thistime = useable_space - params_sent_thistime;
495 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
497 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
499 /* smb_proff is the offset from the start of the SMB header to the
500 parameter bytes, however the first 4 bytes of outbuf are
501 the Netbios over TCP header. Thus use smb_base() to subtract
502 them from the calculation */
504 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
506 if(params_sent_thistime == 0)
507 SSVAL(outbuf,smb_prdisp,0);
508 else
509 /* Absolute displacement of param bytes sent in this packet */
510 SSVAL(outbuf,smb_prdisp,pp - params);
512 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
513 if(data_sent_thistime == 0) {
514 SSVAL(outbuf,smb_droff,0);
515 SSVAL(outbuf,smb_drdisp, 0);
516 } else {
517 /* The offset of the data bytes is the offset of the
518 parameter bytes plus the number of parameters being sent this time */
519 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
520 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
521 SSVAL(outbuf,smb_drdisp, pd - pdata);
524 /* Copy the param bytes into the packet */
526 if(params_sent_thistime)
527 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
529 /* Copy in the data bytes */
530 if(data_sent_thistime)
531 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
532 data_alignment_offset,pd,data_sent_thistime);
534 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
535 params_sent_thistime, data_sent_thistime, useable_space));
536 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
537 params_to_send, data_to_send, paramsize, datasize));
539 /* Send the packet */
540 if (!send_smb(smbd_server_fd(),outbuf))
541 exit_server("send_trans2_replies: send_smb failed.");
543 pp += params_sent_thistime;
544 pd += data_sent_thistime;
546 params_to_send -= params_sent_thistime;
547 data_to_send -= data_sent_thistime;
549 /* Sanity check */
550 if(params_to_send < 0 || data_to_send < 0) {
551 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
552 params_to_send, data_to_send));
553 return -1;
557 return 0;
560 /****************************************************************************
561 Reply to a TRANSACT2_OPEN.
562 ****************************************************************************/
564 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
565 char **pparams, int total_params, char **ppdata, int total_data)
567 char *params = *pparams;
568 int16 open_mode;
569 int16 open_attr;
570 BOOL oplock_request;
571 #if 0
572 BOOL return_additional_info;
573 int16 open_sattr;
574 time_t open_time;
575 #endif
576 int16 open_ofun;
577 int32 open_size;
578 char *pname;
579 pstring fname;
580 SMB_OFF_T size=0;
581 int fmode=0,mtime=0,rmode;
582 SMB_INO_T inode = 0;
583 SMB_STRUCT_STAT sbuf;
584 int smb_action = 0;
585 BOOL bad_path = False;
586 files_struct *fsp;
587 NTSTATUS status;
590 * Ensure we have enough parameters to perform the operation.
593 if (total_params < 29)
594 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
596 open_mode = SVAL(params, 2);
597 open_attr = SVAL(params,6);
598 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
599 #if 0
600 return_additional_info = BITSETW(params,0);
601 open_sattr = SVAL(params, 4);
602 open_time = make_unix_date3(params+8);
603 #endif
604 open_ofun = SVAL(params,12);
605 open_size = IVAL(params,14);
606 pname = &params[28];
608 if (IS_IPC(conn))
609 return(ERROR_DOS(ERRSRV,ERRaccess));
611 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);
612 if (!NT_STATUS_IS_OK(status)) {
613 return ERROR_NT(status);
616 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
617 fname,open_mode, open_attr, open_ofun, open_size));
619 /* XXXX we need to handle passed times, sattr and flags */
621 unix_convert(fname,conn,0,&bad_path,&sbuf);
623 if (!check_name(fname,conn)) {
624 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
627 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
628 oplock_request, &rmode,&smb_action);
630 if (!fsp) {
631 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
634 size = get_file_size(sbuf);
635 fmode = dos_mode(conn,fname,&sbuf);
636 mtime = sbuf.st_mtime;
637 inode = sbuf.st_ino;
638 if (fmode & aDIR) {
639 close_file(fsp,False);
640 return(ERROR_DOS(ERRDOS,ERRnoaccess));
643 /* Realloc the size of parameters and data we will return */
644 params = Realloc(*pparams, 28);
645 if( params == NULL )
646 return(ERROR_DOS(ERRDOS,ERRnomem));
647 *pparams = params;
649 memset((char *)params,'\0',28);
650 SSVAL(params,0,fsp->fnum);
651 SSVAL(params,2,fmode);
652 put_dos_date2(params,4, mtime);
653 SIVAL(params,8, (uint32)size);
654 SSVAL(params,12,rmode);
656 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
657 smb_action |= EXTENDED_OPLOCK_GRANTED;
659 SSVAL(params,18,smb_action);
662 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
664 SIVAL(params,20,inode);
666 /* Send the required number of replies */
667 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
669 return -1;
672 /*********************************************************
673 Routine to check if a given string matches exactly.
674 as a special case a mask of "." does NOT match. That
675 is required for correct wildcard semantics
676 Case can be significant or not.
677 **********************************************************/
679 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
681 if (mask[0] == '.' && mask[1] == 0)
682 return False;
683 if (case_sig)
684 return strcmp(str,mask)==0;
685 if (StrCaseCmp(str,mask) != 0) {
686 return False;
688 if (ms_has_wild(str)) {
689 return False;
691 return True;
694 /****************************************************************************
695 Return the filetype for UNIX extensions.
696 ****************************************************************************/
698 static uint32 unix_filetype(mode_t mode)
700 if(S_ISREG(mode))
701 return UNIX_TYPE_FILE;
702 else if(S_ISDIR(mode))
703 return UNIX_TYPE_DIR;
704 #ifdef S_ISLNK
705 else if(S_ISLNK(mode))
706 return UNIX_TYPE_SYMLINK;
707 #endif
708 #ifdef S_ISCHR
709 else if(S_ISCHR(mode))
710 return UNIX_TYPE_CHARDEV;
711 #endif
712 #ifdef S_ISBLK
713 else if(S_ISBLK(mode))
714 return UNIX_TYPE_BLKDEV;
715 #endif
716 #ifdef S_ISFIFO
717 else if(S_ISFIFO(mode))
718 return UNIX_TYPE_FIFO;
719 #endif
720 #ifdef S_ISSOCK
721 else if(S_ISSOCK(mode))
722 return UNIX_TYPE_SOCKET;
723 #endif
725 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
726 return UNIX_TYPE_UNKNOWN;
729 /****************************************************************************
730 Return the major devicenumber for UNIX extensions.
731 ****************************************************************************/
733 static uint32 unix_dev_major(SMB_DEV_T dev)
735 #if defined(HAVE_DEVICE_MAJOR_FN)
736 return (uint32)major(dev);
737 #else
738 return (uint32)(dev >> 8);
739 #endif
742 /****************************************************************************
743 Return the minor devicenumber for UNIX extensions.
744 ****************************************************************************/
746 static uint32 unix_dev_minor(SMB_DEV_T dev)
748 #if defined(HAVE_DEVICE_MINOR_FN)
749 return (uint32)minor(dev);
750 #else
751 return (uint32)(dev & 0xff);
752 #endif
755 /****************************************************************************
756 Map wire perms onto standard UNIX permissions. Obey share restrictions.
757 ****************************************************************************/
759 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
761 mode_t ret = 0;
763 if (perms == SMB_MODE_NO_CHANGE)
764 return pst->st_mode;
766 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
767 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
768 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
769 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
770 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
771 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
772 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
773 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
774 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
775 #ifdef S_ISVTX
776 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
777 #endif
778 #ifdef S_ISGID
779 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
780 #endif
781 #ifdef S_ISUID
782 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
783 #endif
785 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
786 ret &= lp_dir_mask(SNUM(conn));
787 /* Add in force bits */
788 ret |= lp_force_dir_mode(SNUM(conn));
789 } else {
790 /* Apply mode mask */
791 ret &= lp_create_mask(SNUM(conn));
792 /* Add in force bits */
793 ret |= lp_force_create_mode(SNUM(conn));
796 return ret;
799 /****************************************************************************
800 Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
801 ****************************************************************************/
803 time_t interpret_long_unix_date(char *p)
805 DEBUG(10,("interpret_long_unix_date\n"));
806 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
807 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
808 return -1;
809 } else {
810 return interpret_long_date(p);
814 /****************************************************************************
815 Get a level dependent lanman2 dir entry.
816 ****************************************************************************/
818 static BOOL get_lanman2_dir_entry(connection_struct *conn,
819 void *inbuf, void *outbuf,
820 char *path_mask,int dirtype,int info_level,
821 int requires_resume_key,
822 BOOL dont_descend,char **ppdata,
823 char *base_data, int space_remaining,
824 BOOL *out_of_space, BOOL *got_exact_match,
825 int *last_name_off)
827 const char *dname;
828 BOOL found = False;
829 SMB_STRUCT_STAT sbuf;
830 pstring mask;
831 pstring pathreal;
832 pstring fname;
833 char *p, *q, *pdata = *ppdata;
834 uint32 reskey=0;
835 int prev_dirpos=0;
836 int mode=0;
837 SMB_OFF_T file_size = 0;
838 SMB_BIG_UINT allocation_size = 0;
839 uint32 len;
840 time_t mdate=0, adate=0, cdate=0;
841 char *nameptr;
842 BOOL was_8_3;
843 int nt_extmode; /* Used for NT connections instead of mode */
844 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
846 *fname = 0;
847 *out_of_space = False;
848 *got_exact_match = False;
850 if (!conn->dirptr)
851 return(False);
853 p = strrchr_m(path_mask,'/');
854 if(p != NULL) {
855 if(p[1] == '\0')
856 pstrcpy(mask,"*.*");
857 else
858 pstrcpy(mask, p+1);
859 } else
860 pstrcpy(mask, path_mask);
862 while (!found) {
863 BOOL got_match;
865 /* Needed if we run out of space */
866 prev_dirpos = TellDir(conn->dirptr);
867 dname = ReadDirName(conn->dirptr);
870 * Due to bugs in NT client redirectors we are not using
871 * resume keys any more - set them to zero.
872 * Check out the related comments in findfirst/findnext.
873 * JRA.
876 reskey = 0;
878 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
879 (long)conn->dirptr,TellDir(conn->dirptr)));
881 if (!dname)
882 return(False);
884 pstrcpy(fname,dname);
886 if(!(got_match = *got_exact_match = exact_match(fname, mask, case_sensitive)))
887 got_match = mask_match(fname, mask, case_sensitive);
889 if(!got_match && !mangle_is_8_3(fname, False)) {
892 * It turns out that NT matches wildcards against
893 * both long *and* short names. This may explain some
894 * of the wildcard wierdness from old DOS clients
895 * that some people have been seeing.... JRA.
898 pstring newname;
899 pstrcpy( newname, fname);
900 mangle_map( newname, True, False, SNUM(conn));
901 if(!(got_match = *got_exact_match = exact_match(newname, mask, case_sensitive)))
902 got_match = mask_match(newname, mask, case_sensitive);
905 if(got_match) {
906 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
907 if (dont_descend && !isdots)
908 continue;
910 pstrcpy(pathreal,conn->dirpath);
911 if(needslash)
912 pstrcat(pathreal,"/");
913 pstrcat(pathreal,dname);
915 if (INFO_LEVEL_IS_UNIX(info_level)) {
916 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
917 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
918 pathreal,strerror(errno)));
919 continue;
921 } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
923 /* Needed to show the msdfs symlinks as
924 * directories */
926 if(lp_host_msdfs() &&
927 lp_msdfs_root(SNUM(conn)) &&
928 is_msdfs_link(conn, pathreal, NULL, NULL,
929 &sbuf)) {
931 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
932 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
934 } else {
936 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
937 pathreal,strerror(errno)));
938 continue;
942 mode = dos_mode(conn,pathreal,&sbuf);
944 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
945 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
946 continue;
949 file_size = get_file_size(sbuf);
950 allocation_size = get_allocation_size(NULL,&sbuf);
951 mdate = sbuf.st_mtime;
952 adate = sbuf.st_atime;
953 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
955 if (lp_dos_filetime_resolution(SNUM(conn))) {
956 cdate &= ~1;
957 mdate &= ~1;
958 adate &= ~1;
961 if(mode & aDIR)
962 file_size = 0;
964 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
966 found = True;
970 mangle_map(fname,False,True,SNUM(conn));
972 p = pdata;
973 nameptr = p;
975 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
977 switch (info_level) {
978 case SMB_INFO_STANDARD:
979 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_STANDARD\n"));
980 if(requires_resume_key) {
981 SIVAL(p,0,reskey);
982 p += 4;
984 put_dos_date2(p,l1_fdateCreation,cdate);
985 put_dos_date2(p,l1_fdateLastAccess,adate);
986 put_dos_date2(p,l1_fdateLastWrite,mdate);
987 SIVAL(p,l1_cbFile,(uint32)file_size);
988 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
989 SSVAL(p,l1_attrFile,mode);
990 p += l1_achName;
991 nameptr = p;
992 p += align_string(outbuf, p, 0);
993 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
994 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
995 if (len > 2) {
996 SCVAL(nameptr, -1, len - 2);
997 } else {
998 SCVAL(nameptr, -1, 0);
1000 } else {
1001 if (len > 1) {
1002 SCVAL(nameptr, -1, len - 1);
1003 } else {
1004 SCVAL(nameptr, -1, 0);
1007 p += len;
1008 break;
1010 case SMB_INFO_QUERY_EA_SIZE:
1011 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_QUERY_EA_SIZE\n"));
1012 if(requires_resume_key) {
1013 SIVAL(p,0,reskey);
1014 p += 4;
1016 put_dos_date2(p,l2_fdateCreation,cdate);
1017 put_dos_date2(p,l2_fdateLastAccess,adate);
1018 put_dos_date2(p,l2_fdateLastWrite,mdate);
1019 SIVAL(p,l2_cbFile,(uint32)file_size);
1020 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1021 SSVAL(p,l2_attrFile,mode);
1023 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1024 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1026 p += l2_achName;
1027 nameptr = p - 1;
1028 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1029 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1030 if (len > 2) {
1031 len -= 2;
1032 } else {
1033 len = 0;
1035 } else {
1036 if (len > 1) {
1037 len -= 1;
1038 } else {
1039 len = 0;
1042 SCVAL(nameptr,0,len);
1043 p += len;
1044 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1045 break;
1047 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1048 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1049 was_8_3 = mangle_is_8_3(fname, True);
1050 p += 4;
1051 SIVAL(p,0,reskey); p += 4;
1052 put_long_date(p,cdate); p += 8;
1053 put_long_date(p,adate); p += 8;
1054 put_long_date(p,mdate); p += 8;
1055 put_long_date(p,mdate); p += 8;
1056 SOFF_T(p,0,file_size); p += 8;
1057 SOFF_T(p,0,allocation_size); p += 8;
1058 SIVAL(p,0,nt_extmode); p += 4;
1059 q = p; p += 4; /* q is placeholder for name length. */
1061 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1062 SIVAL(p,0,ea_size); /* Extended attributes */
1063 p += 4;
1065 /* Clear the short name buffer. This is
1066 * IMPORTANT as not doing so will trigger
1067 * a Win2k client bug. JRA.
1069 memset(p,'\0',26);
1070 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1071 pstring mangled_name;
1072 pstrcpy(mangled_name, fname);
1073 mangle_map(mangled_name,True,True,SNUM(conn));
1074 mangled_name[12] = 0;
1075 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1076 SSVAL(p, 0, len);
1077 } else {
1078 SSVAL(p,0,0);
1079 *(p+2) = 0;
1081 p += 2 + 24;
1082 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1083 SIVAL(q,0,len);
1084 p += len;
1085 len = PTR_DIFF(p, pdata);
1086 len = (len + 3) & ~3;
1087 SIVAL(pdata,0,len);
1088 p = pdata + len;
1089 break;
1091 case SMB_FIND_FILE_DIRECTORY_INFO:
1092 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1093 p += 4;
1094 SIVAL(p,0,reskey); p += 4;
1095 put_long_date(p,cdate); p += 8;
1096 put_long_date(p,adate); p += 8;
1097 put_long_date(p,mdate); p += 8;
1098 put_long_date(p,mdate); p += 8;
1099 SOFF_T(p,0,file_size); p += 8;
1100 SOFF_T(p,0,allocation_size); p += 8;
1101 SIVAL(p,0,nt_extmode); p += 4;
1102 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1103 SIVAL(p,0,len);
1104 p += 4 + len;
1105 len = PTR_DIFF(p, pdata);
1106 len = (len + 3) & ~3;
1107 SIVAL(pdata,0,len);
1108 p = pdata + len;
1109 break;
1111 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1112 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1113 p += 4;
1114 SIVAL(p,0,reskey); p += 4;
1115 put_long_date(p,cdate); p += 8;
1116 put_long_date(p,adate); p += 8;
1117 put_long_date(p,mdate); p += 8;
1118 put_long_date(p,mdate); p += 8;
1119 SOFF_T(p,0,file_size); p += 8;
1120 SOFF_T(p,0,allocation_size); p += 8;
1121 SIVAL(p,0,nt_extmode); p += 4;
1122 q = p; p += 4; /* q is placeholder for name length. */
1124 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1125 SIVAL(p,0,ea_size); /* Extended attributes */
1126 p +=4;
1128 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1129 SIVAL(q, 0, len);
1130 p += len;
1132 len = PTR_DIFF(p, pdata);
1133 len = (len + 3) & ~3;
1134 SIVAL(pdata,0,len);
1135 p = pdata + len;
1136 break;
1138 case SMB_FIND_FILE_NAMES_INFO:
1139 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1140 p += 4;
1141 SIVAL(p,0,reskey); p += 4;
1142 p += 4;
1143 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1144 acl on a dir (tridge) */
1145 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1146 SIVAL(p, -4, len);
1147 p += len;
1148 len = PTR_DIFF(p, pdata);
1149 len = (len + 3) & ~3;
1150 SIVAL(pdata,0,len);
1151 p = pdata + len;
1152 break;
1154 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1155 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1156 p += 4;
1157 SIVAL(p,0,reskey); p += 4;
1158 put_long_date(p,cdate); p += 8;
1159 put_long_date(p,adate); p += 8;
1160 put_long_date(p,mdate); p += 8;
1161 put_long_date(p,mdate); p += 8;
1162 SOFF_T(p,0,file_size); p += 8;
1163 SOFF_T(p,0,allocation_size); p += 8;
1164 SIVAL(p,0,nt_extmode); p += 4;
1165 q = p; p += 4; /* q is placeholder for name length. */
1167 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1168 SIVAL(p,0,ea_size); /* Extended attributes */
1169 p +=4;
1171 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1172 SIVAL(p,0,sbuf.st_dev); p += 4;
1173 SIVAL(p,0,sbuf.st_ino); p += 4;
1174 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1175 SIVAL(q, 0, len);
1176 p += len;
1177 len = PTR_DIFF(p, pdata);
1178 len = (len + 3) & ~3;
1179 SIVAL(pdata,0,len);
1180 p = pdata + len;
1181 break;
1183 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1184 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1185 was_8_3 = mangle_is_8_3(fname, True);
1186 p += 4;
1187 SIVAL(p,0,reskey); p += 4;
1188 put_long_date(p,cdate); p += 8;
1189 put_long_date(p,adate); p += 8;
1190 put_long_date(p,mdate); p += 8;
1191 put_long_date(p,mdate); p += 8;
1192 SOFF_T(p,0,file_size); p += 8;
1193 SOFF_T(p,0,allocation_size); p += 8;
1194 SIVAL(p,0,nt_extmode); p += 4;
1195 q = p; p += 4; /* q is placeholder for name length */
1197 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1198 SIVAL(p,0,ea_size); /* Extended attributes */
1199 p +=4;
1201 /* Clear the short name buffer. This is
1202 * IMPORTANT as not doing so will trigger
1203 * a Win2k client bug. JRA.
1205 memset(p,'\0',26);
1206 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1207 pstring mangled_name;
1208 pstrcpy(mangled_name, fname);
1209 mangle_map(mangled_name,True,True,SNUM(conn));
1210 mangled_name[12] = 0;
1211 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1212 SSVAL(p, 0, len);
1213 } else {
1214 SSVAL(p,0,0);
1215 *(p+2) = 0;
1217 p += 26;
1218 SSVAL(p,0,0); p += 2; /* Reserved ? */
1219 SIVAL(p,0,sbuf.st_dev); p += 4;
1220 SIVAL(p,0,sbuf.st_ino); p += 4;
1221 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1222 SIVAL(q,0,len);
1223 p += len;
1224 len = PTR_DIFF(p, pdata);
1225 len = (len + 3) & ~3;
1226 SIVAL(pdata,0,len);
1227 p = pdata + len;
1228 break;
1230 /* CIFS UNIX Extension. */
1232 case SMB_FIND_FILE_UNIX:
1233 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1234 p+= 4;
1235 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1237 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1238 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1239 p+= 8;
1241 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1242 p+= 8;
1244 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1245 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1246 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1247 p+= 24;
1249 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1250 SIVAL(p,4,0);
1251 p+= 8;
1253 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1254 SIVAL(p,4,0);
1255 p+= 8;
1257 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1258 p+= 4;
1260 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1261 SIVAL(p,4,0);
1262 p+= 8;
1264 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1265 SIVAL(p,4,0);
1266 p+= 8;
1268 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1269 p+= 8;
1271 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1272 SIVAL(p,4,0);
1273 p+= 8;
1275 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1276 SIVAL(p,4,0);
1277 p+= 8;
1279 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1280 p += len;
1282 len = PTR_DIFF(p, pdata);
1283 len = (len + 3) & ~3;
1284 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1285 p = pdata + len;
1286 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1288 break;
1290 default:
1291 return(False);
1295 if (PTR_DIFF(p,pdata) > space_remaining) {
1296 /* Move the dirptr back to prev_dirpos */
1297 SeekDir(conn->dirptr, prev_dirpos);
1298 *out_of_space = True;
1299 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1300 return False; /* Not finished - just out of space */
1303 /* Setup the last_filename pointer, as an offset from base_data */
1304 *last_name_off = PTR_DIFF(nameptr,base_data);
1305 /* Advance the data pointer to the next slot */
1306 *ppdata = p;
1308 return(found);
1311 /****************************************************************************
1312 Reply to a TRANS2_FINDFIRST.
1313 ****************************************************************************/
1315 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1316 char **pparams, int total_params, char **ppdata, int total_data)
1318 /* We must be careful here that we don't return more than the
1319 allowed number of data bytes. If this means returning fewer than
1320 maxentries then so be it. We assume that the redirector has
1321 enough room for the fixed number of parameter bytes it has
1322 requested. */
1323 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1324 char *params = *pparams;
1325 char *pdata = *ppdata;
1326 int dirtype = SVAL(params,0);
1327 int maxentries = SVAL(params,2);
1328 BOOL close_after_first = BITSETW(params+4,0);
1329 BOOL close_if_end = BITSETW(params+4,1);
1330 BOOL requires_resume_key = BITSETW(params+4,2);
1331 int info_level = SVAL(params,6);
1332 pstring directory;
1333 pstring mask;
1334 char *p, *wcard;
1335 int last_name_off=0;
1336 int dptr_num = -1;
1337 int numentries = 0;
1338 int i;
1339 BOOL finished = False;
1340 BOOL dont_descend = False;
1341 BOOL out_of_space = False;
1342 int space_remaining;
1343 BOOL bad_path = False;
1344 SMB_STRUCT_STAT sbuf;
1345 NTSTATUS ntstatus = NT_STATUS_OK;
1347 if (total_params < 12)
1348 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1350 *directory = *mask = 0;
1352 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1353 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1354 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1355 info_level, max_data_bytes));
1357 switch (info_level) {
1358 case SMB_INFO_STANDARD:
1359 case SMB_INFO_QUERY_EA_SIZE:
1360 case SMB_FIND_FILE_DIRECTORY_INFO:
1361 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1362 case SMB_FIND_FILE_NAMES_INFO:
1363 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1364 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1365 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1366 break;
1367 case SMB_FIND_FILE_UNIX:
1368 if (!lp_unix_extensions())
1369 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1370 break;
1371 default:
1372 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1375 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus);
1376 if (!NT_STATUS_IS_OK(ntstatus)) {
1377 return ERROR_NT(ntstatus);
1380 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
1382 unix_convert(directory,conn,0,&bad_path,&sbuf);
1383 if(!check_name(directory,conn)) {
1384 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1387 p = strrchr_m(directory,'/');
1388 if(p == NULL) {
1389 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1390 if((directory[0] == '.') && (directory[1] == '\0'))
1391 pstrcpy(mask,"*");
1392 else
1393 pstrcpy(mask,directory);
1394 pstrcpy(directory,"./");
1395 } else {
1396 pstrcpy(mask,p+1);
1397 *p = 0;
1400 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1402 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1403 if( pdata == NULL )
1404 return(ERROR_DOS(ERRDOS,ERRnomem));
1406 *ppdata = pdata;
1407 memset((char *)pdata,'\0',max_data_bytes + 1024);
1409 /* Realloc the params space */
1410 params = Realloc(*pparams, 10);
1411 if (params == NULL)
1412 return ERROR_DOS(ERRDOS,ERRnomem);
1413 *pparams = params;
1415 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1416 if (dptr_num < 0)
1417 return(UNIXERROR(ERRDOS,ERRbadfile));
1419 /* Save the wildcard match and attribs we are using on this directory -
1420 needed as lanman2 assumes these are being saved between calls */
1422 if(!(wcard = strdup(mask))) {
1423 dptr_close(&dptr_num);
1424 return ERROR_DOS(ERRDOS,ERRnomem);
1427 dptr_set_wcard(dptr_num, wcard);
1428 dptr_set_attr(dptr_num, dirtype);
1430 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
1432 /* We don't need to check for VOL here as this is returned by
1433 a different TRANS2 call. */
1435 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1436 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1437 dont_descend = True;
1439 p = pdata;
1440 space_remaining = max_data_bytes;
1441 out_of_space = False;
1443 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1444 BOOL got_exact_match = False;
1446 /* this is a heuristic to avoid seeking the dirptr except when
1447 absolutely necessary. It allows for a filename of about 40 chars */
1448 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1449 out_of_space = True;
1450 finished = False;
1451 } else {
1452 finished = !get_lanman2_dir_entry(conn,
1453 inbuf, outbuf,
1454 mask,dirtype,info_level,
1455 requires_resume_key,dont_descend,
1456 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1457 &last_name_off);
1460 if (finished && out_of_space)
1461 finished = False;
1463 if (!finished && !out_of_space)
1464 numentries++;
1467 * As an optimisation if we know we aren't looking
1468 * for a wildcard name (ie. the name matches the wildcard exactly)
1469 * then we can finish on any (first) match.
1470 * This speeds up large directory searches. JRA.
1473 if(got_exact_match)
1474 finished = True;
1476 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1479 /* Check if we can close the dirptr */
1480 if(close_after_first || (finished && close_if_end)) {
1481 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1482 dptr_close(&dptr_num);
1486 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1487 * from observation of NT.
1490 if(numentries == 0) {
1491 dptr_close(&dptr_num);
1492 return ERROR_DOS(ERRDOS,ERRbadfile);
1495 /* At this point pdata points to numentries directory entries. */
1497 /* Set up the return parameter block */
1498 SSVAL(params,0,dptr_num);
1499 SSVAL(params,2,numentries);
1500 SSVAL(params,4,finished);
1501 SSVAL(params,6,0); /* Never an EA error */
1502 SSVAL(params,8,last_name_off);
1504 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1506 if ((! *directory) && dptr_path(dptr_num))
1507 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1509 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1510 smb_fn_name(CVAL(inbuf,smb_com)),
1511 mask, directory, dirtype, numentries ) );
1514 * Force a name mangle here to ensure that the
1515 * mask as an 8.3 name is top of the mangled cache.
1516 * The reasons for this are subtle. Don't remove
1517 * this code unless you know what you are doing
1518 * (see PR#13758). JRA.
1521 if(!mangle_is_8_3_wildcards( mask, False))
1522 mangle_map(mask, True, True, SNUM(conn));
1524 return(-1);
1527 /****************************************************************************
1528 Reply to a TRANS2_FINDNEXT.
1529 ****************************************************************************/
1531 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1532 char **pparams, int total_params, char **ppdata, int total_data)
1534 /* We must be careful here that we don't return more than the
1535 allowed number of data bytes. If this means returning fewer than
1536 maxentries then so be it. We assume that the redirector has
1537 enough room for the fixed number of parameter bytes it has
1538 requested. */
1539 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1540 char *params = *pparams;
1541 char *pdata = *ppdata;
1542 int dptr_num = SVAL(params,0);
1543 int maxentries = SVAL(params,2);
1544 uint16 info_level = SVAL(params,4);
1545 uint32 resume_key = IVAL(params,6);
1546 BOOL close_after_request = BITSETW(params+10,0);
1547 BOOL close_if_end = BITSETW(params+10,1);
1548 BOOL requires_resume_key = BITSETW(params+10,2);
1549 BOOL continue_bit = BITSETW(params+10,3);
1550 pstring resume_name;
1551 pstring mask;
1552 pstring directory;
1553 char *p;
1554 uint16 dirtype;
1555 int numentries = 0;
1556 int i, last_name_off=0;
1557 BOOL finished = False;
1558 BOOL dont_descend = False;
1559 BOOL out_of_space = False;
1560 int space_remaining;
1561 NTSTATUS ntstatus = NT_STATUS_OK;
1563 if (total_params < 12)
1564 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1566 *mask = *directory = *resume_name = 0;
1568 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus);
1569 if (!NT_STATUS_IS_OK(ntstatus)) {
1570 return ERROR_NT(ntstatus);
1573 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1574 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1575 resume_key = %d resume name = %s continue=%d level = %d\n",
1576 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1577 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1579 switch (info_level) {
1580 case SMB_INFO_STANDARD:
1581 case SMB_INFO_QUERY_EA_SIZE:
1582 case SMB_FIND_FILE_DIRECTORY_INFO:
1583 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1584 case SMB_FIND_FILE_NAMES_INFO:
1585 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1586 break;
1587 case SMB_FIND_FILE_UNIX:
1588 if (!lp_unix_extensions())
1589 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1590 break;
1591 default:
1592 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1595 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1596 if(pdata == NULL)
1597 return ERROR_DOS(ERRDOS,ERRnomem);
1599 *ppdata = pdata;
1600 memset((char *)pdata,'\0',max_data_bytes + 1024);
1602 /* Realloc the params space */
1603 params = Realloc(*pparams, 6*SIZEOFWORD);
1604 if( params == NULL )
1605 return ERROR_DOS(ERRDOS,ERRnomem);
1607 *pparams = params;
1609 /* Check that the dptr is valid */
1610 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1611 return ERROR_DOS(ERRDOS,ERRnofiles);
1613 string_set(&conn->dirpath,dptr_path(dptr_num));
1615 /* Get the wildcard mask from the dptr */
1616 if((p = dptr_wcard(dptr_num))== NULL) {
1617 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1618 return ERROR_DOS(ERRDOS,ERRnofiles);
1621 pstrcpy(mask, p);
1622 pstrcpy(directory,conn->dirpath);
1624 /* Get the attr mask from the dptr */
1625 dirtype = dptr_attr(dptr_num);
1627 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1628 dptr_num, mask, dirtype,
1629 (long)conn->dirptr,
1630 TellDir(conn->dirptr)));
1632 /* We don't need to check for VOL here as this is returned by
1633 a different TRANS2 call. */
1635 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1636 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
1637 dont_descend = True;
1639 p = pdata;
1640 space_remaining = max_data_bytes;
1641 out_of_space = False;
1644 * Seek to the correct position. We no longer use the resume key but
1645 * depend on the last file name instead.
1648 if(requires_resume_key && *resume_name && !continue_bit) {
1651 * Fix for NT redirector problem triggered by resume key indexes
1652 * changing between directory scans. We now return a resume key of 0
1653 * and instead look for the filename to continue from (also given
1654 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1655 * findfirst/findnext (as is usual) then the directory pointer
1656 * should already be at the correct place. Check this by scanning
1657 * backwards looking for an exact (ie. case sensitive) filename match.
1658 * If we get to the beginning of the directory and haven't found it then scan
1659 * forwards again looking for a match. JRA.
1662 int current_pos, start_pos;
1663 const char *dname = NULL;
1664 pstring dname_pstring;
1665 void *dirptr = conn->dirptr;
1666 start_pos = TellDir(dirptr);
1667 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1668 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1670 SeekDir(dirptr, current_pos);
1671 dname = ReadDirName(dirptr);
1672 if (dname) {
1674 * Remember, mangle_map is called by
1675 * get_lanman2_dir_entry(), so the resume name
1676 * could be mangled. Ensure we do the same
1677 * here.
1680 /* make sure we get a copy that mangle_map can modify */
1682 pstrcpy(dname_pstring, dname);
1683 mangle_map( dname_pstring, False, True, SNUM(conn));
1685 if(strcsequal( resume_name, dname_pstring)) {
1686 SeekDir(dirptr, current_pos+1);
1687 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1688 break;
1694 * Scan forward from start if not found going backwards.
1697 if(current_pos < 0) {
1698 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1699 SeekDir(dirptr, start_pos);
1700 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1703 * Remember, mangle_map is called by
1704 * get_lanman2_dir_entry(), so the resume name
1705 * could be mangled. Ensure we do the same
1706 * here.
1709 if(dname) {
1710 /* make sure we get a copy that mangle_map can modify */
1712 pstrcpy(dname_pstring, dname);
1713 mangle_map(dname_pstring, False, True, SNUM(conn));
1715 if(strcsequal( resume_name, dname_pstring)) {
1716 SeekDir(dirptr, current_pos+1);
1717 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1718 break;
1721 } /* end for */
1722 } /* end if current_pos */
1723 } /* end if requires_resume_key && !continue_bit */
1725 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1726 BOOL got_exact_match = False;
1728 /* this is a heuristic to avoid seeking the dirptr except when
1729 absolutely necessary. It allows for a filename of about 40 chars */
1730 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1731 out_of_space = True;
1732 finished = False;
1733 } else {
1734 finished = !get_lanman2_dir_entry(conn,
1735 inbuf, outbuf,
1736 mask,dirtype,info_level,
1737 requires_resume_key,dont_descend,
1738 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1739 &last_name_off);
1742 if (finished && out_of_space)
1743 finished = False;
1745 if (!finished && !out_of_space)
1746 numentries++;
1749 * As an optimisation if we know we aren't looking
1750 * for a wildcard name (ie. the name matches the wildcard exactly)
1751 * then we can finish on any (first) match.
1752 * This speeds up large directory searches. JRA.
1755 if(got_exact_match)
1756 finished = True;
1758 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1761 /* Check if we can close the dirptr */
1762 if(close_after_request || (finished && close_if_end)) {
1763 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1764 dptr_close(&dptr_num); /* This frees up the saved mask */
1767 /* Set up the return parameter block */
1768 SSVAL(params,0,numentries);
1769 SSVAL(params,2,finished);
1770 SSVAL(params,4,0); /* Never an EA error */
1771 SSVAL(params,6,last_name_off);
1773 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1775 if ((! *directory) && dptr_path(dptr_num))
1776 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1778 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1779 smb_fn_name(CVAL(inbuf,smb_com)),
1780 mask, directory, dirtype, numentries ) );
1782 return(-1);
1785 /****************************************************************************
1786 Reply to a TRANS2_QFSINFO (query filesystem info).
1787 ****************************************************************************/
1789 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1790 int length, int bufsize,
1791 char **pparams, int total_params, char **ppdata, int total_data)
1793 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1794 char *pdata = *ppdata;
1795 char *params = *pparams;
1796 uint16 info_level = SVAL(params,0);
1797 int data_len, len;
1798 SMB_STRUCT_STAT st;
1799 char *vname = volume_label(SNUM(conn));
1800 int snum = SNUM(conn);
1801 char *fstype = lp_fstype(SNUM(conn));
1802 int quota_flag = 0;
1804 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1806 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1807 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1808 return ERROR_DOS(ERRSRV,ERRinvdevice);
1811 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1812 if ( pdata == NULL )
1813 return ERROR_DOS(ERRDOS,ERRnomem);
1815 *ppdata = pdata;
1816 memset((char *)pdata,'\0',max_data_bytes + 1024);
1818 switch (info_level) {
1819 case SMB_INFO_ALLOCATION:
1821 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1822 data_len = 18;
1823 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1824 block_size = lp_block_size(snum);
1825 if (bsize < block_size) {
1826 SMB_BIG_UINT factor = block_size/bsize;
1827 bsize = block_size;
1828 dsize /= factor;
1829 dfree /= factor;
1831 if (bsize > block_size) {
1832 SMB_BIG_UINT factor = bsize/block_size;
1833 bsize = block_size;
1834 dsize *= factor;
1835 dfree *= factor;
1837 bytes_per_sector = 512;
1838 sectors_per_unit = bsize/bytes_per_sector;
1840 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1841 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1842 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1844 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1845 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1846 SIVAL(pdata,l1_cUnit,dsize);
1847 SIVAL(pdata,l1_cUnitAvail,dfree);
1848 SSVAL(pdata,l1_cbSector,bytes_per_sector);
1849 break;
1852 case SMB_INFO_VOLUME:
1853 /* Return volume name */
1855 * Add volume serial number - hash of a combination of
1856 * the called hostname and the service name.
1858 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1859 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1860 SCVAL(pdata,l2_vol_cch,len);
1861 data_len = l2_vol_szVolLabel + len;
1862 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1863 (unsigned)st.st_ctime, len, vname));
1864 break;
1866 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1867 case SMB_FS_ATTRIBUTE_INFORMATION:
1870 #if defined(HAVE_SYS_QUOTAS)
1871 quota_flag = FILE_VOLUME_QUOTAS;
1872 #endif
1874 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1875 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1876 quota_flag); /* FS ATTRIBUTES */
1878 SIVAL(pdata,4,255); /* Max filename component length */
1879 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1880 and will think we can't do long filenames */
1881 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1882 SIVAL(pdata,8,len);
1883 data_len = 12 + len;
1884 break;
1886 case SMB_QUERY_FS_LABEL_INFO:
1887 case SMB_FS_LABEL_INFORMATION:
1888 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1889 data_len = 4 + len;
1890 SIVAL(pdata,0,len);
1891 break;
1893 case SMB_QUERY_FS_VOLUME_INFO:
1894 case SMB_FS_VOLUME_INFORMATION:
1897 * Add volume serial number - hash of a combination of
1898 * the called hostname and the service name.
1900 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1901 (str_checksum(local_machine)<<16));
1903 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1904 SIVAL(pdata,12,len);
1905 data_len = 18+len;
1906 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1907 (int)strlen(vname),vname, lp_servicename(snum)));
1908 break;
1910 case SMB_QUERY_FS_SIZE_INFO:
1911 case SMB_FS_SIZE_INFORMATION:
1913 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1914 data_len = 24;
1915 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1916 block_size = lp_block_size(snum);
1917 if (bsize < block_size) {
1918 SMB_BIG_UINT factor = block_size/bsize;
1919 bsize = block_size;
1920 dsize /= factor;
1921 dfree /= factor;
1923 if (bsize > block_size) {
1924 SMB_BIG_UINT factor = bsize/block_size;
1925 bsize = block_size;
1926 dsize *= factor;
1927 dfree *= factor;
1929 bytes_per_sector = 512;
1930 sectors_per_unit = bsize/bytes_per_sector;
1931 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1932 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1933 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1934 SBIG_UINT(pdata,0,dsize);
1935 SBIG_UINT(pdata,8,dfree);
1936 SIVAL(pdata,16,sectors_per_unit);
1937 SIVAL(pdata,20,bytes_per_sector);
1938 break;
1941 case SMB_FS_FULL_SIZE_INFORMATION:
1943 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1944 data_len = 32;
1945 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1946 block_size = lp_block_size(snum);
1947 if (bsize < block_size) {
1948 SMB_BIG_UINT factor = block_size/bsize;
1949 bsize = block_size;
1950 dsize /= factor;
1951 dfree /= factor;
1953 if (bsize > block_size) {
1954 SMB_BIG_UINT factor = bsize/block_size;
1955 bsize = block_size;
1956 dsize *= factor;
1957 dfree *= factor;
1959 bytes_per_sector = 512;
1960 sectors_per_unit = bsize/bytes_per_sector;
1961 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1962 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1963 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1964 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1965 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1966 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1967 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1968 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1969 break;
1972 case SMB_QUERY_FS_DEVICE_INFO:
1973 case SMB_FS_DEVICE_INFORMATION:
1974 data_len = 8;
1975 SIVAL(pdata,0,0); /* dev type */
1976 SIVAL(pdata,4,0); /* characteristics */
1977 break;
1979 #ifdef HAVE_SYS_QUOTAS
1980 case SMB_FS_QUOTA_INFORMATION:
1982 * what we have to send --metze:
1984 * Unknown1: 24 NULL bytes
1985 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1986 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
1987 * Quota Flags: 2 byte :
1988 * Unknown3: 6 NULL bytes
1990 * 48 bytes total
1992 * details for Quota Flags:
1994 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1995 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
1996 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1997 * 0x0001 Enable Quotas: enable quota for this fs
2001 /* we need to fake up a fsp here,
2002 * because its not send in this call
2004 files_struct fsp;
2005 SMB_NTQUOTA_STRUCT quotas;
2007 ZERO_STRUCT(fsp);
2008 ZERO_STRUCT(quotas);
2010 fsp.conn = conn;
2011 fsp.fnum = -1;
2012 fsp.fd = -1;
2014 /* access check */
2015 if (current_user.uid != 0) {
2016 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2017 lp_servicename(SNUM(conn)),conn->user));
2018 return ERROR_DOS(ERRDOS,ERRnoaccess);
2021 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2022 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2023 return ERROR_DOS(ERRSRV,ERRerror);
2026 data_len = 48;
2028 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2030 /* Unknown1 24 NULL bytes*/
2031 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2032 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2033 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2035 /* Default Soft Quota 8 bytes */
2036 SBIG_UINT(pdata,24,quotas.softlim);
2038 /* Default Hard Quota 8 bytes */
2039 SBIG_UINT(pdata,32,quotas.hardlim);
2041 /* Quota flag 2 bytes */
2042 SSVAL(pdata,40,quotas.qflags);
2044 /* Unknown3 6 NULL bytes */
2045 SSVAL(pdata,42,0);
2046 SIVAL(pdata,44,0);
2048 break;
2050 #endif /* HAVE_SYS_QUOTAS */
2051 case SMB_FS_OBJECTID_INFORMATION:
2052 data_len = 64;
2053 break;
2056 * Query the version and capabilities of the CIFS UNIX extensions
2057 * in use.
2060 case SMB_QUERY_CIFS_UNIX_INFO:
2061 if (!lp_unix_extensions())
2062 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2063 data_len = 12;
2064 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2065 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2066 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
2067 break;
2069 case SMB_MAC_QUERY_FS_INFO:
2071 * Thursby MAC extension... ONLY on NTFS filesystems
2072 * once we do streams then we don't need this
2074 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2075 data_len = 88;
2076 SIVAL(pdata,84,0x100); /* Don't support mac... */
2077 break;
2079 /* drop through */
2080 default:
2081 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2085 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2087 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2089 return -1;
2092 #ifdef HAVE_SYS_QUOTAS
2093 /****************************************************************************
2094 Reply to a TRANS2_SETFSINFO (set filesystem info).
2095 ****************************************************************************/
2097 static int call_trans2setfsinfo(connection_struct *conn,
2098 char *inbuf, char *outbuf, int length, int bufsize,
2099 char **pparams, int total_params, char **ppdata, int total_data)
2101 char *pdata = *ppdata;
2102 char *params = *pparams;
2103 files_struct *fsp = NULL;
2104 uint16 info_level;
2105 int outsize;
2106 SMB_NTQUOTA_STRUCT quotas;
2108 ZERO_STRUCT(quotas);
2110 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2112 /* access check */
2113 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2114 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2115 lp_servicename(SNUM(conn)),conn->user));
2116 return ERROR_DOS(ERRSRV,ERRaccess);
2119 /* */
2120 if (total_params < 4) {
2121 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2122 total_params));
2123 return ERROR_DOS(ERRDOS,ERRinvalidparam);
2126 fsp = file_fsp(params,0);
2128 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2129 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2130 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2133 info_level = SVAL(params,2);
2135 switch(info_level) {
2136 case SMB_FS_QUOTA_INFORMATION:
2137 /* note: normaly there're 48 bytes,
2138 * but we didn't use the last 6 bytes for now
2139 * --metze
2141 if (total_data < 42) {
2142 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2143 total_data));
2144 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2147 /* unknown_1 24 NULL bytes in pdata*/
2149 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2150 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2151 #ifdef LARGE_SMB_OFF_T
2152 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2153 #else /* LARGE_SMB_OFF_T */
2154 if ((IVAL(pdata,28) != 0)&&
2155 ((quotas.softlim != 0xFFFFFFFF)||
2156 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2157 /* more than 32 bits? */
2158 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2160 #endif /* LARGE_SMB_OFF_T */
2162 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2163 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2164 #ifdef LARGE_SMB_OFF_T
2165 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2166 #else /* LARGE_SMB_OFF_T */
2167 if ((IVAL(pdata,36) != 0)&&
2168 ((quotas.hardlim != 0xFFFFFFFF)||
2169 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2170 /* more than 32 bits? */
2171 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2173 #endif /* LARGE_SMB_OFF_T */
2175 /* quota_flags 2 bytes **/
2176 quotas.qflags = SVAL(pdata,40);
2178 /* unknown_2 6 NULL bytes follow*/
2180 /* now set the quotas */
2181 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2182 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2183 return ERROR_DOS(ERRSRV,ERRerror);
2186 break;
2187 default:
2188 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2189 info_level));
2190 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2191 break;
2195 * sending this reply works fine,
2196 * but I'm not sure it's the same
2197 * like windows do...
2198 * --metze
2200 outsize = set_message(outbuf,10,0,True);
2202 return outsize;
2204 #endif /* HAVE_SYS_QUOTAS */
2206 /****************************************************************************
2207 * Utility function to set bad path error.
2208 ****************************************************************************/
2210 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2212 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2213 err, (int)bad_path ));
2215 if(err == ENOENT) {
2216 if (bad_path) {
2217 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2218 } else {
2219 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2222 return UNIXERROR(def_class,def_code);
2225 /****************************************************************************
2226 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2227 file name or file id).
2228 ****************************************************************************/
2230 static int call_trans2qfilepathinfo(connection_struct *conn,
2231 char *inbuf, char *outbuf, int length,
2232 int bufsize,
2233 char **pparams, int total_params, char **ppdata, int total_data)
2235 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
2236 char *params = *pparams;
2237 char *pdata = *ppdata;
2238 uint16 tran_call = SVAL(inbuf, smb_setup0);
2239 uint16 info_level;
2240 int mode=0;
2241 SMB_OFF_T file_size=0;
2242 SMB_BIG_UINT allocation_size=0;
2243 unsigned int data_size;
2244 unsigned int param_size = 2;
2245 SMB_STRUCT_STAT sbuf;
2246 pstring fname, dos_fname;
2247 char *fullpathname;
2248 char *base_name;
2249 char *p;
2250 SMB_OFF_T pos = 0;
2251 BOOL bad_path = False;
2252 BOOL delete_pending = False;
2253 int len;
2254 time_t c_time;
2255 files_struct *fsp = NULL;
2256 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2258 if (!params)
2259 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2261 if (tran_call == TRANSACT2_QFILEINFO) {
2262 if (total_params < 4)
2263 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2265 fsp = file_fsp(params,0);
2266 info_level = SVAL(params,2);
2268 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2270 if(fsp && (fsp->fake_file_handle)) {
2272 * This is actually for the QUOTA_FAKE_FILE --metze
2275 pstrcpy(fname, fsp->fsp_name);
2276 unix_convert(fname,conn,0,&bad_path,&sbuf);
2277 if (!check_name(fname,conn)) {
2278 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno)));
2279 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2282 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2284 * This is actually a QFILEINFO on a directory
2285 * handle (returned from an NT SMB). NT5.0 seems
2286 * to do this call. JRA.
2288 pstrcpy(fname, fsp->fsp_name);
2289 unix_convert(fname,conn,0,&bad_path,&sbuf);
2290 if (!check_name(fname,conn)) {
2291 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2292 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2295 if (INFO_LEVEL_IS_UNIX(info_level)) {
2296 /* Always do lstat for UNIX calls. */
2297 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2298 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2299 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2301 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
2302 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2303 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2306 delete_pending = fsp->directory_delete_on_close;
2307 } else {
2309 * Original code - this is an open file.
2311 CHECK_FSP(fsp,conn);
2313 pstrcpy(fname, fsp->fsp_name);
2314 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2315 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2316 return(UNIXERROR(ERRDOS,ERRbadfid));
2318 pos = fsp->position_information;
2319 delete_pending = fsp->delete_on_close;
2320 desired_access = fsp->desired_access;
2322 } else {
2323 NTSTATUS status = NT_STATUS_OK;
2325 /* qpathinfo */
2326 if (total_params < 6)
2327 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2329 info_level = SVAL(params,0);
2331 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2333 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
2334 if (!NT_STATUS_IS_OK(status)) {
2335 return ERROR_NT(status);
2338 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2340 unix_convert(fname,conn,0,&bad_path,&sbuf);
2341 if (!check_name(fname,conn)) {
2342 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2343 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2346 if (INFO_LEVEL_IS_UNIX(info_level)) {
2347 /* Always do lstat for UNIX calls. */
2348 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2349 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2350 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2352 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2353 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2354 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2358 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2359 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2361 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2362 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2364 p = strrchr_m(fname,'/');
2365 if (!p)
2366 base_name = fname;
2367 else
2368 base_name = p+1;
2370 mode = dos_mode(conn,fname,&sbuf);
2371 if (!mode)
2372 mode = FILE_ATTRIBUTE_NORMAL;
2374 fullpathname = fname;
2375 file_size = get_file_size(sbuf);
2376 allocation_size = get_allocation_size(fsp,&sbuf);
2377 if (mode & aDIR)
2378 file_size = 0;
2380 params = Realloc(*pparams,2);
2381 if (params == NULL)
2382 return ERROR_DOS(ERRDOS,ERRnomem);
2383 *pparams = params;
2384 memset((char *)params,'\0',2);
2385 data_size = max_data_bytes + 1024;
2386 pdata = Realloc(*ppdata, data_size);
2387 if ( pdata == NULL )
2388 return ERROR_DOS(ERRDOS,ERRnomem);
2389 *ppdata = pdata;
2391 if (total_data > 0 && IVAL(pdata,0) == total_data) {
2392 /* uggh, EAs for OS2 */
2393 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2394 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2397 memset((char *)pdata,'\0',data_size);
2399 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2401 if (lp_dos_filetime_resolution(SNUM(conn))) {
2402 c_time &= ~1;
2403 sbuf.st_atime &= ~1;
2404 sbuf.st_mtime &= ~1;
2405 sbuf.st_mtime &= ~1;
2408 /* NT expects the name to be in an exact form of the *full*
2409 filename. See the trans2 torture test */
2410 if (strequal(base_name,".")) {
2411 pstrcpy(dos_fname, "\\");
2412 } else {
2413 pstr_sprintf(dos_fname, "\\%s", fname);
2414 string_replace(dos_fname, '/', '\\');
2417 switch (info_level) {
2418 case SMB_INFO_STANDARD:
2419 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2420 data_size = 22;
2421 put_dos_date2(pdata,l1_fdateCreation,c_time);
2422 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2423 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2424 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2425 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2426 SSVAL(pdata,l1_attrFile,mode);
2427 break;
2429 case SMB_INFO_QUERY_EA_SIZE:
2431 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2432 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2433 data_size = 26;
2434 put_dos_date2(pdata,l1_fdateCreation,c_time);
2435 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2436 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2437 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2438 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2439 SSVAL(pdata,l1_attrFile,mode);
2440 SIVAL(pdata,l1_attrFile+2,ea_size);
2441 break;
2444 case SMB_INFO_IS_NAME_VALID:
2445 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2446 if (tran_call == TRANSACT2_QFILEINFO) {
2447 /* os/2 needs this ? really ?*/
2448 return ERROR_DOS(ERRDOS,ERRbadfunc);
2450 data_size = 0;
2451 param_size = 0;
2452 break;
2454 case SMB_INFO_QUERY_EAS_FROM_LIST:
2455 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2456 data_size = 24;
2457 put_dos_date2(pdata,0,c_time);
2458 put_dos_date2(pdata,4,sbuf.st_atime);
2459 put_dos_date2(pdata,8,sbuf.st_mtime);
2460 SIVAL(pdata,12,(uint32)file_size);
2461 SIVAL(pdata,16,(uint32)allocation_size);
2462 SIVAL(pdata,20,mode);
2463 break;
2465 case SMB_INFO_QUERY_ALL_EAS:
2466 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2467 /* We have data_size bytes to put EA's into. */
2468 data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname);
2469 break;
2471 case SMB_FILE_BASIC_INFORMATION:
2472 case SMB_QUERY_FILE_BASIC_INFO:
2474 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2475 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2476 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2477 } else {
2478 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2479 data_size = 40;
2480 SIVAL(pdata,36,0);
2482 put_long_date(pdata,c_time);
2483 put_long_date(pdata+8,sbuf.st_atime);
2484 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2485 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2486 SIVAL(pdata,32,mode);
2488 DEBUG(5,("SMB_QFBI - "));
2490 time_t create_time = c_time;
2491 DEBUG(5,("create: %s ", ctime(&create_time)));
2493 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2494 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2495 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2496 DEBUG(5,("mode: %x\n", mode));
2498 break;
2500 case SMB_FILE_STANDARD_INFORMATION:
2501 case SMB_QUERY_FILE_STANDARD_INFO:
2503 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2504 data_size = 24;
2505 SOFF_T(pdata,0,allocation_size);
2506 SOFF_T(pdata,8,file_size);
2507 if (delete_pending & sbuf.st_nlink)
2508 SIVAL(pdata,16,sbuf.st_nlink - 1);
2509 else
2510 SIVAL(pdata,16,sbuf.st_nlink);
2511 SCVAL(pdata,20,0);
2512 SCVAL(pdata,21,(mode&aDIR)?1:0);
2513 break;
2515 case SMB_FILE_EA_INFORMATION:
2516 case SMB_QUERY_FILE_EA_INFO:
2518 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2519 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2520 data_size = 4;
2521 SIVAL(pdata,0,ea_size);
2522 break;
2525 /* Get the 8.3 name - used if NT SMB was negotiated. */
2526 case SMB_QUERY_FILE_ALT_NAME_INFO:
2527 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2529 pstring short_name;
2531 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2532 pstrcpy(short_name,base_name);
2533 /* Mangle if not already 8.3 */
2534 if(!mangle_is_8_3(short_name, True)) {
2535 mangle_map(short_name,True,True,SNUM(conn));
2537 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2538 data_size = 4 + len;
2539 SIVAL(pdata,0,len);
2540 break;
2543 case SMB_QUERY_FILE_NAME_INFO:
2545 this must be *exactly* right for ACLs on mapped drives to work
2547 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2548 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2549 data_size = 4 + len;
2550 SIVAL(pdata,0,len);
2551 break;
2553 case SMB_FILE_ALLOCATION_INFORMATION:
2554 case SMB_QUERY_FILE_ALLOCATION_INFO:
2555 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2556 data_size = 8;
2557 SOFF_T(pdata,0,allocation_size);
2558 break;
2560 case SMB_FILE_END_OF_FILE_INFORMATION:
2561 case SMB_QUERY_FILE_END_OF_FILEINFO:
2562 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2563 data_size = 8;
2564 SOFF_T(pdata,0,file_size);
2565 break;
2567 case SMB_QUERY_FILE_ALL_INFO:
2568 case SMB_FILE_ALL_INFORMATION:
2570 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2571 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2572 put_long_date(pdata,c_time);
2573 put_long_date(pdata+8,sbuf.st_atime);
2574 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2575 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2576 SIVAL(pdata,32,mode);
2577 pdata += 40;
2578 SOFF_T(pdata,0,allocation_size);
2579 SOFF_T(pdata,8,file_size);
2580 if (delete_pending && sbuf.st_nlink)
2581 SIVAL(pdata,16,sbuf.st_nlink - 1);
2582 else
2583 SIVAL(pdata,16,sbuf.st_nlink);
2584 SCVAL(pdata,20,delete_pending);
2585 SCVAL(pdata,21,(mode&aDIR)?1:0);
2586 pdata += 24;
2587 SIVAL(pdata,0,ea_size);
2588 pdata += 4; /* EA info */
2589 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2590 SIVAL(pdata,0,len);
2591 pdata += 4 + len;
2592 data_size = PTR_DIFF(pdata,(*ppdata));
2593 break;
2595 case SMB_FILE_INTERNAL_INFORMATION:
2596 /* This should be an index number - looks like
2597 dev/ino to me :-)
2599 I think this causes us to fail the IFSKIT
2600 BasicFileInformationTest. -tpot */
2602 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2603 SIVAL(pdata,0,sbuf.st_dev);
2604 SIVAL(pdata,4,sbuf.st_ino);
2605 data_size = 8;
2606 break;
2608 case SMB_FILE_ACCESS_INFORMATION:
2609 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2610 SIVAL(pdata,0,desired_access);
2611 data_size = 4;
2612 break;
2614 case SMB_FILE_NAME_INFORMATION:
2615 /* Pathname with leading '\'. */
2617 size_t byte_len;
2618 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2619 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2620 SIVAL(pdata,0,byte_len);
2621 data_size = 4 + byte_len;
2622 break;
2625 case SMB_FILE_DISPOSITION_INFORMATION:
2626 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2627 data_size = 1;
2628 SCVAL(pdata,0,delete_pending);
2629 break;
2631 case SMB_FILE_POSITION_INFORMATION:
2632 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2633 data_size = 8;
2634 SOFF_T(pdata,0,pos);
2635 break;
2637 case SMB_FILE_MODE_INFORMATION:
2638 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2639 SIVAL(pdata,0,mode);
2640 data_size = 4;
2641 break;
2643 case SMB_FILE_ALIGNMENT_INFORMATION:
2644 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2645 SIVAL(pdata,0,0); /* No alignment needed. */
2646 data_size = 4;
2647 break;
2649 #if 0
2651 * NT4 server just returns "invalid query" to this - if we try to answer
2652 * it then NTws gets a BSOD! (tridge).
2653 * W2K seems to want this. JRA.
2655 case SMB_QUERY_FILE_STREAM_INFO:
2656 #endif
2657 case SMB_FILE_STREAM_INFORMATION:
2658 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2659 if (mode & aDIR) {
2660 data_size = 0;
2661 } else {
2662 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2663 SIVAL(pdata,0,0); /* ??? */
2664 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2665 SOFF_T(pdata,8,file_size);
2666 SIVAL(pdata,16,allocation_size);
2667 SIVAL(pdata,20,0); /* ??? */
2668 data_size = 24 + byte_len;
2670 break;
2672 case SMB_QUERY_COMPRESSION_INFO:
2673 case SMB_FILE_COMPRESSION_INFORMATION:
2674 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2675 SOFF_T(pdata,0,file_size);
2676 SIVAL(pdata,8,0); /* ??? */
2677 SIVAL(pdata,12,0); /* ??? */
2678 data_size = 16;
2679 break;
2681 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2682 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2683 put_long_date(pdata,c_time);
2684 put_long_date(pdata+8,sbuf.st_atime);
2685 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2686 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2687 SIVAL(pdata,32,allocation_size);
2688 SOFF_T(pdata,40,file_size);
2689 SIVAL(pdata,48,mode);
2690 SIVAL(pdata,52,0); /* ??? */
2691 data_size = 56;
2692 break;
2694 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2695 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2696 SIVAL(pdata,0,mode);
2697 SIVAL(pdata,4,0);
2698 data_size = 8;
2699 break;
2702 * CIFS UNIX Extensions.
2705 case SMB_QUERY_FILE_UNIX_BASIC:
2707 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2708 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2710 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2711 pdata += 8;
2713 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2714 pdata += 8;
2716 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2717 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2718 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2719 pdata += 24;
2721 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2722 SIVAL(pdata,4,0);
2723 pdata += 8;
2725 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2726 SIVAL(pdata,4,0);
2727 pdata += 8;
2729 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2730 pdata += 4;
2732 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2733 SIVAL(pdata,4,0);
2734 pdata += 8;
2736 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2737 SIVAL(pdata,4,0);
2738 pdata += 8;
2740 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2741 pdata += 8;
2743 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2744 SIVAL(pdata,4,0);
2745 pdata += 8;
2747 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2748 SIVAL(pdata,4,0);
2749 pdata += 8+1;
2750 data_size = PTR_DIFF(pdata,(*ppdata));
2753 int i;
2754 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2756 for (i=0; i<100; i++)
2757 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2758 DEBUG(4,("\n"));
2761 break;
2763 case SMB_QUERY_FILE_UNIX_LINK:
2765 pstring buffer;
2767 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
2768 #ifdef S_ISLNK
2769 if(!S_ISLNK(sbuf.st_mode))
2770 return(UNIXERROR(ERRSRV,ERRbadlink));
2771 #else
2772 return(UNIXERROR(ERRDOS,ERRbadlink));
2773 #endif
2774 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2775 if (len == -1)
2776 return(UNIXERROR(ERRDOS,ERRnoaccess));
2777 buffer[len] = 0;
2778 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2779 pdata += len;
2780 data_size = PTR_DIFF(pdata,(*ppdata));
2782 break;
2785 default:
2786 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2789 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
2791 return(-1);
2794 /****************************************************************************
2795 Deal with the internal needs of setting the delete on close flag. Note that
2796 as the tdb locking is recursive, it is safe to call this from within
2797 open_file_shared. JRA.
2798 ****************************************************************************/
2800 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2803 * Only allow delete on close for writable shares.
2806 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2807 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2808 fsp->fsp_name ));
2809 return NT_STATUS_ACCESS_DENIED;
2812 * Only allow delete on close for files/directories opened with delete intent.
2815 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2816 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2817 fsp->fsp_name ));
2818 return NT_STATUS_ACCESS_DENIED;
2821 if(fsp->is_directory) {
2822 fsp->directory_delete_on_close = delete_on_close;
2823 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2824 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2825 } else {
2826 fsp->delete_on_close = delete_on_close;
2827 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2828 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2831 return NT_STATUS_OK;
2834 /****************************************************************************
2835 Sets the delete on close flag over all share modes on this file.
2836 Modify the share mode entry for all files open
2837 on this device and inode to tell other smbds we have
2838 changed the delete on close flag. This will be noticed
2839 in the close code, the last closer will delete the file
2840 if flag is set.
2841 ****************************************************************************/
2843 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2845 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2846 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2848 if (fsp->is_directory || fsp->is_stat)
2849 return NT_STATUS_OK;
2851 if (lock_share_entry_fsp(fsp) == False)
2852 return NT_STATUS_ACCESS_DENIED;
2854 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2855 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2856 fsp->fsp_name ));
2857 unlock_share_entry_fsp(fsp);
2858 return NT_STATUS_ACCESS_DENIED;
2861 unlock_share_entry_fsp(fsp);
2862 return NT_STATUS_OK;
2865 /****************************************************************************
2866 Returns true if this pathname is within the share, and thus safe.
2867 ****************************************************************************/
2869 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2871 #ifdef PATH_MAX
2872 char resolved_name[PATH_MAX+1];
2873 #else
2874 pstring resolved_name;
2875 #endif
2876 fstring last_component;
2877 pstring link_dest;
2878 pstring link_test;
2879 char *p;
2880 BOOL bad_path = False;
2881 SMB_STRUCT_STAT sbuf;
2883 pstrcpy(link_dest, link_dest_in);
2884 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2886 /* Store the UNIX converted path. */
2887 pstrcpy(link_dest_out, link_dest);
2889 p = strrchr(link_dest, '/');
2890 if (p) {
2891 fstrcpy(last_component, p+1);
2892 *p = '\0';
2893 } else {
2894 fstrcpy(last_component, link_dest);
2895 pstrcpy(link_dest, "./");
2898 if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL)
2899 return -1;
2901 pstrcpy(link_dest, resolved_name);
2902 pstrcat(link_dest, "/");
2903 pstrcat(link_dest, last_component);
2905 if (*link_dest != '/') {
2906 /* Relative path. */
2907 pstrcpy(link_test, conn->connectpath);
2908 pstrcat(link_test, "/");
2909 pstrcat(link_test, link_dest);
2910 } else {
2911 pstrcpy(link_test, link_dest);
2915 * Check if the link is within the share.
2918 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2919 errno = EACCES;
2920 return -1;
2922 return 0;
2925 /****************************************************************************
2926 Set a hard link (called by UNIX extensions and by NT rename with HARD link
2927 code.
2928 ****************************************************************************/
2930 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
2932 BOOL bad_path_oldname = False;
2933 BOOL bad_path_newname = False;
2934 SMB_STRUCT_STAT sbuf1, sbuf2;
2935 BOOL rc, rcdest;
2936 pstring last_component_oldname;
2937 pstring last_component_newname;
2938 NTSTATUS status = NT_STATUS_OK;
2940 ZERO_STRUCT(sbuf1);
2941 ZERO_STRUCT(sbuf2);
2943 /* No wildcards. */
2944 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
2945 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
2948 rc = unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
2949 if (!rc && bad_path_oldname) {
2950 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2953 /* Quick check for "." and ".." */
2954 if (last_component_oldname[0] == '.') {
2955 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
2956 return NT_STATUS_OBJECT_NAME_INVALID;
2960 /* source must already exist. */
2961 if (!VALID_STAT(sbuf1)) {
2962 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2965 rcdest = unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
2966 if (!rcdest && bad_path_newname) {
2967 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2970 /* Quick check for "." and ".." */
2971 if (last_component_newname[0] == '.') {
2972 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
2973 return NT_STATUS_OBJECT_NAME_INVALID;
2977 /* Disallow if newname already exists. */
2978 if (VALID_STAT(sbuf2)) {
2979 return NT_STATUS_OBJECT_NAME_COLLISION;
2982 /* No links from a directory. */
2983 if (S_ISDIR(sbuf1.st_mode)) {
2984 return NT_STATUS_FILE_IS_A_DIRECTORY;
2987 if (ensure_link_is_safe(conn, oldname, oldname) != 0)
2988 return NT_STATUS_ACCESS_DENIED;
2990 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
2992 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
2993 status = map_nt_error_from_unix(errno);
2994 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
2995 nt_errstr(status), newname, oldname));
2998 return status;
3001 /****************************************************************************
3002 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3003 ****************************************************************************/
3005 static int call_trans2setfilepathinfo(connection_struct *conn,
3006 char *inbuf, char *outbuf, int length, int bufsize,
3007 char **pparams, int total_params, char **ppdata, int total_data)
3009 char *params = *pparams;
3010 char *pdata = *ppdata;
3011 uint16 tran_call = SVAL(inbuf, smb_setup0);
3012 uint16 info_level;
3013 int dosmode=0;
3014 SMB_OFF_T size=0;
3015 struct utimbuf tvs;
3016 SMB_STRUCT_STAT sbuf;
3017 pstring fname;
3018 int fd = -1;
3019 BOOL bad_path = False;
3020 files_struct *fsp = NULL;
3021 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3022 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3023 mode_t unixmode = 0;
3024 NTSTATUS status = NT_STATUS_OK;
3026 if (!params)
3027 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3029 if (tran_call == TRANSACT2_SETFILEINFO) {
3030 if (total_params < 4)
3031 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3033 fsp = file_fsp(params,0);
3034 info_level = SVAL(params,2);
3036 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3038 * This is actually a SETFILEINFO on a directory
3039 * handle (returned from an NT SMB). NT5.0 seems
3040 * to do this call. JRA.
3042 pstrcpy(fname, fsp->fsp_name);
3043 unix_convert(fname,conn,0,&bad_path,&sbuf);
3044 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
3045 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3046 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3048 } else if (fsp && fsp->print_file) {
3050 * Doing a DELETE_ON_CLOSE should cancel a print job.
3052 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3053 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3055 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3057 SSVAL(params,0,0);
3058 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3059 return(-1);
3060 } else
3061 return (UNIXERROR(ERRDOS,ERRbadpath));
3062 } else {
3064 * Original code - this is an open file.
3066 CHECK_FSP(fsp,conn);
3068 pstrcpy(fname, fsp->fsp_name);
3069 fd = fsp->fd;
3071 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3072 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3073 return(UNIXERROR(ERRDOS,ERRbadfid));
3076 } else {
3077 /* set path info */
3078 if (total_params < 6)
3079 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3081 info_level = SVAL(params,0);
3082 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
3083 if (!NT_STATUS_IS_OK(status)) {
3084 return ERROR_NT(status);
3086 unix_convert(fname,conn,0,&bad_path,&sbuf);
3089 * For CIFS UNIX extensions the target name may not exist.
3092 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3093 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3094 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3097 if(!check_name(fname, conn)) {
3098 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3103 if (!CAN_WRITE(conn))
3104 return ERROR_DOS(ERRSRV,ERRaccess);
3106 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3107 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3109 if (VALID_STAT(sbuf))
3110 unixmode = sbuf.st_mode;
3112 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3113 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3115 /* Realloc the parameter and data sizes */
3116 params = Realloc(*pparams,2);
3117 if(params == NULL)
3118 return ERROR_DOS(ERRDOS,ERRnomem);
3119 *pparams = params;
3121 SSVAL(params,0,0);
3123 if (fsp) {
3124 /* the pending modtime overrides the current modtime */
3125 sbuf.st_mtime = fsp->pending_modtime;
3128 size = get_file_size(sbuf);
3129 tvs.modtime = sbuf.st_mtime;
3130 tvs.actime = sbuf.st_atime;
3131 dosmode = dos_mode(conn,fname,&sbuf);
3132 unixmode = sbuf.st_mode;
3134 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3135 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3137 switch (info_level) {
3138 case SMB_INFO_STANDARD:
3140 if (total_data < 12)
3141 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3143 /* access time */
3144 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3145 /* write time */
3146 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3147 break;
3150 case SMB_INFO_SET_EA:
3151 status = set_ea(conn, fsp, fname, pdata, total_data);
3152 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3153 return ERROR_NT(status);
3154 break;
3156 /* XXXX um, i don't think this is right.
3157 it's also not in the cifs6.txt spec.
3159 case SMB_INFO_QUERY_EAS_FROM_LIST:
3160 if (total_data < 28)
3161 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3163 tvs.actime = make_unix_date2(pdata+8);
3164 tvs.modtime = make_unix_date2(pdata+12);
3165 size = IVAL(pdata,16);
3166 dosmode = IVAL(pdata,24);
3167 break;
3169 /* XXXX nor this. not in cifs6.txt, either. */
3170 case SMB_INFO_QUERY_ALL_EAS:
3171 if (total_data < 28)
3172 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3174 tvs.actime = make_unix_date2(pdata+8);
3175 tvs.modtime = make_unix_date2(pdata+12);
3176 size = IVAL(pdata,16);
3177 dosmode = IVAL(pdata,24);
3178 break;
3180 case SMB_SET_FILE_BASIC_INFO:
3181 case SMB_FILE_BASIC_INFORMATION:
3183 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3184 time_t write_time;
3185 time_t changed_time;
3187 if (total_data < 36)
3188 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3190 /* Ignore create time at offset pdata. */
3192 /* access time */
3193 tvs.actime = interpret_long_date(pdata+8);
3195 write_time = interpret_long_date(pdata+16);
3196 changed_time = interpret_long_date(pdata+24);
3198 tvs.modtime = MIN(write_time, changed_time);
3200 if (write_time > tvs.modtime && write_time != 0xffffffff) {
3201 tvs.modtime = write_time;
3203 /* Prefer a defined time to an undefined one. */
3204 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3205 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
3206 ? changed_time : write_time);
3208 /* attributes */
3209 dosmode = IVAL(pdata,32);
3210 break;
3213 case SMB_FILE_ALLOCATION_INFORMATION:
3214 case SMB_SET_FILE_ALLOCATION_INFO:
3216 int ret = -1;
3217 SMB_BIG_UINT allocation_size;
3219 if (total_data < 8)
3220 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3222 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3223 #ifdef LARGE_SMB_OFF_T
3224 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3225 #else /* LARGE_SMB_OFF_T */
3226 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3227 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3228 #endif /* LARGE_SMB_OFF_T */
3229 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3230 fname, (double)allocation_size ));
3232 if (allocation_size)
3233 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
3235 if(allocation_size != get_file_size(sbuf)) {
3236 SMB_STRUCT_STAT new_sbuf;
3238 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3239 fname, (double)allocation_size ));
3241 if (fd == -1) {
3242 files_struct *new_fsp = NULL;
3243 int access_mode = 0;
3244 int action = 0;
3246 if(global_oplock_break) {
3247 /* Queue this file modify as we are the process of an oplock break. */
3249 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3250 DEBUGADD(2,( "in oplock break state.\n"));
3252 push_oplock_pending_smb_message(inbuf, length);
3253 return -1;
3256 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3257 SET_OPEN_MODE(DOS_OPEN_RDWR),
3258 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3259 FILE_ATTRIBUTE_NORMAL,
3260 0, &access_mode, &action);
3262 if (new_fsp == NULL)
3263 return(UNIXERROR(ERRDOS,ERRbadpath));
3264 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3265 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3266 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3267 new_fsp->fnum, strerror(errno)));
3268 ret = -1;
3270 close_file(new_fsp,True);
3271 } else {
3272 ret = vfs_allocate_file_space(fsp, allocation_size);
3273 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3274 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3275 fsp->fnum, strerror(errno)));
3276 ret = -1;
3279 if (ret == -1)
3280 return ERROR_NT(NT_STATUS_DISK_FULL);
3282 /* Allocate can truncate size... */
3283 size = get_file_size(new_sbuf);
3286 break;
3289 case SMB_FILE_END_OF_FILE_INFORMATION:
3290 case SMB_SET_FILE_END_OF_FILE_INFO:
3292 if (total_data < 8)
3293 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3295 size = IVAL(pdata,0);
3296 #ifdef LARGE_SMB_OFF_T
3297 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3298 #else /* LARGE_SMB_OFF_T */
3299 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3300 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3301 #endif /* LARGE_SMB_OFF_T */
3302 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3303 break;
3306 case SMB_FILE_DISPOSITION_INFORMATION:
3307 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3309 BOOL delete_on_close;
3311 if (total_data < 1)
3312 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3314 delete_on_close = (CVAL(pdata,0) ? True : False);
3316 /* Just ignore this set on a path. */
3317 if (tran_call != TRANSACT2_SETFILEINFO)
3318 break;
3320 if (fsp == NULL)
3321 return(UNIXERROR(ERRDOS,ERRbadfid));
3323 status = set_delete_on_close_internal(fsp, delete_on_close);
3325 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3326 return ERROR_NT(status);
3328 /* The set is across all open files on this dev/inode pair. */
3329 status =set_delete_on_close_over_all(fsp, delete_on_close);
3330 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3331 return ERROR_NT(status);
3333 break;
3336 case SMB_FILE_POSITION_INFORMATION:
3338 SMB_BIG_UINT position_information;
3340 if (total_data < 8)
3341 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3343 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3344 #ifdef LARGE_SMB_OFF_T
3345 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3346 #else /* LARGE_SMB_OFF_T */
3347 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3348 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3349 #endif /* LARGE_SMB_OFF_T */
3350 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3351 fname, (double)position_information ));
3352 if (fsp)
3353 fsp->position_information = position_information;
3354 break;
3358 * CIFS UNIX extensions.
3361 case SMB_SET_FILE_UNIX_BASIC:
3363 uint32 raw_unixmode;
3365 if (total_data < 100)
3366 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3368 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3369 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3370 size=IVAL(pdata,0); /* first 8 Bytes are size */
3371 #ifdef LARGE_SMB_OFF_T
3372 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3373 #else /* LARGE_SMB_OFF_T */
3374 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3375 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3376 #endif /* LARGE_SMB_OFF_T */
3378 pdata+=24; /* ctime & st_blocks are not changed */
3379 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
3380 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
3381 pdata+=16;
3382 set_owner = (uid_t)IVAL(pdata,0);
3383 pdata += 8;
3384 set_grp = (gid_t)IVAL(pdata,0);
3385 pdata += 8;
3386 raw_unixmode = IVAL(pdata,28);
3387 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3388 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3390 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3391 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3392 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3394 if (!VALID_STAT(sbuf)) {
3397 * The only valid use of this is to create character and block
3398 * devices, and named pipes. This is deprecated (IMHO) and
3399 * a new info level should be used for mknod. JRA.
3402 #if !defined(HAVE_MAKEDEV_FN)
3403 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3404 #else /* HAVE_MAKEDEV_FN */
3405 uint32 file_type = IVAL(pdata,0);
3406 uint32 dev_major = IVAL(pdata,4);
3407 uint32 dev_minor = IVAL(pdata,12);
3409 uid_t myuid = geteuid();
3410 gid_t mygid = getegid();
3411 SMB_DEV_T dev;
3413 if (tran_call == TRANSACT2_SETFILEINFO)
3414 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3416 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3417 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3419 dev = makedev(dev_major, dev_minor);
3421 /* We can only create as the owner/group we are. */
3423 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3424 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3425 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3426 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3428 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
3429 file_type != UNIX_TYPE_FIFO)
3430 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3432 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3433 0%o for file %s\n", (double)dev, unixmode, fname ));
3435 /* Ok - do the mknod. */
3436 if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
3437 return(UNIXERROR(ERRDOS,ERRnoaccess));
3439 inherit_access_acl(conn, fname, unixmode);
3441 SSVAL(params,0,0);
3442 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3443 return(-1);
3444 #endif /* HAVE_MAKEDEV_FN */
3449 * Deal with the UNIX specific mode set.
3452 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3453 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3454 (unsigned int)unixmode, fname ));
3455 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3456 return(UNIXERROR(ERRDOS,ERRnoaccess));
3460 * Deal with the UNIX specific uid set.
3463 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3464 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3465 (unsigned int)set_owner, fname ));
3466 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3467 return(UNIXERROR(ERRDOS,ERRnoaccess));
3471 * Deal with the UNIX specific gid set.
3474 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3475 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3476 (unsigned int)set_owner, fname ));
3477 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3478 return(UNIXERROR(ERRDOS,ERRnoaccess));
3480 break;
3483 case SMB_SET_FILE_UNIX_LINK:
3485 pstring oldname;
3486 char *newname = fname;
3488 /* Set a symbolic link. */
3489 /* Don't allow this if follow links is false. */
3491 if (!lp_symlinks(SNUM(conn)))
3492 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3494 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
3495 if (!NT_STATUS_IS_OK(status)) {
3496 return ERROR_NT(status);
3499 if (ensure_link_is_safe(conn, oldname, oldname) != 0)
3500 return(UNIXERROR(ERRDOS,ERRnoaccess));
3502 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3503 fname, oldname ));
3505 if (SMB_VFS_SYMLINK(conn,oldname,newname) != 0)
3506 return(UNIXERROR(ERRDOS,ERRnoaccess));
3507 SSVAL(params,0,0);
3508 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3509 return(-1);
3512 case SMB_SET_FILE_UNIX_HLINK:
3514 pstring oldname;
3515 char *newname = fname;
3517 /* Set a hard link. */
3518 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
3519 if (!NT_STATUS_IS_OK(status)) {
3520 return ERROR_NT(status);
3523 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3524 fname, oldname));
3526 status = hardlink_internals(conn, oldname, newname);
3527 if (!NT_STATUS_IS_OK(status)) {
3528 return ERROR_NT(status);
3531 SSVAL(params,0,0);
3532 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3533 return(-1);
3536 case SMB_FILE_RENAME_INFORMATION:
3538 BOOL overwrite;
3539 uint32 root_fid;
3540 uint32 len;
3541 pstring newname;
3542 pstring base_name;
3543 char *p;
3545 if (total_data < 12)
3546 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3548 overwrite = (CVAL(pdata,0) ? True : False);
3549 root_fid = IVAL(pdata,4);
3550 len = IVAL(pdata,8);
3551 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
3552 if (!NT_STATUS_IS_OK(status)) {
3553 return ERROR_NT(status);
3556 /* Check the new name has no '/' characters. */
3557 if (strchr_m(newname, '/'))
3558 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3560 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3562 /* Create the base directory. */
3563 pstrcpy(base_name, fname);
3564 p = strrchr_m(base_name, '/');
3565 if (p)
3566 *p = '\0';
3567 /* Append the new name. */
3568 pstrcat(base_name, "/");
3569 pstrcat(base_name, newname);
3571 if (fsp) {
3572 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3573 fsp->fnum, fsp->fsp_name, base_name ));
3574 status = rename_internals_fsp(conn, fsp, base_name, overwrite);
3575 } else {
3576 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3577 fname, newname ));
3578 status = rename_internals(conn, fname, base_name, 0, overwrite);
3580 if (!NT_STATUS_IS_OK(status)) {
3581 return ERROR_NT(status);
3583 process_pending_change_notify_queue((time_t)0);
3584 SSVAL(params,0,0);
3585 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3586 return(-1);
3588 default:
3589 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3592 /* get some defaults (no modifications) if any info is zero or -1. */
3593 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
3594 tvs.actime = sbuf.st_atime;
3596 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3597 tvs.modtime = sbuf.st_mtime;
3599 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3600 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3601 DEBUG(6,("size: %.0f ", (double)size));
3603 if (dosmode) {
3604 if (S_ISDIR(sbuf.st_mode))
3605 dosmode |= aDIR;
3606 else
3607 dosmode &= ~aDIR;
3610 DEBUG(6,("dosmode: %x\n" , dosmode));
3612 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3613 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3614 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3615 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3618 * Only do this test if we are not explicitly
3619 * changing the size of a file.
3621 if (!size)
3622 size = get_file_size(sbuf);
3626 * Try and set the times, size and mode of this file -
3627 * if they are different from the current values
3629 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3630 if(fsp != NULL) {
3632 * This was a setfileinfo on an open file.
3633 * NT does this a lot. It's actually pointless
3634 * setting the time here, as it will be overwritten
3635 * on the next write, so we save the request
3636 * away and will set it on file close. JRA.
3639 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3640 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3641 fsp->pending_modtime = tvs.modtime;
3644 } else {
3646 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3648 if(file_utime(conn, fname, &tvs)!=0)
3649 return(UNIXERROR(ERRDOS,ERRnoaccess));
3653 /* check the mode isn't different, before changing it */
3654 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3656 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3658 if(file_set_dosmode(conn, fname, dosmode, NULL)) {
3659 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
3660 return(UNIXERROR(ERRDOS,ERRnoaccess));
3664 if (size != get_file_size(sbuf)) {
3666 int ret;
3668 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3669 fname, (double)size ));
3671 if (fd == -1) {
3672 files_struct *new_fsp = NULL;
3673 int access_mode = 0;
3674 int action = 0;
3676 if(global_oplock_break) {
3677 /* Queue this file modify as we are the process of an oplock break. */
3679 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3680 DEBUGADD(2,( "in oplock break state.\n"));
3682 push_oplock_pending_smb_message(inbuf, length);
3683 return -1;
3686 new_fsp = open_file_shared(conn, fname, &sbuf,
3687 SET_OPEN_MODE(DOS_OPEN_RDWR),
3688 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3689 FILE_ATTRIBUTE_NORMAL,
3690 0, &access_mode, &action);
3692 if (new_fsp == NULL)
3693 return(UNIXERROR(ERRDOS,ERRbadpath));
3694 ret = vfs_set_filelen(new_fsp, size);
3695 close_file(new_fsp,True);
3696 } else {
3697 ret = vfs_set_filelen(fsp, size);
3700 if (ret == -1)
3701 return (UNIXERROR(ERRHRD,ERRdiskfull));
3704 SSVAL(params,0,0);
3705 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3707 return(-1);
3710 /****************************************************************************
3711 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3712 ****************************************************************************/
3714 static int call_trans2mkdir(connection_struct *conn,
3715 char *inbuf, char *outbuf, int length, int bufsize,
3716 char **pparams, int total_params, char **ppdata, int total_data)
3718 char *params = *pparams;
3719 pstring directory;
3720 int ret = -1;
3721 SMB_STRUCT_STAT sbuf;
3722 BOOL bad_path = False;
3723 NTSTATUS status = NT_STATUS_OK;
3725 if (!CAN_WRITE(conn))
3726 return ERROR_DOS(ERRSRV,ERRaccess);
3728 if (total_params < 4)
3729 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3731 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status);
3732 if (!NT_STATUS_IS_OK(status)) {
3733 return ERROR_NT(status);
3736 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3738 unix_convert(directory,conn,0,&bad_path,&sbuf);
3739 if (check_name(directory,conn))
3740 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3742 if(ret < 0) {
3743 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3744 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
3747 /* Realloc the parameter and data sizes */
3748 params = Realloc(*pparams,2);
3749 if(params == NULL)
3750 return ERROR_DOS(ERRDOS,ERRnomem);
3751 *pparams = params;
3753 SSVAL(params,0,0);
3755 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3757 return(-1);
3760 /****************************************************************************
3761 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3762 We don't actually do this - we just send a null response.
3763 ****************************************************************************/
3765 static int call_trans2findnotifyfirst(connection_struct *conn,
3766 char *inbuf, char *outbuf, int length, int bufsize,
3767 char **pparams, int total_params, char **ppdata, int total_data)
3769 static uint16 fnf_handle = 257;
3770 char *params = *pparams;
3771 uint16 info_level;
3773 if (total_params < 6)
3774 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3776 info_level = SVAL(params,4);
3777 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3779 switch (info_level) {
3780 case 1:
3781 case 2:
3782 break;
3783 default:
3784 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3787 /* Realloc the parameter and data sizes */
3788 params = Realloc(*pparams,6);
3789 if(params == NULL)
3790 return ERROR_DOS(ERRDOS,ERRnomem);
3791 *pparams = params;
3793 SSVAL(params,0,fnf_handle);
3794 SSVAL(params,2,0); /* No changes */
3795 SSVAL(params,4,0); /* No EA errors */
3797 fnf_handle++;
3799 if(fnf_handle == 0)
3800 fnf_handle = 257;
3802 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3804 return(-1);
3807 /****************************************************************************
3808 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3809 changes). Currently this does nothing.
3810 ****************************************************************************/
3812 static int call_trans2findnotifynext(connection_struct *conn,
3813 char *inbuf, char *outbuf, int length, int bufsize,
3814 char **pparams, int total_params, char **ppdata, int total_data)
3816 char *params = *pparams;
3818 DEBUG(3,("call_trans2findnotifynext\n"));
3820 /* Realloc the parameter and data sizes */
3821 params = Realloc(*pparams,4);
3822 if(params == NULL)
3823 return ERROR_DOS(ERRDOS,ERRnomem);
3824 *pparams = params;
3826 SSVAL(params,0,0); /* No changes */
3827 SSVAL(params,2,0); /* No EA errors */
3829 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3831 return(-1);
3834 /****************************************************************************
3835 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3836 ****************************************************************************/
3838 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3839 char* outbuf, int length, int bufsize,
3840 char **pparams, int total_params, char **ppdata, int total_data)
3842 char *params = *pparams;
3843 pstring pathname;
3844 int reply_size = 0;
3845 int max_referral_level;
3847 DEBUG(10,("call_trans2getdfsreferral\n"));
3849 if (total_params < 2)
3850 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3852 max_referral_level = SVAL(params,0);
3854 if(!lp_host_msdfs())
3855 return ERROR_DOS(ERRDOS,ERRbadfunc);
3857 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
3858 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
3859 return UNIXERROR(ERRDOS,ERRbadfile);
3861 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3862 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3864 return(-1);
3867 #define LMCAT_SPL 0x53
3868 #define LMFUNC_GETJOBID 0x60
3870 /****************************************************************************
3871 Reply to a TRANS2_IOCTL - used for OS/2 printing.
3872 ****************************************************************************/
3874 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3875 char* outbuf, int length, int bufsize,
3876 char **pparams, int total_params, char **ppdata, int total_data)
3878 char *pdata = *ppdata;
3879 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3881 /* check for an invalid fid before proceeding */
3883 if (!fsp)
3884 return(ERROR_DOS(ERRDOS,ERRbadfid));
3886 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3887 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3888 pdata = Realloc(*ppdata, 32);
3889 if(pdata == NULL)
3890 return ERROR_DOS(ERRDOS,ERRnomem);
3891 *ppdata = pdata;
3893 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3894 CAN ACCEPT THIS IN UNICODE. JRA. */
3896 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
3897 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3898 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3899 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3900 return(-1);
3901 } else {
3902 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3903 return ERROR_DOS(ERRSRV,ERRerror);
3907 /****************************************************************************
3908 Reply to a SMBfindclose (stop trans2 directory search).
3909 ****************************************************************************/
3911 int reply_findclose(connection_struct *conn,
3912 char *inbuf,char *outbuf,int length,int bufsize)
3914 int outsize = 0;
3915 int dptr_num=SVALS(inbuf,smb_vwv0);
3916 START_PROFILE(SMBfindclose);
3918 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3920 dptr_close(&dptr_num);
3922 outsize = set_message(outbuf,0,0,True);
3924 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3926 END_PROFILE(SMBfindclose);
3927 return(outsize);
3930 /****************************************************************************
3931 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3932 ****************************************************************************/
3934 int reply_findnclose(connection_struct *conn,
3935 char *inbuf,char *outbuf,int length,int bufsize)
3937 int outsize = 0;
3938 int dptr_num= -1;
3939 START_PROFILE(SMBfindnclose);
3941 dptr_num = SVAL(inbuf,smb_vwv0);
3943 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3945 /* We never give out valid handles for a
3946 findnotifyfirst - so any dptr_num is ok here.
3947 Just ignore it. */
3949 outsize = set_message(outbuf,0,0,True);
3951 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3953 END_PROFILE(SMBfindnclose);
3954 return(outsize);
3957 /****************************************************************************
3958 Reply to a SMBtranss2 - just ignore it!
3959 ****************************************************************************/
3961 int reply_transs2(connection_struct *conn,
3962 char *inbuf,char *outbuf,int length,int bufsize)
3964 START_PROFILE(SMBtranss2);
3965 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3966 END_PROFILE(SMBtranss2);
3967 return(-1);
3970 /****************************************************************************
3971 Reply to a SMBtrans2.
3972 ****************************************************************************/
3974 int reply_trans2(connection_struct *conn,
3975 char *inbuf,char *outbuf,int length,int bufsize)
3977 int outsize = 0;
3978 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3979 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3980 #if 0
3981 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3982 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3983 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3984 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3985 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3986 int32 timeout = IVALS(inbuf,smb_timeout);
3987 #endif
3988 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3989 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3990 char *params = NULL, *data = NULL;
3991 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
3992 START_PROFILE(SMBtrans2);
3994 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3995 /* Queue this open message as we are the process of an
3996 * oplock break. */
3998 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3999 DEBUGADD(2,( "in oplock break state.\n"));
4001 push_oplock_pending_smb_message(inbuf, length);
4002 END_PROFILE(SMBtrans2);
4003 return -1;
4006 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4007 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4008 END_PROFILE(SMBtrans2);
4009 return ERROR_DOS(ERRSRV,ERRaccess);
4012 outsize = set_message(outbuf,0,0,True);
4014 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4015 is so as a sanity check */
4016 if (suwcnt != 1) {
4018 * Need to have rc=0 for ioctl to get job id for OS/2.
4019 * Network printing will fail if function is not successful.
4020 * Similar function in reply.c will be used if protocol
4021 * is LANMAN1.0 instead of LM1.2X002.
4022 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4023 * outbuf doesn't have to be set(only job id is used).
4025 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4026 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4027 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4028 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4029 } else {
4030 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4031 DEBUG(2,("Transaction is %d\n",tran_call));
4032 END_PROFILE(SMBtrans2);
4033 ERROR_DOS(ERRDOS,ERRinvalidparam);
4037 /* Allocate the space for the maximum needed parameters and data */
4038 if (total_params > 0)
4039 params = (char *)malloc(total_params);
4040 if (total_data > 0)
4041 data = (char *)malloc(total_data);
4043 if ((total_params && !params) || (total_data && !data)) {
4044 DEBUG(2,("Out of memory in reply_trans2\n"));
4045 SAFE_FREE(params);
4046 SAFE_FREE(data);
4047 END_PROFILE(SMBtrans2);
4048 return ERROR_DOS(ERRDOS,ERRnomem);
4051 /* Copy the param and data bytes sent with this request into
4052 the params buffer */
4053 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4054 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4056 if (num_params > total_params || num_data > total_data)
4057 exit_server("invalid params in reply_trans2");
4059 if(params) {
4060 unsigned int psoff = SVAL(inbuf, smb_psoff);
4061 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4062 goto bad_param;
4063 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4064 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4065 goto bad_param;
4066 memcpy( params, smb_base(inbuf) + psoff, num_params);
4068 if(data) {
4069 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4070 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4071 goto bad_param;
4072 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4073 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4074 goto bad_param;
4075 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4078 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4080 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4081 /* We need to send an interim response then receive the rest
4082 of the parameter/data bytes */
4083 outsize = set_message(outbuf,0,0,True);
4084 srv_signing_trans_stop();
4085 if (!send_smb(smbd_server_fd(),outbuf))
4086 exit_server("reply_trans2: send_smb failed.");
4088 while (num_data_sofar < total_data ||
4089 num_params_sofar < total_params) {
4090 BOOL ret;
4091 unsigned int param_disp;
4092 unsigned int param_off;
4093 unsigned int data_disp;
4094 unsigned int data_off;
4096 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4099 * The sequence number for the trans reply is always
4100 * based on the last secondary received.
4103 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4105 if ((ret &&
4106 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4107 outsize = set_message(outbuf,0,0,True);
4108 if(ret)
4109 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4110 else
4111 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4112 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4113 goto bad_param;
4116 /* Revise total_params and total_data in case
4117 they have changed downwards */
4118 if (SVAL(inbuf, smb_tpscnt) < total_params)
4119 total_params = SVAL(inbuf, smb_tpscnt);
4120 if (SVAL(inbuf, smb_tdscnt) < total_data)
4121 total_data = SVAL(inbuf, smb_tdscnt);
4123 num_params = SVAL(inbuf,smb_spscnt);
4124 param_off = SVAL(inbuf, smb_spsoff);
4125 param_disp = SVAL(inbuf, smb_spsdisp);
4126 num_params_sofar += num_params;
4128 num_data = SVAL(inbuf, smb_sdscnt);
4129 data_off = SVAL(inbuf, smb_sdsoff);
4130 data_disp = SVAL(inbuf, smb_sdsdisp);
4131 num_data_sofar += num_data;
4133 if (num_params_sofar > total_params || num_data_sofar > total_data)
4134 goto bad_param;
4136 if (num_params) {
4137 if (param_disp + num_params >= total_params)
4138 goto bad_param;
4139 if ((param_disp + num_params < param_disp) ||
4140 (param_disp + num_params < num_params))
4141 goto bad_param;
4142 if (param_disp > total_params)
4143 goto bad_param;
4144 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4145 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4146 goto bad_param;
4147 if (params + param_disp < params)
4148 goto bad_param;
4150 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4152 if (num_data) {
4153 if (data_disp + num_data >= total_data)
4154 goto bad_param;
4155 if ((data_disp + num_data < data_disp) ||
4156 (data_disp + num_data < num_data))
4157 goto bad_param;
4158 if (data_disp > total_data)
4159 goto bad_param;
4160 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4161 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4162 goto bad_param;
4163 if (data + data_disp < data)
4164 goto bad_param;
4166 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4171 if (Protocol >= PROTOCOL_NT1) {
4172 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4175 /* Now we must call the relevant TRANS2 function */
4176 switch(tran_call) {
4177 case TRANSACT2_OPEN:
4178 START_PROFILE_NESTED(Trans2_open);
4179 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4180 &params, total_params, &data, total_data);
4181 END_PROFILE_NESTED(Trans2_open);
4182 break;
4184 case TRANSACT2_FINDFIRST:
4185 START_PROFILE_NESTED(Trans2_findfirst);
4186 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4187 &params, total_params, &data, total_data);
4188 END_PROFILE_NESTED(Trans2_findfirst);
4189 break;
4191 case TRANSACT2_FINDNEXT:
4192 START_PROFILE_NESTED(Trans2_findnext);
4193 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4194 &params, total_params, &data, total_data);
4195 END_PROFILE_NESTED(Trans2_findnext);
4196 break;
4198 case TRANSACT2_QFSINFO:
4199 START_PROFILE_NESTED(Trans2_qfsinfo);
4200 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4201 &params, total_params, &data, total_data);
4202 END_PROFILE_NESTED(Trans2_qfsinfo);
4203 break;
4205 #ifdef HAVE_SYS_QUOTAS
4206 case TRANSACT2_SETFSINFO:
4207 START_PROFILE_NESTED(Trans2_setfsinfo);
4208 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4209 &params, total_params, &data, total_data);
4210 END_PROFILE_NESTED(Trans2_setfsinfo);
4211 break;
4212 #endif
4213 case TRANSACT2_QPATHINFO:
4214 case TRANSACT2_QFILEINFO:
4215 START_PROFILE_NESTED(Trans2_qpathinfo);
4216 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4217 &params, total_params, &data, total_data);
4218 END_PROFILE_NESTED(Trans2_qpathinfo);
4219 break;
4220 case TRANSACT2_SETPATHINFO:
4221 case TRANSACT2_SETFILEINFO:
4222 START_PROFILE_NESTED(Trans2_setpathinfo);
4223 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4224 &params, total_params, &data, total_data);
4225 END_PROFILE_NESTED(Trans2_setpathinfo);
4226 break;
4228 case TRANSACT2_FINDNOTIFYFIRST:
4229 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4230 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4231 &params, total_params, &data, total_data);
4232 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4233 break;
4235 case TRANSACT2_FINDNOTIFYNEXT:
4236 START_PROFILE_NESTED(Trans2_findnotifynext);
4237 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4238 &params, total_params, &data, total_data);
4239 END_PROFILE_NESTED(Trans2_findnotifynext);
4240 break;
4241 case TRANSACT2_MKDIR:
4242 START_PROFILE_NESTED(Trans2_mkdir);
4243 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4244 &params, total_params, &data, total_data);
4245 END_PROFILE_NESTED(Trans2_mkdir);
4246 break;
4248 case TRANSACT2_GET_DFS_REFERRAL:
4249 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4250 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4251 &params, total_params, &data, total_data);
4252 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4253 break;
4254 case TRANSACT2_IOCTL:
4255 START_PROFILE_NESTED(Trans2_ioctl);
4256 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4257 &params, total_params, &data, total_data);
4258 END_PROFILE_NESTED(Trans2_ioctl);
4259 break;
4260 default:
4261 /* Error in request */
4262 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4263 SAFE_FREE(params);
4264 SAFE_FREE(data);
4265 END_PROFILE(SMBtrans2);
4266 srv_signing_trans_stop();
4267 return ERROR_DOS(ERRSRV,ERRerror);
4270 /* As we do not know how many data packets will need to be
4271 returned here the various call_trans2xxxx calls
4272 must send their own. Thus a call_trans2xxx routine only
4273 returns a value other than -1 when it wants to send
4274 an error packet.
4277 srv_signing_trans_stop();
4279 SAFE_FREE(params);
4280 SAFE_FREE(data);
4281 END_PROFILE(SMBtrans2);
4282 return outsize; /* If a correct response was needed the
4283 call_trans2xxx calls have already sent
4284 it. If outsize != -1 then it is returning */
4286 bad_param:
4288 srv_signing_trans_stop();
4289 SAFE_FREE(params);
4290 SAFE_FREE(data);
4291 END_PROFILE(SMBtrans2);
4292 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);