r570: Remove lots of globals to handle case issues - move them
[Samba/bb.git] / source3 / smbd / trans2.c
blob25954d44336689bee4c9d1f4d06b5e38aa041945
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 int smb_read_error;
28 extern fstring local_machine;
29 extern int global_oplock_break;
30 extern uint32 global_client_caps;
31 extern struct current_user current_user;
33 #define get_file_size(sbuf) ((sbuf).st_size)
35 /* given a stat buffer return the allocated size on disk, taking into
36 account sparse files */
37 SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
39 SMB_BIG_UINT ret;
40 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
41 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
42 #else
43 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
44 #endif
45 if (!ret && fsp && fsp->initial_allocation_size)
46 ret = fsp->initial_allocation_size;
47 ret = SMB_ROUNDUP(ret,SMB_ROUNDUP_ALLOCATION_SIZE);
48 return ret;
51 /****************************************************************************
52 Utility functions for dealing with extended attributes.
53 ****************************************************************************/
55 static const char *prohibited_ea_names[] = {
56 SAMBA_POSIX_INHERITANCE_EA_NAME,
57 SAMBA_XATTR_DOS_ATTRIB,
58 NULL
61 /****************************************************************************
62 Refuse to allow clients to overwrite our private xattrs.
63 ****************************************************************************/
65 static BOOL samba_private_attr_name(const char *unix_ea_name)
67 int i;
69 for (i = 0; prohibited_ea_names[i]; i++) {
70 if (strequal( prohibited_ea_names[i], unix_ea_name))
71 return True;
73 return False;
76 struct ea_list {
77 struct ea_list *next, *prev;
78 struct ea_struct ea;
81 /****************************************************************************
82 Get one EA value. Fill in a struct ea_struct.
83 ****************************************************************************/
85 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
86 const char *fname, char *ea_name, struct ea_struct *pea)
88 /* Get the value of this xattr. Max size is 64k. */
89 size_t attr_size = 256;
90 char *val = NULL;
91 ssize_t sizeret;
93 again:
95 val = talloc_realloc(mem_ctx, val, attr_size);
96 if (!val) {
97 return False;
100 if (fsp && fsp->fd != -1) {
101 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
102 } else {
103 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
106 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
107 attr_size = 65536;
108 goto again;
111 if (sizeret == -1) {
112 return False;
115 DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
116 dump_data(10, val, sizeret);
118 pea->flags = 0;
119 if (strnequal(ea_name, "user.", 5)) {
120 pea->name = &ea_name[5];
121 } else {
122 pea->name = ea_name;
124 pea->value.data = val;
125 pea->value.length = (size_t)sizeret;
126 return True;
129 /****************************************************************************
130 Return a linked list of the total EA's. Plus the total size
131 ****************************************************************************/
133 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)
135 /* Get a list of all xattrs. Max namesize is 64k. */
136 size_t ea_namelist_size = 1024;
137 char *ea_namelist;
138 char *p;
139 ssize_t sizeret;
140 int i;
141 struct ea_list *ea_list_head = NULL;
143 *pea_total_len = 0;
145 if (!lp_ea_support(SNUM(conn))) {
146 return NULL;
149 for (i = 0, ea_namelist = talloc(mem_ctx, ea_namelist_size); i < 6;
150 ea_namelist = talloc_realloc(mem_ctx, ea_namelist, ea_namelist_size), i++) {
151 if (fsp && fsp->fd != -1) {
152 sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
153 } else {
154 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
157 if (sizeret == -1 && errno == ERANGE) {
158 ea_namelist_size *= 2;
159 } else {
160 break;
164 if (sizeret == -1)
165 return NULL;
167 DEBUG(10,("get_ea_list: ea_namelist size = %d\n", sizeret ));
169 if (sizeret) {
170 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
171 struct ea_list *listp, *tmp;
173 if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
174 continue;
176 listp = talloc(mem_ctx, sizeof(struct ea_list));
177 if (!listp)
178 return NULL;
180 if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
181 return NULL;
185 fstring dos_ea_name;
186 push_ascii_fstring(dos_ea_name, listp->ea.name);
187 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
188 DEBUG(10,("get_ea_list: total_len = %u, %s, val len = %u\n",
189 *pea_total_len, dos_ea_name,
190 (unsigned int)listp->ea.value.length ));
192 DLIST_ADD_END(ea_list_head, listp, tmp);
194 /* Add on 4 for total length. */
195 if (*pea_total_len) {
196 *pea_total_len += 4;
200 DEBUG(10,("get_ea_list: total_len = %u\n", *pea_total_len));
201 return ea_list_head;
204 /****************************************************************************
205 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
206 that was filled.
207 ****************************************************************************/
209 static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size,
210 connection_struct *conn, files_struct *fsp, const char *fname)
212 unsigned int ret_data_size = 4;
213 char *p = pdata;
214 size_t total_ea_len;
215 TALLOC_CTX *mem_ctx;
216 struct ea_list *ea_list;
218 SMB_ASSERT(total_data_size >= 4);
220 SIVAL(pdata,0,0);
221 if (!lp_ea_support(SNUM(conn))) {
222 return 4;
224 mem_ctx = talloc_init("fill_ea_buffer");
225 if (!mem_ctx) {
226 return 4;
229 ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
230 if (!ea_list) {
231 talloc_destroy(mem_ctx);
232 return 4;
235 if (total_ea_len > total_data_size) {
236 talloc_destroy(mem_ctx);
237 return 4;
240 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
241 size_t dos_namelen;
242 fstring dos_ea_name;
243 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
244 dos_namelen = strlen(dos_ea_name);
245 if (dos_namelen > 255 || dos_namelen == 0) {
246 break;
248 if (ea_list->ea.value.length > 65535) {
249 break;
251 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
252 break;
255 /* We know we have room. */
256 SCVAL(p,0,ea_list->ea.flags);
257 SCVAL(p,1,dos_namelen);
258 SSVAL(p,2,ea_list->ea.value.length);
259 fstrcpy(p+4, dos_ea_name);
260 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
262 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
263 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
266 ret_data_size = PTR_DIFF(p, pdata);
267 DEBUG(10,("fill_ea_buffer: data_size = %u, total_ea_len = %u\n",
268 ret_data_size, total_ea_len ));
269 talloc_destroy(mem_ctx);
270 SIVAL(pdata,0,ret_data_size);
271 return ret_data_size;
274 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
276 size_t total_ea_len = 0;
277 TALLOC_CTX *mem_ctx = NULL;
279 if (!lp_ea_support(SNUM(conn))) {
280 return 0;
282 mem_ctx = talloc_init("estimate_ea_size");
283 (void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
284 talloc_destroy(mem_ctx);
285 return total_ea_len;
288 /****************************************************************************
289 Ensure the EA name is case insensitive by matching any existing EA name.
290 ****************************************************************************/
292 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
294 size_t total_ea_len;
295 TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
296 struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
298 for (; ea_list; ea_list = ea_list->next) {
299 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
300 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
301 &unix_ea_name[5], ea_list->ea.name));
302 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
303 break;
306 talloc_destroy(mem_ctx);
309 /****************************************************************************
310 Set or delete an extended attribute.
311 ****************************************************************************/
313 static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname,
314 char *pdata, int total_data)
316 unsigned int namelen;
317 unsigned int ealen;
318 int ret;
319 fstring unix_ea_name;
321 if (!lp_ea_support(SNUM(conn))) {
322 return NT_STATUS_EAS_NOT_SUPPORTED;
325 if (total_data < 8) {
326 return NT_STATUS_INVALID_PARAMETER;
329 if (IVAL(pdata,0) > total_data) {
330 DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data));
331 return NT_STATUS_INVALID_PARAMETER;
334 pdata += 4;
335 namelen = CVAL(pdata,1);
336 ealen = SVAL(pdata,2);
337 pdata += 4;
338 if (total_data < 8 + namelen + 1 + ealen) {
339 DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n",
340 (unsigned int)total_data, namelen, ealen));
341 return NT_STATUS_INVALID_PARAMETER;
344 if (pdata[namelen] != '\0') {
345 DEBUG(10,("set_ea: ea name not null terminated\n"));
346 return NT_STATUS_INVALID_PARAMETER;
349 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
350 pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE);
351 pdata += (namelen + 1);
353 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
355 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen));
356 if (ealen) {
357 DEBUG(10,("set_ea: data :\n"));
358 dump_data(10, pdata, ealen);
361 if (samba_private_attr_name(unix_ea_name)) {
362 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
363 return NT_STATUS_ACCESS_DENIED;
366 if (ealen == 0) {
367 /* Remove the attribute. */
368 if (fsp && (fsp->fd != -1)) {
369 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
370 unix_ea_name, fsp->fsp_name));
371 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
372 } else {
373 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
374 unix_ea_name, fname));
375 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
377 #ifdef ENOATTR
378 /* Removing a non existent attribute always succeeds. */
379 if (ret == -1 && errno == ENOATTR) {
380 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name));
381 ret = 0;
383 #endif
384 } else {
385 if (fsp && (fsp->fd != -1)) {
386 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
387 unix_ea_name, fsp->fsp_name));
388 ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0);
389 } else {
390 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
391 unix_ea_name, fname));
392 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0);
396 if (ret == -1) {
397 #ifdef ENOTSUP
398 if (errno == ENOTSUP) {
399 return NT_STATUS_EAS_NOT_SUPPORTED;
401 #endif
402 return map_nt_error_from_unix(errno);
405 return NT_STATUS_OK;
408 /****************************************************************************
409 Send the required number of replies back.
410 We assume all fields other than the data fields are
411 set correctly for the type of call.
412 HACK ! Always assumes smb_setup field is zero.
413 ****************************************************************************/
415 static int send_trans2_replies(char *outbuf,
416 int bufsize,
417 char *params,
418 int paramsize,
419 char *pdata,
420 int datasize)
422 /* As we are using a protocol > LANMAN1 then the max_send
423 variable must have been set in the sessetupX call.
424 This takes precedence over the max_xmit field in the
425 global struct. These different max_xmit variables should
426 be merged as this is now too confusing */
428 extern int max_send;
429 int data_to_send = datasize;
430 int params_to_send = paramsize;
431 int useable_space;
432 char *pp = params;
433 char *pd = pdata;
434 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
435 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
436 int data_alignment_offset = 0;
438 /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
440 set_message(outbuf,10,0,True);
442 /* If there genuinely are no parameters or data to send just send the empty packet */
444 if(params_to_send == 0 && data_to_send == 0) {
445 if (!send_smb(smbd_server_fd(),outbuf))
446 exit_server("send_trans2_replies: send_smb failed.");
447 return 0;
450 /* When sending params and data ensure that both are nicely aligned */
451 /* Only do this alignment when there is also data to send - else
452 can cause NT redirector problems. */
454 if (((params_to_send % 4) != 0) && (data_to_send != 0))
455 data_alignment_offset = 4 - (params_to_send % 4);
457 /* Space is bufsize minus Netbios over TCP header minus SMB header */
458 /* The alignment_offset is to align the param bytes on an even byte
459 boundary. NT 4.0 Beta needs this to work correctly. */
461 useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
463 /* useable_space can never be more than max_send minus the alignment offset. */
465 useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
467 while (params_to_send || data_to_send) {
468 /* Calculate whether we will totally or partially fill this packet */
470 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
472 /* We can never send more than useable_space */
474 * Note that 'useable_space' does not include the alignment offsets,
475 * but we must include the alignment offsets in the calculation of
476 * the length of the data we send over the wire, as the alignment offsets
477 * are sent here. Fix from Marc_Jacobsen@hp.com.
480 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
482 set_message(outbuf, 10, total_sent_thistime, True);
484 /* Set total params and data to be sent */
485 SSVAL(outbuf,smb_tprcnt,paramsize);
486 SSVAL(outbuf,smb_tdrcnt,datasize);
488 /* Calculate how many parameters and data we can fit into
489 * this packet. Parameters get precedence
492 params_sent_thistime = MIN(params_to_send,useable_space);
493 data_sent_thistime = useable_space - params_sent_thistime;
494 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
496 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
498 /* smb_proff is the offset from the start of the SMB header to the
499 parameter bytes, however the first 4 bytes of outbuf are
500 the Netbios over TCP header. Thus use smb_base() to subtract
501 them from the calculation */
503 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
505 if(params_sent_thistime == 0)
506 SSVAL(outbuf,smb_prdisp,0);
507 else
508 /* Absolute displacement of param bytes sent in this packet */
509 SSVAL(outbuf,smb_prdisp,pp - params);
511 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
512 if(data_sent_thistime == 0) {
513 SSVAL(outbuf,smb_droff,0);
514 SSVAL(outbuf,smb_drdisp, 0);
515 } else {
516 /* The offset of the data bytes is the offset of the
517 parameter bytes plus the number of parameters being sent this time */
518 SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
519 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
520 SSVAL(outbuf,smb_drdisp, pd - pdata);
523 /* Copy the param bytes into the packet */
525 if(params_sent_thistime)
526 memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
528 /* Copy in the data bytes */
529 if(data_sent_thistime)
530 memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
531 data_alignment_offset,pd,data_sent_thistime);
533 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
534 params_sent_thistime, data_sent_thistime, useable_space));
535 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
536 params_to_send, data_to_send, paramsize, datasize));
538 /* Send the packet */
539 if (!send_smb(smbd_server_fd(),outbuf))
540 exit_server("send_trans2_replies: send_smb failed.");
542 pp += params_sent_thistime;
543 pd += data_sent_thistime;
545 params_to_send -= params_sent_thistime;
546 data_to_send -= data_sent_thistime;
548 /* Sanity check */
549 if(params_to_send < 0 || data_to_send < 0) {
550 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
551 params_to_send, data_to_send));
552 return -1;
556 return 0;
559 /****************************************************************************
560 Reply to a TRANSACT2_OPEN.
561 ****************************************************************************/
563 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
564 char **pparams, int total_params, char **ppdata, int total_data)
566 char *params = *pparams;
567 int16 open_mode;
568 int16 open_attr;
569 BOOL oplock_request;
570 #if 0
571 BOOL return_additional_info;
572 int16 open_sattr;
573 time_t open_time;
574 #endif
575 int16 open_ofun;
576 int32 open_size;
577 char *pname;
578 pstring fname;
579 SMB_OFF_T size=0;
580 int fmode=0,mtime=0,rmode;
581 SMB_INO_T inode = 0;
582 SMB_STRUCT_STAT sbuf;
583 int smb_action = 0;
584 BOOL bad_path = False;
585 files_struct *fsp;
586 NTSTATUS status;
589 * Ensure we have enough parameters to perform the operation.
592 if (total_params < 29)
593 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
595 open_mode = SVAL(params, 2);
596 open_attr = SVAL(params,6);
597 oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
598 #if 0
599 return_additional_info = BITSETW(params,0);
600 open_sattr = SVAL(params, 4);
601 open_time = make_unix_date3(params+8);
602 #endif
603 open_ofun = SVAL(params,12);
604 open_size = IVAL(params,14);
605 pname = &params[28];
607 if (IS_IPC(conn))
608 return(ERROR_DOS(ERRSRV,ERRaccess));
610 srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);
611 if (!NT_STATUS_IS_OK(status)) {
612 return ERROR_NT(status);
615 DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
616 fname,open_mode, open_attr, open_ofun, open_size));
618 /* XXXX we need to handle passed times, sattr and flags */
620 unix_convert(fname,conn,0,&bad_path,&sbuf);
622 if (!check_name(fname,conn)) {
623 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
626 fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
627 oplock_request, &rmode,&smb_action);
629 if (!fsp) {
630 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
633 size = get_file_size(sbuf);
634 fmode = dos_mode(conn,fname,&sbuf);
635 mtime = sbuf.st_mtime;
636 inode = sbuf.st_ino;
637 if (fmode & aDIR) {
638 close_file(fsp,False);
639 return(ERROR_DOS(ERRDOS,ERRnoaccess));
642 /* Realloc the size of parameters and data we will return */
643 params = Realloc(*pparams, 28);
644 if( params == NULL )
645 return(ERROR_DOS(ERRDOS,ERRnomem));
646 *pparams = params;
648 memset((char *)params,'\0',28);
649 SSVAL(params,0,fsp->fnum);
650 SSVAL(params,2,fmode);
651 put_dos_date2(params,4, mtime);
652 SIVAL(params,8, (uint32)size);
653 SSVAL(params,12,rmode);
655 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
656 smb_action |= EXTENDED_OPLOCK_GRANTED;
658 SSVAL(params,18,smb_action);
661 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
663 SIVAL(params,20,inode);
665 /* Send the required number of replies */
666 send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
668 return -1;
671 /*********************************************************
672 Routine to check if a given string matches exactly.
673 as a special case a mask of "." does NOT match. That
674 is required for correct wildcard semantics
675 Case can be significant or not.
676 **********************************************************/
678 static BOOL exact_match(char *str,char *mask, BOOL case_sig)
680 if (mask[0] == '.' && mask[1] == 0)
681 return False;
682 if (case_sig)
683 return strcmp(str,mask)==0;
684 if (StrCaseCmp(str,mask) != 0) {
685 return False;
687 if (ms_has_wild(str)) {
688 return False;
690 return True;
693 /****************************************************************************
694 Return the filetype for UNIX extensions.
695 ****************************************************************************/
697 static uint32 unix_filetype(mode_t mode)
699 if(S_ISREG(mode))
700 return UNIX_TYPE_FILE;
701 else if(S_ISDIR(mode))
702 return UNIX_TYPE_DIR;
703 #ifdef S_ISLNK
704 else if(S_ISLNK(mode))
705 return UNIX_TYPE_SYMLINK;
706 #endif
707 #ifdef S_ISCHR
708 else if(S_ISCHR(mode))
709 return UNIX_TYPE_CHARDEV;
710 #endif
711 #ifdef S_ISBLK
712 else if(S_ISBLK(mode))
713 return UNIX_TYPE_BLKDEV;
714 #endif
715 #ifdef S_ISFIFO
716 else if(S_ISFIFO(mode))
717 return UNIX_TYPE_FIFO;
718 #endif
719 #ifdef S_ISSOCK
720 else if(S_ISSOCK(mode))
721 return UNIX_TYPE_SOCKET;
722 #endif
724 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
725 return UNIX_TYPE_UNKNOWN;
728 /****************************************************************************
729 Return the major devicenumber for UNIX extensions.
730 ****************************************************************************/
732 static uint32 unix_dev_major(SMB_DEV_T dev)
734 #if defined(HAVE_DEVICE_MAJOR_FN)
735 return (uint32)major(dev);
736 #else
737 return (uint32)(dev >> 8);
738 #endif
741 /****************************************************************************
742 Return the minor devicenumber for UNIX extensions.
743 ****************************************************************************/
745 static uint32 unix_dev_minor(SMB_DEV_T dev)
747 #if defined(HAVE_DEVICE_MINOR_FN)
748 return (uint32)minor(dev);
749 #else
750 return (uint32)(dev & 0xff);
751 #endif
754 /****************************************************************************
755 Map wire perms onto standard UNIX permissions. Obey share restrictions.
756 ****************************************************************************/
758 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
760 mode_t ret = 0;
762 if (perms == SMB_MODE_NO_CHANGE)
763 return pst->st_mode;
765 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
766 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
767 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
768 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
769 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
770 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
771 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
772 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
773 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
774 #ifdef S_ISVTX
775 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
776 #endif
777 #ifdef S_ISGID
778 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
779 #endif
780 #ifdef S_ISUID
781 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
782 #endif
784 if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
785 ret &= lp_dir_mask(SNUM(conn));
786 /* Add in force bits */
787 ret |= lp_force_dir_mode(SNUM(conn));
788 } else {
789 /* Apply mode mask */
790 ret &= lp_create_mask(SNUM(conn));
791 /* Add in force bits */
792 ret |= lp_force_create_mode(SNUM(conn));
795 return ret;
798 /****************************************************************************
799 Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
800 ****************************************************************************/
802 time_t interpret_long_unix_date(char *p)
804 DEBUG(10,("interpret_long_unix_date\n"));
805 if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
806 IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
807 return -1;
808 } else {
809 return interpret_long_date(p);
813 /****************************************************************************
814 Get a level dependent lanman2 dir entry.
815 ****************************************************************************/
817 static BOOL get_lanman2_dir_entry(connection_struct *conn,
818 void *inbuf, void *outbuf,
819 char *path_mask,int dirtype,int info_level,
820 int requires_resume_key,
821 BOOL dont_descend,char **ppdata,
822 char *base_data, int space_remaining,
823 BOOL *out_of_space, BOOL *got_exact_match,
824 int *last_name_off)
826 const char *dname;
827 BOOL found = False;
828 SMB_STRUCT_STAT sbuf;
829 pstring mask;
830 pstring pathreal;
831 pstring fname;
832 char *p, *q, *pdata = *ppdata;
833 uint32 reskey=0;
834 int prev_dirpos=0;
835 int mode=0;
836 SMB_OFF_T file_size = 0;
837 SMB_BIG_UINT allocation_size = 0;
838 uint32 len;
839 time_t mdate=0, adate=0, cdate=0;
840 char *nameptr;
841 BOOL was_8_3;
842 int nt_extmode; /* Used for NT connections instead of mode */
843 BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
845 *fname = 0;
846 *out_of_space = False;
847 *got_exact_match = False;
849 if (!conn->dirptr)
850 return(False);
852 p = strrchr_m(path_mask,'/');
853 if(p != NULL) {
854 if(p[1] == '\0')
855 pstrcpy(mask,"*.*");
856 else
857 pstrcpy(mask, p+1);
858 } else
859 pstrcpy(mask, path_mask);
861 while (!found) {
862 BOOL got_match;
864 /* Needed if we run out of space */
865 prev_dirpos = TellDir(conn->dirptr);
866 dname = ReadDirName(conn->dirptr);
869 * Due to bugs in NT client redirectors we are not using
870 * resume keys any more - set them to zero.
871 * Check out the related comments in findfirst/findnext.
872 * JRA.
875 reskey = 0;
877 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
878 (long)conn->dirptr,TellDir(conn->dirptr)));
880 if (!dname)
881 return(False);
883 pstrcpy(fname,dname);
885 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
886 got_match = mask_match(fname, mask, conn->case_sensitive);
888 if(!got_match && !mangle_is_8_3(fname, False)) {
891 * It turns out that NT matches wildcards against
892 * both long *and* short names. This may explain some
893 * of the wildcard wierdness from old DOS clients
894 * that some people have been seeing.... JRA.
897 pstring newname;
898 pstrcpy( newname, fname);
899 mangle_map( newname, True, False, SNUM(conn));
900 if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
901 got_match = mask_match(newname, mask, conn->case_sensitive);
904 if(got_match) {
905 BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
906 if (dont_descend && !isdots)
907 continue;
909 pstrcpy(pathreal,conn->dirpath);
910 if(needslash)
911 pstrcat(pathreal,"/");
912 pstrcat(pathreal,dname);
914 if (INFO_LEVEL_IS_UNIX(info_level)) {
915 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
916 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
917 pathreal,strerror(errno)));
918 continue;
920 } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
922 /* Needed to show the msdfs symlinks as
923 * directories */
925 if(lp_host_msdfs() &&
926 lp_msdfs_root(SNUM(conn)) &&
927 is_msdfs_link(conn, pathreal, NULL, NULL,
928 &sbuf)) {
930 DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
931 sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
933 } else {
935 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
936 pathreal,strerror(errno)));
937 continue;
941 mode = dos_mode(conn,pathreal,&sbuf);
943 if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
944 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
945 continue;
948 file_size = get_file_size(sbuf);
949 allocation_size = get_allocation_size(NULL,&sbuf);
950 mdate = sbuf.st_mtime;
951 adate = sbuf.st_atime;
952 cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
954 if (lp_dos_filetime_resolution(SNUM(conn))) {
955 cdate &= ~1;
956 mdate &= ~1;
957 adate &= ~1;
960 if(mode & aDIR)
961 file_size = 0;
963 DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
965 found = True;
969 mangle_map(fname,False,True,SNUM(conn));
971 p = pdata;
972 nameptr = p;
974 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
976 switch (info_level) {
977 case SMB_INFO_STANDARD:
978 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_STANDARD\n"));
979 if(requires_resume_key) {
980 SIVAL(p,0,reskey);
981 p += 4;
983 put_dos_date2(p,l1_fdateCreation,cdate);
984 put_dos_date2(p,l1_fdateLastAccess,adate);
985 put_dos_date2(p,l1_fdateLastWrite,mdate);
986 SIVAL(p,l1_cbFile,(uint32)file_size);
987 SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
988 SSVAL(p,l1_attrFile,mode);
989 p += l1_achName;
990 nameptr = p;
991 p += align_string(outbuf, p, 0);
992 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
993 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
994 if (len > 2) {
995 SCVAL(nameptr, -1, len - 2);
996 } else {
997 SCVAL(nameptr, -1, 0);
999 } else {
1000 if (len > 1) {
1001 SCVAL(nameptr, -1, len - 1);
1002 } else {
1003 SCVAL(nameptr, -1, 0);
1006 p += len;
1007 break;
1009 case SMB_INFO_QUERY_EA_SIZE:
1010 DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_QUERY_EA_SIZE\n"));
1011 if(requires_resume_key) {
1012 SIVAL(p,0,reskey);
1013 p += 4;
1015 put_dos_date2(p,l2_fdateCreation,cdate);
1016 put_dos_date2(p,l2_fdateLastAccess,adate);
1017 put_dos_date2(p,l2_fdateLastWrite,mdate);
1018 SIVAL(p,l2_cbFile,(uint32)file_size);
1019 SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1020 SSVAL(p,l2_attrFile,mode);
1022 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1023 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1025 p += l2_achName;
1026 nameptr = p - 1;
1027 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1028 if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1029 if (len > 2) {
1030 len -= 2;
1031 } else {
1032 len = 0;
1034 } else {
1035 if (len > 1) {
1036 len -= 1;
1037 } else {
1038 len = 0;
1041 SCVAL(nameptr,0,len);
1042 p += len;
1043 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1044 break;
1046 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1047 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1048 was_8_3 = mangle_is_8_3(fname, True);
1049 p += 4;
1050 SIVAL(p,0,reskey); p += 4;
1051 put_long_date(p,cdate); p += 8;
1052 put_long_date(p,adate); p += 8;
1053 put_long_date(p,mdate); p += 8;
1054 put_long_date(p,mdate); p += 8;
1055 SOFF_T(p,0,file_size); p += 8;
1056 SOFF_T(p,0,allocation_size); p += 8;
1057 SIVAL(p,0,nt_extmode); p += 4;
1058 q = p; p += 4; /* q is placeholder for name length. */
1060 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1061 SIVAL(p,0,ea_size); /* Extended attributes */
1062 p += 4;
1064 /* Clear the short name buffer. This is
1065 * IMPORTANT as not doing so will trigger
1066 * a Win2k client bug. JRA.
1068 memset(p,'\0',26);
1069 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1070 pstring mangled_name;
1071 pstrcpy(mangled_name, fname);
1072 mangle_map(mangled_name,True,True,SNUM(conn));
1073 mangled_name[12] = 0;
1074 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1075 SSVAL(p, 0, len);
1076 } else {
1077 SSVAL(p,0,0);
1078 *(p+2) = 0;
1080 p += 2 + 24;
1081 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1082 SIVAL(q,0,len);
1083 p += len;
1084 len = PTR_DIFF(p, pdata);
1085 len = (len + 3) & ~3;
1086 SIVAL(pdata,0,len);
1087 p = pdata + len;
1088 break;
1090 case SMB_FIND_FILE_DIRECTORY_INFO:
1091 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1092 p += 4;
1093 SIVAL(p,0,reskey); p += 4;
1094 put_long_date(p,cdate); p += 8;
1095 put_long_date(p,adate); p += 8;
1096 put_long_date(p,mdate); p += 8;
1097 put_long_date(p,mdate); p += 8;
1098 SOFF_T(p,0,file_size); p += 8;
1099 SOFF_T(p,0,allocation_size); p += 8;
1100 SIVAL(p,0,nt_extmode); p += 4;
1101 len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1102 SIVAL(p,0,len);
1103 p += 4 + len;
1104 len = PTR_DIFF(p, pdata);
1105 len = (len + 3) & ~3;
1106 SIVAL(pdata,0,len);
1107 p = pdata + len;
1108 break;
1110 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1111 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1112 p += 4;
1113 SIVAL(p,0,reskey); p += 4;
1114 put_long_date(p,cdate); p += 8;
1115 put_long_date(p,adate); p += 8;
1116 put_long_date(p,mdate); p += 8;
1117 put_long_date(p,mdate); p += 8;
1118 SOFF_T(p,0,file_size); p += 8;
1119 SOFF_T(p,0,allocation_size); p += 8;
1120 SIVAL(p,0,nt_extmode); p += 4;
1121 q = p; p += 4; /* q is placeholder for name length. */
1123 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1124 SIVAL(p,0,ea_size); /* Extended attributes */
1125 p +=4;
1127 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1128 SIVAL(q, 0, len);
1129 p += len;
1131 len = PTR_DIFF(p, pdata);
1132 len = (len + 3) & ~3;
1133 SIVAL(pdata,0,len);
1134 p = pdata + len;
1135 break;
1137 case SMB_FIND_FILE_NAMES_INFO:
1138 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1139 p += 4;
1140 SIVAL(p,0,reskey); p += 4;
1141 p += 4;
1142 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1143 acl on a dir (tridge) */
1144 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1145 SIVAL(p, -4, len);
1146 p += len;
1147 len = PTR_DIFF(p, pdata);
1148 len = (len + 3) & ~3;
1149 SIVAL(pdata,0,len);
1150 p = pdata + len;
1151 break;
1153 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1154 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1155 p += 4;
1156 SIVAL(p,0,reskey); p += 4;
1157 put_long_date(p,cdate); p += 8;
1158 put_long_date(p,adate); p += 8;
1159 put_long_date(p,mdate); p += 8;
1160 put_long_date(p,mdate); p += 8;
1161 SOFF_T(p,0,file_size); p += 8;
1162 SOFF_T(p,0,allocation_size); p += 8;
1163 SIVAL(p,0,nt_extmode); p += 4;
1164 q = p; p += 4; /* q is placeholder for name length. */
1166 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1167 SIVAL(p,0,ea_size); /* Extended attributes */
1168 p +=4;
1170 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1171 SIVAL(p,0,sbuf.st_dev); p += 4;
1172 SIVAL(p,0,sbuf.st_ino); p += 4;
1173 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1174 SIVAL(q, 0, len);
1175 p += len;
1176 len = PTR_DIFF(p, pdata);
1177 len = (len + 3) & ~3;
1178 SIVAL(pdata,0,len);
1179 p = pdata + len;
1180 break;
1182 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1183 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1184 was_8_3 = mangle_is_8_3(fname, True);
1185 p += 4;
1186 SIVAL(p,0,reskey); p += 4;
1187 put_long_date(p,cdate); p += 8;
1188 put_long_date(p,adate); p += 8;
1189 put_long_date(p,mdate); p += 8;
1190 put_long_date(p,mdate); p += 8;
1191 SOFF_T(p,0,file_size); p += 8;
1192 SOFF_T(p,0,allocation_size); p += 8;
1193 SIVAL(p,0,nt_extmode); p += 4;
1194 q = p; p += 4; /* q is placeholder for name length */
1196 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1197 SIVAL(p,0,ea_size); /* Extended attributes */
1198 p +=4;
1200 /* Clear the short name buffer. This is
1201 * IMPORTANT as not doing so will trigger
1202 * a Win2k client bug. JRA.
1204 memset(p,'\0',26);
1205 if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1206 pstring mangled_name;
1207 pstrcpy(mangled_name, fname);
1208 mangle_map(mangled_name,True,True,SNUM(conn));
1209 mangled_name[12] = 0;
1210 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1211 SSVAL(p, 0, len);
1212 } else {
1213 SSVAL(p,0,0);
1214 *(p+2) = 0;
1216 p += 26;
1217 SSVAL(p,0,0); p += 2; /* Reserved ? */
1218 SIVAL(p,0,sbuf.st_dev); p += 4;
1219 SIVAL(p,0,sbuf.st_ino); p += 4;
1220 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1221 SIVAL(q,0,len);
1222 p += len;
1223 len = PTR_DIFF(p, pdata);
1224 len = (len + 3) & ~3;
1225 SIVAL(pdata,0,len);
1226 p = pdata + len;
1227 break;
1229 /* CIFS UNIX Extension. */
1231 case SMB_FIND_FILE_UNIX:
1232 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1233 p+= 4;
1234 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1236 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1237 SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
1238 p+= 8;
1240 SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1241 p+= 8;
1243 put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
1244 put_long_date(p+8,sbuf.st_atime); /* Last access time 64 Bit */
1245 put_long_date(p+16,sbuf.st_mtime); /* Last modification time 64 Bit */
1246 p+= 24;
1248 SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
1249 SIVAL(p,4,0);
1250 p+= 8;
1252 SIVAL(p,0,sbuf.st_gid); /* group id of owner */
1253 SIVAL(p,4,0);
1254 p+= 8;
1256 SIVAL(p,0,unix_filetype(sbuf.st_mode));
1257 p+= 4;
1259 SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
1260 SIVAL(p,4,0);
1261 p+= 8;
1263 SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
1264 SIVAL(p,4,0);
1265 p+= 8;
1267 SINO_T(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
1268 p+= 8;
1270 SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
1271 SIVAL(p,4,0);
1272 p+= 8;
1274 SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
1275 SIVAL(p,4,0);
1276 p+= 8;
1278 len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1279 p += len;
1281 len = PTR_DIFF(p, pdata);
1282 len = (len + 3) & ~3;
1283 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1284 p = pdata + len;
1285 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1287 break;
1289 default:
1290 return(False);
1294 if (PTR_DIFF(p,pdata) > space_remaining) {
1295 /* Move the dirptr back to prev_dirpos */
1296 SeekDir(conn->dirptr, prev_dirpos);
1297 *out_of_space = True;
1298 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1299 return False; /* Not finished - just out of space */
1302 /* Setup the last_filename pointer, as an offset from base_data */
1303 *last_name_off = PTR_DIFF(nameptr,base_data);
1304 /* Advance the data pointer to the next slot */
1305 *ppdata = p;
1307 return(found);
1310 /****************************************************************************
1311 Reply to a TRANS2_FINDFIRST.
1312 ****************************************************************************/
1314 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1315 char **pparams, int total_params, char **ppdata, int total_data)
1317 /* We must be careful here that we don't return more than the
1318 allowed number of data bytes. If this means returning fewer than
1319 maxentries then so be it. We assume that the redirector has
1320 enough room for the fixed number of parameter bytes it has
1321 requested. */
1322 uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1323 char *params = *pparams;
1324 char *pdata = *ppdata;
1325 int dirtype = SVAL(params,0);
1326 int maxentries = SVAL(params,2);
1327 BOOL close_after_first = BITSETW(params+4,0);
1328 BOOL close_if_end = BITSETW(params+4,1);
1329 BOOL requires_resume_key = BITSETW(params+4,2);
1330 int info_level = SVAL(params,6);
1331 pstring directory;
1332 pstring mask;
1333 char *p, *wcard;
1334 int last_name_off=0;
1335 int dptr_num = -1;
1336 int numentries = 0;
1337 int i;
1338 BOOL finished = False;
1339 BOOL dont_descend = False;
1340 BOOL out_of_space = False;
1341 int space_remaining;
1342 BOOL bad_path = False;
1343 SMB_STRUCT_STAT sbuf;
1344 NTSTATUS ntstatus = NT_STATUS_OK;
1346 if (total_params < 12)
1347 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1349 *directory = *mask = 0;
1351 DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1352 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1353 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1354 info_level, max_data_bytes));
1356 switch (info_level) {
1357 case SMB_INFO_STANDARD:
1358 case SMB_INFO_QUERY_EA_SIZE:
1359 case SMB_FIND_FILE_DIRECTORY_INFO:
1360 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1361 case SMB_FIND_FILE_NAMES_INFO:
1362 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1363 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1364 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1365 break;
1366 case SMB_FIND_FILE_UNIX:
1367 if (!lp_unix_extensions())
1368 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1369 break;
1370 default:
1371 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1374 srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus);
1375 if (!NT_STATUS_IS_OK(ntstatus)) {
1376 return ERROR_NT(ntstatus);
1379 RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
1381 unix_convert(directory,conn,0,&bad_path,&sbuf);
1382 if(!check_name(directory,conn)) {
1383 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1386 p = strrchr_m(directory,'/');
1387 if(p == NULL) {
1388 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1389 if((directory[0] == '.') && (directory[1] == '\0'))
1390 pstrcpy(mask,"*");
1391 else
1392 pstrcpy(mask,directory);
1393 pstrcpy(directory,"./");
1394 } else {
1395 pstrcpy(mask,p+1);
1396 *p = 0;
1399 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1401 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1402 if( pdata == NULL )
1403 return(ERROR_DOS(ERRDOS,ERRnomem));
1405 *ppdata = pdata;
1406 memset((char *)pdata,'\0',max_data_bytes + 1024);
1408 /* Realloc the params space */
1409 params = Realloc(*pparams, 10);
1410 if (params == NULL)
1411 return ERROR_DOS(ERRDOS,ERRnomem);
1412 *pparams = params;
1414 dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1415 if (dptr_num < 0)
1416 return(UNIXERROR(ERRDOS,ERRbadfile));
1418 /* Save the wildcard match and attribs we are using on this directory -
1419 needed as lanman2 assumes these are being saved between calls */
1421 if(!(wcard = strdup(mask))) {
1422 dptr_close(&dptr_num);
1423 return ERROR_DOS(ERRDOS,ERRnomem);
1426 dptr_set_wcard(dptr_num, wcard);
1427 dptr_set_attr(dptr_num, dirtype);
1429 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
1431 /* We don't need to check for VOL here as this is returned by
1432 a different TRANS2 call. */
1434 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1435 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1436 dont_descend = True;
1438 p = pdata;
1439 space_remaining = max_data_bytes;
1440 out_of_space = False;
1442 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1443 BOOL got_exact_match = False;
1445 /* this is a heuristic to avoid seeking the dirptr except when
1446 absolutely necessary. It allows for a filename of about 40 chars */
1447 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1448 out_of_space = True;
1449 finished = False;
1450 } else {
1451 finished = !get_lanman2_dir_entry(conn,
1452 inbuf, outbuf,
1453 mask,dirtype,info_level,
1454 requires_resume_key,dont_descend,
1455 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1456 &last_name_off);
1459 if (finished && out_of_space)
1460 finished = False;
1462 if (!finished && !out_of_space)
1463 numentries++;
1466 * As an optimisation if we know we aren't looking
1467 * for a wildcard name (ie. the name matches the wildcard exactly)
1468 * then we can finish on any (first) match.
1469 * This speeds up large directory searches. JRA.
1472 if(got_exact_match)
1473 finished = True;
1475 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1478 /* Check if we can close the dirptr */
1479 if(close_after_first || (finished && close_if_end)) {
1480 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1481 dptr_close(&dptr_num);
1485 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1486 * from observation of NT.
1489 if(numentries == 0) {
1490 dptr_close(&dptr_num);
1491 return ERROR_DOS(ERRDOS,ERRbadfile);
1494 /* At this point pdata points to numentries directory entries. */
1496 /* Set up the return parameter block */
1497 SSVAL(params,0,dptr_num);
1498 SSVAL(params,2,numentries);
1499 SSVAL(params,4,finished);
1500 SSVAL(params,6,0); /* Never an EA error */
1501 SSVAL(params,8,last_name_off);
1503 send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1505 if ((! *directory) && dptr_path(dptr_num))
1506 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1508 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1509 smb_fn_name(CVAL(inbuf,smb_com)),
1510 mask, directory, dirtype, numentries ) );
1513 * Force a name mangle here to ensure that the
1514 * mask as an 8.3 name is top of the mangled cache.
1515 * The reasons for this are subtle. Don't remove
1516 * this code unless you know what you are doing
1517 * (see PR#13758). JRA.
1520 if(!mangle_is_8_3_wildcards( mask, False))
1521 mangle_map(mask, True, True, SNUM(conn));
1523 return(-1);
1526 /****************************************************************************
1527 Reply to a TRANS2_FINDNEXT.
1528 ****************************************************************************/
1530 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1531 char **pparams, int total_params, char **ppdata, int total_data)
1533 /* We must be careful here that we don't return more than the
1534 allowed number of data bytes. If this means returning fewer than
1535 maxentries then so be it. We assume that the redirector has
1536 enough room for the fixed number of parameter bytes it has
1537 requested. */
1538 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1539 char *params = *pparams;
1540 char *pdata = *ppdata;
1541 int dptr_num = SVAL(params,0);
1542 int maxentries = SVAL(params,2);
1543 uint16 info_level = SVAL(params,4);
1544 uint32 resume_key = IVAL(params,6);
1545 BOOL close_after_request = BITSETW(params+10,0);
1546 BOOL close_if_end = BITSETW(params+10,1);
1547 BOOL requires_resume_key = BITSETW(params+10,2);
1548 BOOL continue_bit = BITSETW(params+10,3);
1549 pstring resume_name;
1550 pstring mask;
1551 pstring directory;
1552 char *p;
1553 uint16 dirtype;
1554 int numentries = 0;
1555 int i, last_name_off=0;
1556 BOOL finished = False;
1557 BOOL dont_descend = False;
1558 BOOL out_of_space = False;
1559 int space_remaining;
1560 NTSTATUS ntstatus = NT_STATUS_OK;
1562 if (total_params < 12)
1563 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1565 *mask = *directory = *resume_name = 0;
1567 srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus);
1568 if (!NT_STATUS_IS_OK(ntstatus)) {
1569 return ERROR_NT(ntstatus);
1572 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1573 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1574 resume_key = %d resume name = %s continue=%d level = %d\n",
1575 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1576 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1578 switch (info_level) {
1579 case SMB_INFO_STANDARD:
1580 case SMB_INFO_QUERY_EA_SIZE:
1581 case SMB_FIND_FILE_DIRECTORY_INFO:
1582 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1583 case SMB_FIND_FILE_NAMES_INFO:
1584 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1585 break;
1586 case SMB_FIND_FILE_UNIX:
1587 if (!lp_unix_extensions())
1588 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1589 break;
1590 default:
1591 return ERROR_DOS(ERRDOS,ERRunknownlevel);
1594 pdata = Realloc( *ppdata, max_data_bytes + 1024);
1595 if(pdata == NULL)
1596 return ERROR_DOS(ERRDOS,ERRnomem);
1598 *ppdata = pdata;
1599 memset((char *)pdata,'\0',max_data_bytes + 1024);
1601 /* Realloc the params space */
1602 params = Realloc(*pparams, 6*SIZEOFWORD);
1603 if( params == NULL )
1604 return ERROR_DOS(ERRDOS,ERRnomem);
1606 *pparams = params;
1608 /* Check that the dptr is valid */
1609 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1610 return ERROR_DOS(ERRDOS,ERRnofiles);
1612 string_set(&conn->dirpath,dptr_path(dptr_num));
1614 /* Get the wildcard mask from the dptr */
1615 if((p = dptr_wcard(dptr_num))== NULL) {
1616 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1617 return ERROR_DOS(ERRDOS,ERRnofiles);
1620 pstrcpy(mask, p);
1621 pstrcpy(directory,conn->dirpath);
1623 /* Get the attr mask from the dptr */
1624 dirtype = dptr_attr(dptr_num);
1626 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
1627 dptr_num, mask, dirtype,
1628 (long)conn->dirptr,
1629 TellDir(conn->dirptr)));
1631 /* We don't need to check for VOL here as this is returned by
1632 a different TRANS2 call. */
1634 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1635 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1636 dont_descend = True;
1638 p = pdata;
1639 space_remaining = max_data_bytes;
1640 out_of_space = False;
1643 * Seek to the correct position. We no longer use the resume key but
1644 * depend on the last file name instead.
1647 if(requires_resume_key && *resume_name && !continue_bit) {
1650 * Fix for NT redirector problem triggered by resume key indexes
1651 * changing between directory scans. We now return a resume key of 0
1652 * and instead look for the filename to continue from (also given
1653 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1654 * findfirst/findnext (as is usual) then the directory pointer
1655 * should already be at the correct place. Check this by scanning
1656 * backwards looking for an exact (ie. case sensitive) filename match.
1657 * If we get to the beginning of the directory and haven't found it then scan
1658 * forwards again looking for a match. JRA.
1661 int current_pos, start_pos;
1662 const char *dname = NULL;
1663 pstring dname_pstring;
1664 void *dirptr = conn->dirptr;
1665 start_pos = TellDir(dirptr);
1666 for(current_pos = start_pos; current_pos >= 0; current_pos--) {
1667 DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
1669 SeekDir(dirptr, current_pos);
1670 dname = ReadDirName(dirptr);
1671 if (dname) {
1673 * Remember, mangle_map is called by
1674 * get_lanman2_dir_entry(), so the resume name
1675 * could be mangled. Ensure we do the same
1676 * here.
1679 /* make sure we get a copy that mangle_map can modify */
1681 pstrcpy(dname_pstring, dname);
1682 mangle_map( dname_pstring, False, True, SNUM(conn));
1684 if(strcsequal( resume_name, dname_pstring)) {
1685 SeekDir(dirptr, current_pos+1);
1686 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1687 break;
1693 * Scan forward from start if not found going backwards.
1696 if(current_pos < 0) {
1697 DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
1698 SeekDir(dirptr, start_pos);
1699 for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
1702 * Remember, mangle_map is called by
1703 * get_lanman2_dir_entry(), so the resume name
1704 * could be mangled. Ensure we do the same
1705 * here.
1708 if(dname) {
1709 /* make sure we get a copy that mangle_map can modify */
1711 pstrcpy(dname_pstring, dname);
1712 mangle_map(dname_pstring, False, True, SNUM(conn));
1714 if(strcsequal( resume_name, dname_pstring)) {
1715 SeekDir(dirptr, current_pos+1);
1716 DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
1717 break;
1720 } /* end for */
1721 } /* end if current_pos */
1722 } /* end if requires_resume_key && !continue_bit */
1724 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1725 BOOL got_exact_match = False;
1727 /* this is a heuristic to avoid seeking the dirptr except when
1728 absolutely necessary. It allows for a filename of about 40 chars */
1729 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1730 out_of_space = True;
1731 finished = False;
1732 } else {
1733 finished = !get_lanman2_dir_entry(conn,
1734 inbuf, outbuf,
1735 mask,dirtype,info_level,
1736 requires_resume_key,dont_descend,
1737 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1738 &last_name_off);
1741 if (finished && out_of_space)
1742 finished = False;
1744 if (!finished && !out_of_space)
1745 numentries++;
1748 * As an optimisation if we know we aren't looking
1749 * for a wildcard name (ie. the name matches the wildcard exactly)
1750 * then we can finish on any (first) match.
1751 * This speeds up large directory searches. JRA.
1754 if(got_exact_match)
1755 finished = True;
1757 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1760 /* Check if we can close the dirptr */
1761 if(close_after_request || (finished && close_if_end)) {
1762 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1763 dptr_close(&dptr_num); /* This frees up the saved mask */
1766 /* Set up the return parameter block */
1767 SSVAL(params,0,numentries);
1768 SSVAL(params,2,finished);
1769 SSVAL(params,4,0); /* Never an EA error */
1770 SSVAL(params,6,last_name_off);
1772 send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1774 if ((! *directory) && dptr_path(dptr_num))
1775 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1777 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1778 smb_fn_name(CVAL(inbuf,smb_com)),
1779 mask, directory, dirtype, numentries ) );
1781 return(-1);
1784 /****************************************************************************
1785 Reply to a TRANS2_QFSINFO (query filesystem info).
1786 ****************************************************************************/
1788 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
1789 int length, int bufsize,
1790 char **pparams, int total_params, char **ppdata, int total_data)
1792 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
1793 char *pdata = *ppdata;
1794 char *params = *pparams;
1795 uint16 info_level = SVAL(params,0);
1796 int data_len, len;
1797 SMB_STRUCT_STAT st;
1798 char *vname = volume_label(SNUM(conn));
1799 int snum = SNUM(conn);
1800 char *fstype = lp_fstype(SNUM(conn));
1801 int quota_flag = 0;
1803 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1805 if(SMB_VFS_STAT(conn,".",&st)!=0) {
1806 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1807 return ERROR_DOS(ERRSRV,ERRinvdevice);
1810 pdata = Realloc(*ppdata, max_data_bytes + 1024);
1811 if ( pdata == NULL )
1812 return ERROR_DOS(ERRDOS,ERRnomem);
1814 *ppdata = pdata;
1815 memset((char *)pdata,'\0',max_data_bytes + 1024);
1817 switch (info_level) {
1818 case SMB_INFO_ALLOCATION:
1820 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1821 data_len = 18;
1822 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1823 block_size = lp_block_size(snum);
1824 if (bsize < block_size) {
1825 SMB_BIG_UINT factor = block_size/bsize;
1826 bsize = block_size;
1827 dsize /= factor;
1828 dfree /= factor;
1830 if (bsize > block_size) {
1831 SMB_BIG_UINT factor = bsize/block_size;
1832 bsize = block_size;
1833 dsize *= factor;
1834 dfree *= factor;
1836 bytes_per_sector = 512;
1837 sectors_per_unit = bsize/bytes_per_sector;
1839 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1840 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1841 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1843 SIVAL(pdata,l1_idFileSystem,st.st_dev);
1844 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1845 SIVAL(pdata,l1_cUnit,dsize);
1846 SIVAL(pdata,l1_cUnitAvail,dfree);
1847 SSVAL(pdata,l1_cbSector,bytes_per_sector);
1848 break;
1851 case SMB_INFO_VOLUME:
1852 /* Return volume name */
1854 * Add volume serial number - hash of a combination of
1855 * the called hostname and the service name.
1857 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
1858 len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1859 SCVAL(pdata,l2_vol_cch,len);
1860 data_len = l2_vol_szVolLabel + len;
1861 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1862 (unsigned)st.st_ctime, len, vname));
1863 break;
1865 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1866 case SMB_FS_ATTRIBUTE_INFORMATION:
1869 #if defined(HAVE_SYS_QUOTAS)
1870 quota_flag = FILE_VOLUME_QUOTAS;
1871 #endif
1873 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1874 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1875 quota_flag); /* FS ATTRIBUTES */
1877 SIVAL(pdata,4,255); /* Max filename component length */
1878 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1879 and will think we can't do long filenames */
1880 len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1881 SIVAL(pdata,8,len);
1882 data_len = 12 + len;
1883 break;
1885 case SMB_QUERY_FS_LABEL_INFO:
1886 case SMB_FS_LABEL_INFORMATION:
1887 len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1888 data_len = 4 + len;
1889 SIVAL(pdata,0,len);
1890 break;
1892 case SMB_QUERY_FS_VOLUME_INFO:
1893 case SMB_FS_VOLUME_INFORMATION:
1896 * Add volume serial number - hash of a combination of
1897 * the called hostname and the service name.
1899 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1900 (str_checksum(local_machine)<<16));
1902 len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1903 SIVAL(pdata,12,len);
1904 data_len = 18+len;
1905 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1906 (int)strlen(vname),vname, lp_servicename(snum)));
1907 break;
1909 case SMB_QUERY_FS_SIZE_INFO:
1910 case SMB_FS_SIZE_INFORMATION:
1912 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1913 data_len = 24;
1914 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1915 block_size = lp_block_size(snum);
1916 if (bsize < block_size) {
1917 SMB_BIG_UINT factor = block_size/bsize;
1918 bsize = block_size;
1919 dsize /= factor;
1920 dfree /= factor;
1922 if (bsize > block_size) {
1923 SMB_BIG_UINT factor = bsize/block_size;
1924 bsize = block_size;
1925 dsize *= factor;
1926 dfree *= factor;
1928 bytes_per_sector = 512;
1929 sectors_per_unit = bsize/bytes_per_sector;
1930 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1931 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1932 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1933 SBIG_UINT(pdata,0,dsize);
1934 SBIG_UINT(pdata,8,dfree);
1935 SIVAL(pdata,16,sectors_per_unit);
1936 SIVAL(pdata,20,bytes_per_sector);
1937 break;
1940 case SMB_FS_FULL_SIZE_INFORMATION:
1942 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1943 data_len = 32;
1944 SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize);
1945 block_size = lp_block_size(snum);
1946 if (bsize < block_size) {
1947 SMB_BIG_UINT factor = block_size/bsize;
1948 bsize = block_size;
1949 dsize /= factor;
1950 dfree /= factor;
1952 if (bsize > block_size) {
1953 SMB_BIG_UINT factor = bsize/block_size;
1954 bsize = block_size;
1955 dsize *= factor;
1956 dfree *= factor;
1958 bytes_per_sector = 512;
1959 sectors_per_unit = bsize/bytes_per_sector;
1960 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1961 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1962 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1963 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1964 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1965 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1966 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1967 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1968 break;
1971 case SMB_QUERY_FS_DEVICE_INFO:
1972 case SMB_FS_DEVICE_INFORMATION:
1973 data_len = 8;
1974 SIVAL(pdata,0,0); /* dev type */
1975 SIVAL(pdata,4,0); /* characteristics */
1976 break;
1978 #ifdef HAVE_SYS_QUOTAS
1979 case SMB_FS_QUOTA_INFORMATION:
1981 * what we have to send --metze:
1983 * Unknown1: 24 NULL bytes
1984 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1985 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
1986 * Quota Flags: 2 byte :
1987 * Unknown3: 6 NULL bytes
1989 * 48 bytes total
1991 * details for Quota Flags:
1993 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1994 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
1995 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1996 * 0x0001 Enable Quotas: enable quota for this fs
2000 /* we need to fake up a fsp here,
2001 * because its not send in this call
2003 files_struct fsp;
2004 SMB_NTQUOTA_STRUCT quotas;
2006 ZERO_STRUCT(fsp);
2007 ZERO_STRUCT(quotas);
2009 fsp.conn = conn;
2010 fsp.fnum = -1;
2011 fsp.fd = -1;
2013 /* access check */
2014 if (current_user.uid != 0) {
2015 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2016 lp_servicename(SNUM(conn)),conn->user));
2017 return ERROR_DOS(ERRDOS,ERRnoaccess);
2020 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2021 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2022 return ERROR_DOS(ERRSRV,ERRerror);
2025 data_len = 48;
2027 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2029 /* Unknown1 24 NULL bytes*/
2030 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2031 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2032 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2034 /* Default Soft Quota 8 bytes */
2035 SBIG_UINT(pdata,24,quotas.softlim);
2037 /* Default Hard Quota 8 bytes */
2038 SBIG_UINT(pdata,32,quotas.hardlim);
2040 /* Quota flag 2 bytes */
2041 SSVAL(pdata,40,quotas.qflags);
2043 /* Unknown3 6 NULL bytes */
2044 SSVAL(pdata,42,0);
2045 SIVAL(pdata,44,0);
2047 break;
2049 #endif /* HAVE_SYS_QUOTAS */
2050 case SMB_FS_OBJECTID_INFORMATION:
2051 data_len = 64;
2052 break;
2055 * Query the version and capabilities of the CIFS UNIX extensions
2056 * in use.
2059 case SMB_QUERY_CIFS_UNIX_INFO:
2060 if (!lp_unix_extensions())
2061 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2062 data_len = 12;
2063 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2064 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2065 SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
2066 break;
2068 case SMB_MAC_QUERY_FS_INFO:
2070 * Thursby MAC extension... ONLY on NTFS filesystems
2071 * once we do streams then we don't need this
2073 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2074 data_len = 88;
2075 SIVAL(pdata,84,0x100); /* Don't support mac... */
2076 break;
2078 /* drop through */
2079 default:
2080 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2084 send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2086 DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2088 return -1;
2091 #ifdef HAVE_SYS_QUOTAS
2092 /****************************************************************************
2093 Reply to a TRANS2_SETFSINFO (set filesystem info).
2094 ****************************************************************************/
2096 static int call_trans2setfsinfo(connection_struct *conn,
2097 char *inbuf, char *outbuf, int length, int bufsize,
2098 char **pparams, int total_params, char **ppdata, int total_data)
2100 char *pdata = *ppdata;
2101 char *params = *pparams;
2102 files_struct *fsp = NULL;
2103 uint16 info_level;
2104 int outsize;
2105 SMB_NTQUOTA_STRUCT quotas;
2107 ZERO_STRUCT(quotas);
2109 DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2111 /* access check */
2112 if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2113 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2114 lp_servicename(SNUM(conn)),conn->user));
2115 return ERROR_DOS(ERRSRV,ERRaccess);
2118 /* */
2119 if (total_params < 4) {
2120 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2121 total_params));
2122 return ERROR_DOS(ERRDOS,ERRinvalidparam);
2125 fsp = file_fsp(params,0);
2127 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2128 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2129 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2132 info_level = SVAL(params,2);
2134 switch(info_level) {
2135 case SMB_FS_QUOTA_INFORMATION:
2136 /* note: normaly there're 48 bytes,
2137 * but we didn't use the last 6 bytes for now
2138 * --metze
2140 if (total_data < 42) {
2141 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2142 total_data));
2143 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2146 /* unknown_1 24 NULL bytes in pdata*/
2148 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2149 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2150 #ifdef LARGE_SMB_OFF_T
2151 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2152 #else /* LARGE_SMB_OFF_T */
2153 if ((IVAL(pdata,28) != 0)&&
2154 ((quotas.softlim != 0xFFFFFFFF)||
2155 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2156 /* more than 32 bits? */
2157 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2159 #endif /* LARGE_SMB_OFF_T */
2161 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2162 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2163 #ifdef LARGE_SMB_OFF_T
2164 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2165 #else /* LARGE_SMB_OFF_T */
2166 if ((IVAL(pdata,36) != 0)&&
2167 ((quotas.hardlim != 0xFFFFFFFF)||
2168 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2169 /* more than 32 bits? */
2170 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2172 #endif /* LARGE_SMB_OFF_T */
2174 /* quota_flags 2 bytes **/
2175 quotas.qflags = SVAL(pdata,40);
2177 /* unknown_2 6 NULL bytes follow*/
2179 /* now set the quotas */
2180 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2181 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2182 return ERROR_DOS(ERRSRV,ERRerror);
2185 break;
2186 default:
2187 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2188 info_level));
2189 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2190 break;
2194 * sending this reply works fine,
2195 * but I'm not sure it's the same
2196 * like windows do...
2197 * --metze
2199 outsize = set_message(outbuf,10,0,True);
2201 return outsize;
2203 #endif /* HAVE_SYS_QUOTAS */
2205 /****************************************************************************
2206 * Utility function to set bad path error.
2207 ****************************************************************************/
2209 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2211 DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2212 err, (int)bad_path ));
2214 if(err == ENOENT) {
2215 if (bad_path) {
2216 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2217 } else {
2218 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2221 return UNIXERROR(def_class,def_code);
2224 /****************************************************************************
2225 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2226 file name or file id).
2227 ****************************************************************************/
2229 static int call_trans2qfilepathinfo(connection_struct *conn,
2230 char *inbuf, char *outbuf, int length,
2231 int bufsize,
2232 char **pparams, int total_params, char **ppdata, int total_data)
2234 int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
2235 char *params = *pparams;
2236 char *pdata = *ppdata;
2237 uint16 tran_call = SVAL(inbuf, smb_setup0);
2238 uint16 info_level;
2239 int mode=0;
2240 SMB_OFF_T file_size=0;
2241 SMB_BIG_UINT allocation_size=0;
2242 unsigned int data_size;
2243 unsigned int param_size = 2;
2244 SMB_STRUCT_STAT sbuf;
2245 pstring fname, dos_fname;
2246 char *fullpathname;
2247 char *base_name;
2248 char *p;
2249 SMB_OFF_T pos = 0;
2250 BOOL bad_path = False;
2251 BOOL delete_pending = False;
2252 int len;
2253 time_t c_time;
2254 files_struct *fsp = NULL;
2255 uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2257 if (!params)
2258 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2260 if (tran_call == TRANSACT2_QFILEINFO) {
2261 if (total_params < 4)
2262 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2264 fsp = file_fsp(params,0);
2265 info_level = SVAL(params,2);
2267 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2269 if(fsp && (fsp->fake_file_handle)) {
2271 * This is actually for the QUOTA_FAKE_FILE --metze
2274 pstrcpy(fname, fsp->fsp_name);
2275 unix_convert(fname,conn,0,&bad_path,&sbuf);
2276 if (!check_name(fname,conn)) {
2277 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno)));
2278 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2281 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2283 * This is actually a QFILEINFO on a directory
2284 * handle (returned from an NT SMB). NT5.0 seems
2285 * to do this call. JRA.
2287 pstrcpy(fname, fsp->fsp_name);
2288 unix_convert(fname,conn,0,&bad_path,&sbuf);
2289 if (!check_name(fname,conn)) {
2290 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2291 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2294 if (INFO_LEVEL_IS_UNIX(info_level)) {
2295 /* Always do lstat for UNIX calls. */
2296 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2297 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2298 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2300 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
2301 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2302 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2305 delete_pending = fsp->directory_delete_on_close;
2306 } else {
2308 * Original code - this is an open file.
2310 CHECK_FSP(fsp,conn);
2312 pstrcpy(fname, fsp->fsp_name);
2313 if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2314 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2315 return(UNIXERROR(ERRDOS,ERRbadfid));
2317 pos = fsp->position_information;
2318 delete_pending = fsp->delete_on_close;
2319 desired_access = fsp->desired_access;
2321 } else {
2322 NTSTATUS status = NT_STATUS_OK;
2324 /* qpathinfo */
2325 if (total_params < 6)
2326 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2328 info_level = SVAL(params,0);
2330 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2332 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
2333 if (!NT_STATUS_IS_OK(status)) {
2334 return ERROR_NT(status);
2337 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2339 unix_convert(fname,conn,0,&bad_path,&sbuf);
2340 if (!check_name(fname,conn)) {
2341 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2342 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2345 if (INFO_LEVEL_IS_UNIX(info_level)) {
2346 /* Always do lstat for UNIX calls. */
2347 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2348 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2349 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2351 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2352 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2353 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2357 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2358 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2360 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2361 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2363 p = strrchr_m(fname,'/');
2364 if (!p)
2365 base_name = fname;
2366 else
2367 base_name = p+1;
2369 mode = dos_mode(conn,fname,&sbuf);
2370 if (!mode)
2371 mode = FILE_ATTRIBUTE_NORMAL;
2373 fullpathname = fname;
2374 file_size = get_file_size(sbuf);
2375 allocation_size = get_allocation_size(fsp,&sbuf);
2376 if (mode & aDIR)
2377 file_size = 0;
2379 params = Realloc(*pparams,2);
2380 if (params == NULL)
2381 return ERROR_DOS(ERRDOS,ERRnomem);
2382 *pparams = params;
2383 memset((char *)params,'\0',2);
2384 data_size = max_data_bytes + 1024;
2385 pdata = Realloc(*ppdata, data_size);
2386 if ( pdata == NULL )
2387 return ERROR_DOS(ERRDOS,ERRnomem);
2388 *ppdata = pdata;
2390 if (total_data > 0 && IVAL(pdata,0) == total_data) {
2391 /* uggh, EAs for OS2 */
2392 DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2393 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2396 memset((char *)pdata,'\0',data_size);
2398 c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2400 if (lp_dos_filetime_resolution(SNUM(conn))) {
2401 c_time &= ~1;
2402 sbuf.st_atime &= ~1;
2403 sbuf.st_mtime &= ~1;
2404 sbuf.st_mtime &= ~1;
2407 /* NT expects the name to be in an exact form of the *full*
2408 filename. See the trans2 torture test */
2409 if (strequal(base_name,".")) {
2410 pstrcpy(dos_fname, "\\");
2411 } else {
2412 pstr_sprintf(dos_fname, "\\%s", fname);
2413 string_replace(dos_fname, '/', '\\');
2416 switch (info_level) {
2417 case SMB_INFO_STANDARD:
2418 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2419 data_size = 22;
2420 put_dos_date2(pdata,l1_fdateCreation,c_time);
2421 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2422 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2423 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2424 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2425 SSVAL(pdata,l1_attrFile,mode);
2426 break;
2428 case SMB_INFO_QUERY_EA_SIZE:
2430 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2431 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2432 data_size = 26;
2433 put_dos_date2(pdata,l1_fdateCreation,c_time);
2434 put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2435 put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2436 SIVAL(pdata,l1_cbFile,(uint32)file_size);
2437 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2438 SSVAL(pdata,l1_attrFile,mode);
2439 SIVAL(pdata,l1_attrFile+2,ea_size);
2440 break;
2443 case SMB_INFO_IS_NAME_VALID:
2444 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2445 if (tran_call == TRANSACT2_QFILEINFO) {
2446 /* os/2 needs this ? really ?*/
2447 return ERROR_DOS(ERRDOS,ERRbadfunc);
2449 data_size = 0;
2450 param_size = 0;
2451 break;
2453 case SMB_INFO_QUERY_EAS_FROM_LIST:
2454 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2455 data_size = 24;
2456 put_dos_date2(pdata,0,c_time);
2457 put_dos_date2(pdata,4,sbuf.st_atime);
2458 put_dos_date2(pdata,8,sbuf.st_mtime);
2459 SIVAL(pdata,12,(uint32)file_size);
2460 SIVAL(pdata,16,(uint32)allocation_size);
2461 SIVAL(pdata,20,mode);
2462 break;
2464 case SMB_INFO_QUERY_ALL_EAS:
2465 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2466 /* We have data_size bytes to put EA's into. */
2467 data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname);
2468 break;
2470 case SMB_FILE_BASIC_INFORMATION:
2471 case SMB_QUERY_FILE_BASIC_INFO:
2473 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2474 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2475 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2476 } else {
2477 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2478 data_size = 40;
2479 SIVAL(pdata,36,0);
2481 put_long_date(pdata,c_time);
2482 put_long_date(pdata+8,sbuf.st_atime);
2483 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2484 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2485 SIVAL(pdata,32,mode);
2487 DEBUG(5,("SMB_QFBI - "));
2489 time_t create_time = c_time;
2490 DEBUG(5,("create: %s ", ctime(&create_time)));
2492 DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2493 DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2494 DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2495 DEBUG(5,("mode: %x\n", mode));
2497 break;
2499 case SMB_FILE_STANDARD_INFORMATION:
2500 case SMB_QUERY_FILE_STANDARD_INFO:
2502 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2503 data_size = 24;
2504 SOFF_T(pdata,0,allocation_size);
2505 SOFF_T(pdata,8,file_size);
2506 if (delete_pending & sbuf.st_nlink)
2507 SIVAL(pdata,16,sbuf.st_nlink - 1);
2508 else
2509 SIVAL(pdata,16,sbuf.st_nlink);
2510 SCVAL(pdata,20,0);
2511 SCVAL(pdata,21,(mode&aDIR)?1:0);
2512 break;
2514 case SMB_FILE_EA_INFORMATION:
2515 case SMB_QUERY_FILE_EA_INFO:
2517 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2518 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2519 data_size = 4;
2520 SIVAL(pdata,0,ea_size);
2521 break;
2524 /* Get the 8.3 name - used if NT SMB was negotiated. */
2525 case SMB_QUERY_FILE_ALT_NAME_INFO:
2526 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2528 pstring short_name;
2530 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2531 pstrcpy(short_name,base_name);
2532 /* Mangle if not already 8.3 */
2533 if(!mangle_is_8_3(short_name, True)) {
2534 mangle_map(short_name,True,True,SNUM(conn));
2536 len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2537 data_size = 4 + len;
2538 SIVAL(pdata,0,len);
2539 break;
2542 case SMB_QUERY_FILE_NAME_INFO:
2544 this must be *exactly* right for ACLs on mapped drives to work
2546 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2547 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2548 data_size = 4 + len;
2549 SIVAL(pdata,0,len);
2550 break;
2552 case SMB_FILE_ALLOCATION_INFORMATION:
2553 case SMB_QUERY_FILE_ALLOCATION_INFO:
2554 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2555 data_size = 8;
2556 SOFF_T(pdata,0,allocation_size);
2557 break;
2559 case SMB_FILE_END_OF_FILE_INFORMATION:
2560 case SMB_QUERY_FILE_END_OF_FILEINFO:
2561 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2562 data_size = 8;
2563 SOFF_T(pdata,0,file_size);
2564 break;
2566 case SMB_QUERY_FILE_ALL_INFO:
2567 case SMB_FILE_ALL_INFORMATION:
2569 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2570 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2571 put_long_date(pdata,c_time);
2572 put_long_date(pdata+8,sbuf.st_atime);
2573 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2574 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2575 SIVAL(pdata,32,mode);
2576 pdata += 40;
2577 SOFF_T(pdata,0,allocation_size);
2578 SOFF_T(pdata,8,file_size);
2579 if (delete_pending && sbuf.st_nlink)
2580 SIVAL(pdata,16,sbuf.st_nlink - 1);
2581 else
2582 SIVAL(pdata,16,sbuf.st_nlink);
2583 SCVAL(pdata,20,delete_pending);
2584 SCVAL(pdata,21,(mode&aDIR)?1:0);
2585 pdata += 24;
2586 SIVAL(pdata,0,ea_size);
2587 pdata += 4; /* EA info */
2588 len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2589 SIVAL(pdata,0,len);
2590 pdata += 4 + len;
2591 data_size = PTR_DIFF(pdata,(*ppdata));
2592 break;
2594 case SMB_FILE_INTERNAL_INFORMATION:
2595 /* This should be an index number - looks like
2596 dev/ino to me :-)
2598 I think this causes us to fail the IFSKIT
2599 BasicFileInformationTest. -tpot */
2601 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2602 SIVAL(pdata,0,sbuf.st_dev);
2603 SIVAL(pdata,4,sbuf.st_ino);
2604 data_size = 8;
2605 break;
2607 case SMB_FILE_ACCESS_INFORMATION:
2608 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2609 SIVAL(pdata,0,desired_access);
2610 data_size = 4;
2611 break;
2613 case SMB_FILE_NAME_INFORMATION:
2614 /* Pathname with leading '\'. */
2616 size_t byte_len;
2617 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2618 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2619 SIVAL(pdata,0,byte_len);
2620 data_size = 4 + byte_len;
2621 break;
2624 case SMB_FILE_DISPOSITION_INFORMATION:
2625 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2626 data_size = 1;
2627 SCVAL(pdata,0,delete_pending);
2628 break;
2630 case SMB_FILE_POSITION_INFORMATION:
2631 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2632 data_size = 8;
2633 SOFF_T(pdata,0,pos);
2634 break;
2636 case SMB_FILE_MODE_INFORMATION:
2637 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2638 SIVAL(pdata,0,mode);
2639 data_size = 4;
2640 break;
2642 case SMB_FILE_ALIGNMENT_INFORMATION:
2643 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2644 SIVAL(pdata,0,0); /* No alignment needed. */
2645 data_size = 4;
2646 break;
2648 #if 0
2650 * NT4 server just returns "invalid query" to this - if we try to answer
2651 * it then NTws gets a BSOD! (tridge).
2652 * W2K seems to want this. JRA.
2654 case SMB_QUERY_FILE_STREAM_INFO:
2655 #endif
2656 case SMB_FILE_STREAM_INFORMATION:
2657 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2658 if (mode & aDIR) {
2659 data_size = 0;
2660 } else {
2661 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2662 SIVAL(pdata,0,0); /* ??? */
2663 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2664 SOFF_T(pdata,8,file_size);
2665 SIVAL(pdata,16,allocation_size);
2666 SIVAL(pdata,20,0); /* ??? */
2667 data_size = 24 + byte_len;
2669 break;
2671 case SMB_QUERY_COMPRESSION_INFO:
2672 case SMB_FILE_COMPRESSION_INFORMATION:
2673 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2674 SOFF_T(pdata,0,file_size);
2675 SIVAL(pdata,8,0); /* ??? */
2676 SIVAL(pdata,12,0); /* ??? */
2677 data_size = 16;
2678 break;
2680 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2681 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2682 put_long_date(pdata,c_time);
2683 put_long_date(pdata+8,sbuf.st_atime);
2684 put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2685 put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2686 SIVAL(pdata,32,allocation_size);
2687 SOFF_T(pdata,40,file_size);
2688 SIVAL(pdata,48,mode);
2689 SIVAL(pdata,52,0); /* ??? */
2690 data_size = 56;
2691 break;
2693 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2694 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2695 SIVAL(pdata,0,mode);
2696 SIVAL(pdata,4,0);
2697 data_size = 8;
2698 break;
2701 * CIFS UNIX Extensions.
2704 case SMB_QUERY_FILE_UNIX_BASIC:
2706 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2707 DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2709 SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
2710 pdata += 8;
2712 SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2713 pdata += 8;
2715 put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
2716 put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
2717 put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
2718 pdata += 24;
2720 SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
2721 SIVAL(pdata,4,0);
2722 pdata += 8;
2724 SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
2725 SIVAL(pdata,4,0);
2726 pdata += 8;
2728 SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2729 pdata += 4;
2731 SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
2732 SIVAL(pdata,4,0);
2733 pdata += 8;
2735 SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
2736 SIVAL(pdata,4,0);
2737 pdata += 8;
2739 SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
2740 pdata += 8;
2742 SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
2743 SIVAL(pdata,4,0);
2744 pdata += 8;
2746 SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
2747 SIVAL(pdata,4,0);
2748 pdata += 8+1;
2749 data_size = PTR_DIFF(pdata,(*ppdata));
2752 int i;
2753 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2755 for (i=0; i<100; i++)
2756 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2757 DEBUG(4,("\n"));
2760 break;
2762 case SMB_QUERY_FILE_UNIX_LINK:
2764 pstring buffer;
2766 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
2767 #ifdef S_ISLNK
2768 if(!S_ISLNK(sbuf.st_mode))
2769 return(UNIXERROR(ERRSRV,ERRbadlink));
2770 #else
2771 return(UNIXERROR(ERRDOS,ERRbadlink));
2772 #endif
2773 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
2774 if (len == -1)
2775 return(UNIXERROR(ERRDOS,ERRnoaccess));
2776 buffer[len] = 0;
2777 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2778 pdata += len;
2779 data_size = PTR_DIFF(pdata,(*ppdata));
2781 break;
2784 default:
2785 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2788 send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
2790 return(-1);
2793 /****************************************************************************
2794 Deal with the internal needs of setting the delete on close flag. Note that
2795 as the tdb locking is recursive, it is safe to call this from within
2796 open_file_shared. JRA.
2797 ****************************************************************************/
2799 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
2802 * Only allow delete on close for writable shares.
2805 if (delete_on_close && !CAN_WRITE(fsp->conn)) {
2806 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
2807 fsp->fsp_name ));
2808 return NT_STATUS_ACCESS_DENIED;
2811 * Only allow delete on close for files/directories opened with delete intent.
2814 if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
2815 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
2816 fsp->fsp_name ));
2817 return NT_STATUS_ACCESS_DENIED;
2820 if(fsp->is_directory) {
2821 fsp->directory_delete_on_close = delete_on_close;
2822 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
2823 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2824 } else {
2825 fsp->delete_on_close = delete_on_close;
2826 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
2827 delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
2830 return NT_STATUS_OK;
2833 /****************************************************************************
2834 Sets the delete on close flag over all share modes on this file.
2835 Modify the share mode entry for all files open
2836 on this device and inode to tell other smbds we have
2837 changed the delete on close flag. This will be noticed
2838 in the close code, the last closer will delete the file
2839 if flag is set.
2840 ****************************************************************************/
2842 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
2844 DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
2845 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
2847 if (fsp->is_directory || fsp->is_stat)
2848 return NT_STATUS_OK;
2850 if (lock_share_entry_fsp(fsp) == False)
2851 return NT_STATUS_ACCESS_DENIED;
2853 if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
2854 DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
2855 fsp->fsp_name ));
2856 unlock_share_entry_fsp(fsp);
2857 return NT_STATUS_ACCESS_DENIED;
2860 unlock_share_entry_fsp(fsp);
2861 return NT_STATUS_OK;
2864 /****************************************************************************
2865 Returns true if this pathname is within the share, and thus safe.
2866 ****************************************************************************/
2868 static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
2870 #ifdef PATH_MAX
2871 char resolved_name[PATH_MAX+1];
2872 #else
2873 pstring resolved_name;
2874 #endif
2875 fstring last_component;
2876 pstring link_dest;
2877 pstring link_test;
2878 char *p;
2879 BOOL bad_path = False;
2880 SMB_STRUCT_STAT sbuf;
2882 pstrcpy(link_dest, link_dest_in);
2883 unix_convert(link_dest,conn,0,&bad_path,&sbuf);
2885 /* Store the UNIX converted path. */
2886 pstrcpy(link_dest_out, link_dest);
2888 p = strrchr(link_dest, '/');
2889 if (p) {
2890 fstrcpy(last_component, p+1);
2891 *p = '\0';
2892 } else {
2893 fstrcpy(last_component, link_dest);
2894 pstrcpy(link_dest, "./");
2897 if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL)
2898 return -1;
2900 pstrcpy(link_dest, resolved_name);
2901 pstrcat(link_dest, "/");
2902 pstrcat(link_dest, last_component);
2904 if (*link_dest != '/') {
2905 /* Relative path. */
2906 pstrcpy(link_test, conn->connectpath);
2907 pstrcat(link_test, "/");
2908 pstrcat(link_test, link_dest);
2909 } else {
2910 pstrcpy(link_test, link_dest);
2914 * Check if the link is within the share.
2917 if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
2918 errno = EACCES;
2919 return -1;
2921 return 0;
2924 /****************************************************************************
2925 Set a hard link (called by UNIX extensions and by NT rename with HARD link
2926 code.
2927 ****************************************************************************/
2929 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
2931 BOOL bad_path_oldname = False;
2932 BOOL bad_path_newname = False;
2933 SMB_STRUCT_STAT sbuf1, sbuf2;
2934 BOOL rc, rcdest;
2935 pstring last_component_oldname;
2936 pstring last_component_newname;
2937 NTSTATUS status = NT_STATUS_OK;
2939 ZERO_STRUCT(sbuf1);
2940 ZERO_STRUCT(sbuf2);
2942 /* No wildcards. */
2943 if (ms_has_wild(newname) || ms_has_wild(oldname)) {
2944 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
2947 rc = unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
2948 if (!rc && bad_path_oldname) {
2949 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2952 /* Quick check for "." and ".." */
2953 if (last_component_oldname[0] == '.') {
2954 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
2955 return NT_STATUS_OBJECT_NAME_INVALID;
2959 /* source must already exist. */
2960 if (!VALID_STAT(sbuf1)) {
2961 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2964 rcdest = unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
2965 if (!rcdest && bad_path_newname) {
2966 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
2969 /* Quick check for "." and ".." */
2970 if (last_component_newname[0] == '.') {
2971 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
2972 return NT_STATUS_OBJECT_NAME_INVALID;
2976 /* Disallow if newname already exists. */
2977 if (VALID_STAT(sbuf2)) {
2978 return NT_STATUS_OBJECT_NAME_COLLISION;
2981 /* No links from a directory. */
2982 if (S_ISDIR(sbuf1.st_mode)) {
2983 return NT_STATUS_FILE_IS_A_DIRECTORY;
2986 if (ensure_link_is_safe(conn, oldname, oldname) != 0)
2987 return NT_STATUS_ACCESS_DENIED;
2989 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
2991 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
2992 status = map_nt_error_from_unix(errno);
2993 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
2994 nt_errstr(status), newname, oldname));
2997 return status;
3000 /****************************************************************************
3001 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3002 ****************************************************************************/
3004 static int call_trans2setfilepathinfo(connection_struct *conn,
3005 char *inbuf, char *outbuf, int length, int bufsize,
3006 char **pparams, int total_params, char **ppdata, int total_data)
3008 char *params = *pparams;
3009 char *pdata = *ppdata;
3010 uint16 tran_call = SVAL(inbuf, smb_setup0);
3011 uint16 info_level;
3012 int dosmode=0;
3013 SMB_OFF_T size=0;
3014 struct utimbuf tvs;
3015 SMB_STRUCT_STAT sbuf;
3016 pstring fname;
3017 int fd = -1;
3018 BOOL bad_path = False;
3019 files_struct *fsp = NULL;
3020 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3021 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3022 mode_t unixmode = 0;
3023 NTSTATUS status = NT_STATUS_OK;
3025 if (!params)
3026 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3028 if (tran_call == TRANSACT2_SETFILEINFO) {
3029 if (total_params < 4)
3030 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3032 fsp = file_fsp(params,0);
3033 info_level = SVAL(params,2);
3035 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3037 * This is actually a SETFILEINFO on a directory
3038 * handle (returned from an NT SMB). NT5.0 seems
3039 * to do this call. JRA.
3041 pstrcpy(fname, fsp->fsp_name);
3042 unix_convert(fname,conn,0,&bad_path,&sbuf);
3043 if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
3044 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3045 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3047 } else if (fsp && fsp->print_file) {
3049 * Doing a DELETE_ON_CLOSE should cancel a print job.
3051 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3052 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3054 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3056 SSVAL(params,0,0);
3057 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3058 return(-1);
3059 } else
3060 return (UNIXERROR(ERRDOS,ERRbadpath));
3061 } else {
3063 * Original code - this is an open file.
3065 CHECK_FSP(fsp,conn);
3067 pstrcpy(fname, fsp->fsp_name);
3068 fd = fsp->fd;
3070 if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3071 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3072 return(UNIXERROR(ERRDOS,ERRbadfid));
3075 } else {
3076 /* set path info */
3077 if (total_params < 6)
3078 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3080 info_level = SVAL(params,0);
3081 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
3082 if (!NT_STATUS_IS_OK(status)) {
3083 return ERROR_NT(status);
3085 unix_convert(fname,conn,0,&bad_path,&sbuf);
3088 * For CIFS UNIX extensions the target name may not exist.
3091 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3092 DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3093 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3096 if(!check_name(fname, conn)) {
3097 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3102 if (!CAN_WRITE(conn))
3103 return ERROR_DOS(ERRSRV,ERRaccess);
3105 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3106 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3108 if (VALID_STAT(sbuf))
3109 unixmode = sbuf.st_mode;
3111 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3112 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3114 /* Realloc the parameter and data sizes */
3115 params = Realloc(*pparams,2);
3116 if(params == NULL)
3117 return ERROR_DOS(ERRDOS,ERRnomem);
3118 *pparams = params;
3120 SSVAL(params,0,0);
3122 if (fsp) {
3123 /* the pending modtime overrides the current modtime */
3124 sbuf.st_mtime = fsp->pending_modtime;
3127 size = get_file_size(sbuf);
3128 tvs.modtime = sbuf.st_mtime;
3129 tvs.actime = sbuf.st_atime;
3130 dosmode = dos_mode(conn,fname,&sbuf);
3131 unixmode = sbuf.st_mode;
3133 set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3134 set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3136 switch (info_level) {
3137 case SMB_INFO_STANDARD:
3139 if (total_data < 12)
3140 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3142 /* access time */
3143 tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3144 /* write time */
3145 tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3146 break;
3149 case SMB_INFO_SET_EA:
3150 status = set_ea(conn, fsp, fname, pdata, total_data);
3151 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3152 return ERROR_NT(status);
3153 break;
3155 /* XXXX um, i don't think this is right.
3156 it's also not in the cifs6.txt spec.
3158 case SMB_INFO_QUERY_EAS_FROM_LIST:
3159 if (total_data < 28)
3160 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3162 tvs.actime = make_unix_date2(pdata+8);
3163 tvs.modtime = make_unix_date2(pdata+12);
3164 size = IVAL(pdata,16);
3165 dosmode = IVAL(pdata,24);
3166 break;
3168 /* XXXX nor this. not in cifs6.txt, either. */
3169 case SMB_INFO_QUERY_ALL_EAS:
3170 if (total_data < 28)
3171 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3173 tvs.actime = make_unix_date2(pdata+8);
3174 tvs.modtime = make_unix_date2(pdata+12);
3175 size = IVAL(pdata,16);
3176 dosmode = IVAL(pdata,24);
3177 break;
3179 case SMB_SET_FILE_BASIC_INFO:
3180 case SMB_FILE_BASIC_INFORMATION:
3182 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3183 time_t write_time;
3184 time_t changed_time;
3186 if (total_data < 36)
3187 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3189 /* Ignore create time at offset pdata. */
3191 /* access time */
3192 tvs.actime = interpret_long_date(pdata+8);
3194 write_time = interpret_long_date(pdata+16);
3195 changed_time = interpret_long_date(pdata+24);
3197 tvs.modtime = MIN(write_time, changed_time);
3199 if (write_time > tvs.modtime && write_time != 0xffffffff) {
3200 tvs.modtime = write_time;
3202 /* Prefer a defined time to an undefined one. */
3203 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3204 tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
3205 ? changed_time : write_time);
3207 /* attributes */
3208 dosmode = IVAL(pdata,32);
3209 break;
3212 case SMB_FILE_ALLOCATION_INFORMATION:
3213 case SMB_SET_FILE_ALLOCATION_INFO:
3215 int ret = -1;
3216 SMB_BIG_UINT allocation_size;
3218 if (total_data < 8)
3219 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3221 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3222 #ifdef LARGE_SMB_OFF_T
3223 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3224 #else /* LARGE_SMB_OFF_T */
3225 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3226 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3227 #endif /* LARGE_SMB_OFF_T */
3228 DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3229 fname, (double)allocation_size ));
3231 if (allocation_size)
3232 allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
3234 if(allocation_size != get_file_size(sbuf)) {
3235 SMB_STRUCT_STAT new_sbuf;
3237 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3238 fname, (double)allocation_size ));
3240 if (fd == -1) {
3241 files_struct *new_fsp = NULL;
3242 int access_mode = 0;
3243 int action = 0;
3245 if(global_oplock_break) {
3246 /* Queue this file modify as we are the process of an oplock break. */
3248 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3249 DEBUGADD(2,( "in oplock break state.\n"));
3251 push_oplock_pending_smb_message(inbuf, length);
3252 return -1;
3255 new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3256 SET_OPEN_MODE(DOS_OPEN_RDWR),
3257 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3258 FILE_ATTRIBUTE_NORMAL,
3259 0, &access_mode, &action);
3261 if (new_fsp == NULL)
3262 return(UNIXERROR(ERRDOS,ERRbadpath));
3263 ret = vfs_allocate_file_space(new_fsp, allocation_size);
3264 if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3265 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3266 new_fsp->fnum, strerror(errno)));
3267 ret = -1;
3269 close_file(new_fsp,True);
3270 } else {
3271 ret = vfs_allocate_file_space(fsp, allocation_size);
3272 if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3273 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3274 fsp->fnum, strerror(errno)));
3275 ret = -1;
3278 if (ret == -1)
3279 return ERROR_NT(NT_STATUS_DISK_FULL);
3281 /* Allocate can truncate size... */
3282 size = get_file_size(new_sbuf);
3285 break;
3288 case SMB_FILE_END_OF_FILE_INFORMATION:
3289 case SMB_SET_FILE_END_OF_FILE_INFO:
3291 if (total_data < 8)
3292 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3294 size = IVAL(pdata,0);
3295 #ifdef LARGE_SMB_OFF_T
3296 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3297 #else /* LARGE_SMB_OFF_T */
3298 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3299 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3300 #endif /* LARGE_SMB_OFF_T */
3301 DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3302 break;
3305 case SMB_FILE_DISPOSITION_INFORMATION:
3306 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3308 BOOL delete_on_close;
3310 if (total_data < 1)
3311 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3313 delete_on_close = (CVAL(pdata,0) ? True : False);
3315 /* Just ignore this set on a path. */
3316 if (tran_call != TRANSACT2_SETFILEINFO)
3317 break;
3319 if (fsp == NULL)
3320 return(UNIXERROR(ERRDOS,ERRbadfid));
3322 status = set_delete_on_close_internal(fsp, delete_on_close);
3324 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3325 return ERROR_NT(status);
3327 /* The set is across all open files on this dev/inode pair. */
3328 status =set_delete_on_close_over_all(fsp, delete_on_close);
3329 if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
3330 return ERROR_NT(status);
3332 break;
3335 case SMB_FILE_POSITION_INFORMATION:
3337 SMB_BIG_UINT position_information;
3339 if (total_data < 8)
3340 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3342 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3343 #ifdef LARGE_SMB_OFF_T
3344 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3345 #else /* LARGE_SMB_OFF_T */
3346 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3347 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3348 #endif /* LARGE_SMB_OFF_T */
3349 DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3350 fname, (double)position_information ));
3351 if (fsp)
3352 fsp->position_information = position_information;
3353 break;
3357 * CIFS UNIX extensions.
3360 case SMB_SET_FILE_UNIX_BASIC:
3362 uint32 raw_unixmode;
3364 if (total_data < 100)
3365 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3367 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3368 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3369 size=IVAL(pdata,0); /* first 8 Bytes are size */
3370 #ifdef LARGE_SMB_OFF_T
3371 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3372 #else /* LARGE_SMB_OFF_T */
3373 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3374 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3375 #endif /* LARGE_SMB_OFF_T */
3377 pdata+=24; /* ctime & st_blocks are not changed */
3378 tvs.actime = interpret_long_unix_date(pdata); /* access_time */
3379 tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
3380 pdata+=16;
3381 set_owner = (uid_t)IVAL(pdata,0);
3382 pdata += 8;
3383 set_grp = (gid_t)IVAL(pdata,0);
3384 pdata += 8;
3385 raw_unixmode = IVAL(pdata,28);
3386 unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3387 dosmode = 0; /* Ensure dos mode change doesn't override this. */
3389 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3390 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3391 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3393 if (!VALID_STAT(sbuf)) {
3396 * The only valid use of this is to create character and block
3397 * devices, and named pipes. This is deprecated (IMHO) and
3398 * a new info level should be used for mknod. JRA.
3401 #if !defined(HAVE_MAKEDEV_FN)
3402 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3403 #else /* HAVE_MAKEDEV_FN */
3404 uint32 file_type = IVAL(pdata,0);
3405 uint32 dev_major = IVAL(pdata,4);
3406 uint32 dev_minor = IVAL(pdata,12);
3408 uid_t myuid = geteuid();
3409 gid_t mygid = getegid();
3410 SMB_DEV_T dev;
3412 if (tran_call == TRANSACT2_SETFILEINFO)
3413 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3415 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3416 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3418 dev = makedev(dev_major, dev_minor);
3420 /* We can only create as the owner/group we are. */
3422 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3423 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3424 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3425 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3427 if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
3428 file_type != UNIX_TYPE_FIFO)
3429 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3431 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3432 0%o for file %s\n", (double)dev, unixmode, fname ));
3434 /* Ok - do the mknod. */
3435 if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
3436 return(UNIXERROR(ERRDOS,ERRnoaccess));
3438 inherit_access_acl(conn, fname, unixmode);
3440 SSVAL(params,0,0);
3441 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3442 return(-1);
3443 #endif /* HAVE_MAKEDEV_FN */
3448 * Deal with the UNIX specific mode set.
3451 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3452 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3453 (unsigned int)unixmode, fname ));
3454 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3455 return(UNIXERROR(ERRDOS,ERRnoaccess));
3459 * Deal with the UNIX specific uid set.
3462 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3463 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3464 (unsigned int)set_owner, fname ));
3465 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3466 return(UNIXERROR(ERRDOS,ERRnoaccess));
3470 * Deal with the UNIX specific gid set.
3473 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3474 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3475 (unsigned int)set_owner, fname ));
3476 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3477 return(UNIXERROR(ERRDOS,ERRnoaccess));
3479 break;
3482 case SMB_SET_FILE_UNIX_LINK:
3484 pstring oldname;
3485 char *newname = fname;
3487 /* Set a symbolic link. */
3488 /* Don't allow this if follow links is false. */
3490 if (!lp_symlinks(SNUM(conn)))
3491 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3493 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
3494 if (!NT_STATUS_IS_OK(status)) {
3495 return ERROR_NT(status);
3498 if (ensure_link_is_safe(conn, oldname, oldname) != 0)
3499 return(UNIXERROR(ERRDOS,ERRnoaccess));
3501 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3502 fname, oldname ));
3504 if (SMB_VFS_SYMLINK(conn,oldname,newname) != 0)
3505 return(UNIXERROR(ERRDOS,ERRnoaccess));
3506 SSVAL(params,0,0);
3507 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3508 return(-1);
3511 case SMB_SET_FILE_UNIX_HLINK:
3513 pstring oldname;
3514 char *newname = fname;
3516 /* Set a hard link. */
3517 srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
3518 if (!NT_STATUS_IS_OK(status)) {
3519 return ERROR_NT(status);
3522 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3523 fname, oldname));
3525 status = hardlink_internals(conn, oldname, newname);
3526 if (!NT_STATUS_IS_OK(status)) {
3527 return ERROR_NT(status);
3530 SSVAL(params,0,0);
3531 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3532 return(-1);
3535 case SMB_FILE_RENAME_INFORMATION:
3537 BOOL overwrite;
3538 uint32 root_fid;
3539 uint32 len;
3540 pstring newname;
3541 pstring base_name;
3542 char *p;
3544 if (total_data < 12)
3545 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3547 overwrite = (CVAL(pdata,0) ? True : False);
3548 root_fid = IVAL(pdata,4);
3549 len = IVAL(pdata,8);
3550 srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
3551 if (!NT_STATUS_IS_OK(status)) {
3552 return ERROR_NT(status);
3555 /* Check the new name has no '/' characters. */
3556 if (strchr_m(newname, '/'))
3557 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3559 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3561 /* Create the base directory. */
3562 pstrcpy(base_name, fname);
3563 p = strrchr_m(base_name, '/');
3564 if (p)
3565 *p = '\0';
3566 /* Append the new name. */
3567 pstrcat(base_name, "/");
3568 pstrcat(base_name, newname);
3570 if (fsp) {
3571 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3572 fsp->fnum, fsp->fsp_name, base_name ));
3573 status = rename_internals_fsp(conn, fsp, base_name, overwrite);
3574 } else {
3575 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3576 fname, newname ));
3577 status = rename_internals(conn, fname, base_name, 0, overwrite);
3579 if (!NT_STATUS_IS_OK(status)) {
3580 return ERROR_NT(status);
3582 process_pending_change_notify_queue((time_t)0);
3583 SSVAL(params,0,0);
3584 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3585 return(-1);
3587 default:
3588 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3591 /* get some defaults (no modifications) if any info is zero or -1. */
3592 if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
3593 tvs.actime = sbuf.st_atime;
3595 if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
3596 tvs.modtime = sbuf.st_mtime;
3598 DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3599 DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3600 DEBUG(6,("size: %.0f ", (double)size));
3602 if (dosmode) {
3603 if (S_ISDIR(sbuf.st_mode))
3604 dosmode |= aDIR;
3605 else
3606 dosmode &= ~aDIR;
3609 DEBUG(6,("dosmode: %x\n" , dosmode));
3611 if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3612 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3613 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3614 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3617 * Only do this test if we are not explicitly
3618 * changing the size of a file.
3620 if (!size)
3621 size = get_file_size(sbuf);
3625 * Try and set the times, size and mode of this file -
3626 * if they are different from the current values
3628 if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
3629 if(fsp != NULL) {
3631 * This was a setfileinfo on an open file.
3632 * NT does this a lot. It's actually pointless
3633 * setting the time here, as it will be overwritten
3634 * on the next write, so we save the request
3635 * away and will set it on file close. JRA.
3638 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3639 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3640 fsp->pending_modtime = tvs.modtime;
3643 } else {
3645 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
3647 if(file_utime(conn, fname, &tvs)!=0)
3648 return(UNIXERROR(ERRDOS,ERRnoaccess));
3652 /* check the mode isn't different, before changing it */
3653 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3655 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3657 if(file_set_dosmode(conn, fname, dosmode, NULL)) {
3658 DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
3659 return(UNIXERROR(ERRDOS,ERRnoaccess));
3663 if (size != get_file_size(sbuf)) {
3665 int ret;
3667 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3668 fname, (double)size ));
3670 if (fd == -1) {
3671 files_struct *new_fsp = NULL;
3672 int access_mode = 0;
3673 int action = 0;
3675 if(global_oplock_break) {
3676 /* Queue this file modify as we are the process of an oplock break. */
3678 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3679 DEBUGADD(2,( "in oplock break state.\n"));
3681 push_oplock_pending_smb_message(inbuf, length);
3682 return -1;
3685 new_fsp = open_file_shared(conn, fname, &sbuf,
3686 SET_OPEN_MODE(DOS_OPEN_RDWR),
3687 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3688 FILE_ATTRIBUTE_NORMAL,
3689 0, &access_mode, &action);
3691 if (new_fsp == NULL)
3692 return(UNIXERROR(ERRDOS,ERRbadpath));
3693 ret = vfs_set_filelen(new_fsp, size);
3694 close_file(new_fsp,True);
3695 } else {
3696 ret = vfs_set_filelen(fsp, size);
3699 if (ret == -1)
3700 return (UNIXERROR(ERRHRD,ERRdiskfull));
3703 SSVAL(params,0,0);
3704 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3706 return(-1);
3709 /****************************************************************************
3710 Reply to a TRANS2_MKDIR (make directory with extended attributes).
3711 ****************************************************************************/
3713 static int call_trans2mkdir(connection_struct *conn,
3714 char *inbuf, char *outbuf, int length, int bufsize,
3715 char **pparams, int total_params, char **ppdata, int total_data)
3717 char *params = *pparams;
3718 pstring directory;
3719 int ret = -1;
3720 SMB_STRUCT_STAT sbuf;
3721 BOOL bad_path = False;
3722 NTSTATUS status = NT_STATUS_OK;
3724 if (!CAN_WRITE(conn))
3725 return ERROR_DOS(ERRSRV,ERRaccess);
3727 if (total_params < 4)
3728 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3730 srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status);
3731 if (!NT_STATUS_IS_OK(status)) {
3732 return ERROR_NT(status);
3735 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
3737 unix_convert(directory,conn,0,&bad_path,&sbuf);
3738 if (check_name(directory,conn))
3739 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3741 if(ret < 0) {
3742 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
3743 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
3746 /* Realloc the parameter and data sizes */
3747 params = Realloc(*pparams,2);
3748 if(params == NULL)
3749 return ERROR_DOS(ERRDOS,ERRnomem);
3750 *pparams = params;
3752 SSVAL(params,0,0);
3754 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3756 return(-1);
3759 /****************************************************************************
3760 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
3761 We don't actually do this - we just send a null response.
3762 ****************************************************************************/
3764 static int call_trans2findnotifyfirst(connection_struct *conn,
3765 char *inbuf, char *outbuf, int length, int bufsize,
3766 char **pparams, int total_params, char **ppdata, int total_data)
3768 static uint16 fnf_handle = 257;
3769 char *params = *pparams;
3770 uint16 info_level;
3772 if (total_params < 6)
3773 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3775 info_level = SVAL(params,4);
3776 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
3778 switch (info_level) {
3779 case 1:
3780 case 2:
3781 break;
3782 default:
3783 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3786 /* Realloc the parameter and data sizes */
3787 params = Realloc(*pparams,6);
3788 if(params == NULL)
3789 return ERROR_DOS(ERRDOS,ERRnomem);
3790 *pparams = params;
3792 SSVAL(params,0,fnf_handle);
3793 SSVAL(params,2,0); /* No changes */
3794 SSVAL(params,4,0); /* No EA errors */
3796 fnf_handle++;
3798 if(fnf_handle == 0)
3799 fnf_handle = 257;
3801 send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
3803 return(-1);
3806 /****************************************************************************
3807 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
3808 changes). Currently this does nothing.
3809 ****************************************************************************/
3811 static int call_trans2findnotifynext(connection_struct *conn,
3812 char *inbuf, char *outbuf, int length, int bufsize,
3813 char **pparams, int total_params, char **ppdata, int total_data)
3815 char *params = *pparams;
3817 DEBUG(3,("call_trans2findnotifynext\n"));
3819 /* Realloc the parameter and data sizes */
3820 params = Realloc(*pparams,4);
3821 if(params == NULL)
3822 return ERROR_DOS(ERRDOS,ERRnomem);
3823 *pparams = params;
3825 SSVAL(params,0,0); /* No changes */
3826 SSVAL(params,2,0); /* No EA errors */
3828 send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
3830 return(-1);
3833 /****************************************************************************
3834 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
3835 ****************************************************************************/
3837 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
3838 char* outbuf, int length, int bufsize,
3839 char **pparams, int total_params, char **ppdata, int total_data)
3841 char *params = *pparams;
3842 pstring pathname;
3843 int reply_size = 0;
3844 int max_referral_level;
3846 DEBUG(10,("call_trans2getdfsreferral\n"));
3848 if (total_params < 2)
3849 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3851 max_referral_level = SVAL(params,0);
3853 if(!lp_host_msdfs())
3854 return ERROR_DOS(ERRDOS,ERRbadfunc);
3856 srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
3857 if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
3858 return UNIXERROR(ERRDOS,ERRbadfile);
3860 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
3861 send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
3863 return(-1);
3866 #define LMCAT_SPL 0x53
3867 #define LMFUNC_GETJOBID 0x60
3869 /****************************************************************************
3870 Reply to a TRANS2_IOCTL - used for OS/2 printing.
3871 ****************************************************************************/
3873 static int call_trans2ioctl(connection_struct *conn, char* inbuf,
3874 char* outbuf, int length, int bufsize,
3875 char **pparams, int total_params, char **ppdata, int total_data)
3877 char *pdata = *ppdata;
3878 files_struct *fsp = file_fsp(inbuf,smb_vwv15);
3880 /* check for an invalid fid before proceeding */
3882 if (!fsp)
3883 return(ERROR_DOS(ERRDOS,ERRbadfid));
3885 if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
3886 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
3887 pdata = Realloc(*ppdata, 32);
3888 if(pdata == NULL)
3889 return ERROR_DOS(ERRDOS,ERRnomem);
3890 *ppdata = pdata;
3892 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
3893 CAN ACCEPT THIS IN UNICODE. JRA. */
3895 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
3896 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
3897 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
3898 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
3899 return(-1);
3900 } else {
3901 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
3902 return ERROR_DOS(ERRSRV,ERRerror);
3906 /****************************************************************************
3907 Reply to a SMBfindclose (stop trans2 directory search).
3908 ****************************************************************************/
3910 int reply_findclose(connection_struct *conn,
3911 char *inbuf,char *outbuf,int length,int bufsize)
3913 int outsize = 0;
3914 int dptr_num=SVALS(inbuf,smb_vwv0);
3915 START_PROFILE(SMBfindclose);
3917 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
3919 dptr_close(&dptr_num);
3921 outsize = set_message(outbuf,0,0,True);
3923 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
3925 END_PROFILE(SMBfindclose);
3926 return(outsize);
3929 /****************************************************************************
3930 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
3931 ****************************************************************************/
3933 int reply_findnclose(connection_struct *conn,
3934 char *inbuf,char *outbuf,int length,int bufsize)
3936 int outsize = 0;
3937 int dptr_num= -1;
3938 START_PROFILE(SMBfindnclose);
3940 dptr_num = SVAL(inbuf,smb_vwv0);
3942 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
3944 /* We never give out valid handles for a
3945 findnotifyfirst - so any dptr_num is ok here.
3946 Just ignore it. */
3948 outsize = set_message(outbuf,0,0,True);
3950 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
3952 END_PROFILE(SMBfindnclose);
3953 return(outsize);
3956 /****************************************************************************
3957 Reply to a SMBtranss2 - just ignore it!
3958 ****************************************************************************/
3960 int reply_transs2(connection_struct *conn,
3961 char *inbuf,char *outbuf,int length,int bufsize)
3963 START_PROFILE(SMBtranss2);
3964 DEBUG(4,("Ignoring transs2 of length %d\n",length));
3965 END_PROFILE(SMBtranss2);
3966 return(-1);
3969 /****************************************************************************
3970 Reply to a SMBtrans2.
3971 ****************************************************************************/
3973 int reply_trans2(connection_struct *conn,
3974 char *inbuf,char *outbuf,int length,int bufsize)
3976 int outsize = 0;
3977 unsigned int total_params = SVAL(inbuf, smb_tpscnt);
3978 unsigned int total_data =SVAL(inbuf, smb_tdscnt);
3979 #if 0
3980 unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
3981 unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
3982 unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
3983 BOOL close_tid = BITSETW(inbuf+smb_flags,0);
3984 BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
3985 int32 timeout = IVALS(inbuf,smb_timeout);
3986 #endif
3987 unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
3988 unsigned int tran_call = SVAL(inbuf, smb_setup0);
3989 char *params = NULL, *data = NULL;
3990 unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
3991 START_PROFILE(SMBtrans2);
3993 if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
3994 /* Queue this open message as we are the process of an
3995 * oplock break. */
3997 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
3998 DEBUGADD(2,( "in oplock break state.\n"));
4000 push_oplock_pending_smb_message(inbuf, length);
4001 END_PROFILE(SMBtrans2);
4002 return -1;
4005 if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4006 && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4007 END_PROFILE(SMBtrans2);
4008 return ERROR_DOS(ERRSRV,ERRaccess);
4011 outsize = set_message(outbuf,0,0,True);
4013 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4014 is so as a sanity check */
4015 if (suwcnt != 1) {
4017 * Need to have rc=0 for ioctl to get job id for OS/2.
4018 * Network printing will fail if function is not successful.
4019 * Similar function in reply.c will be used if protocol
4020 * is LANMAN1.0 instead of LM1.2X002.
4021 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
4022 * outbuf doesn't have to be set(only job id is used).
4024 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4025 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4026 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4027 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4028 } else {
4029 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4030 DEBUG(2,("Transaction is %d\n",tran_call));
4031 END_PROFILE(SMBtrans2);
4032 ERROR_DOS(ERRDOS,ERRinvalidparam);
4036 /* Allocate the space for the maximum needed parameters and data */
4037 if (total_params > 0)
4038 params = (char *)malloc(total_params);
4039 if (total_data > 0)
4040 data = (char *)malloc(total_data);
4042 if ((total_params && !params) || (total_data && !data)) {
4043 DEBUG(2,("Out of memory in reply_trans2\n"));
4044 SAFE_FREE(params);
4045 SAFE_FREE(data);
4046 END_PROFILE(SMBtrans2);
4047 return ERROR_DOS(ERRDOS,ERRnomem);
4050 /* Copy the param and data bytes sent with this request into
4051 the params buffer */
4052 num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4053 num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4055 if (num_params > total_params || num_data > total_data)
4056 exit_server("invalid params in reply_trans2");
4058 if(params) {
4059 unsigned int psoff = SVAL(inbuf, smb_psoff);
4060 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4061 goto bad_param;
4062 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4063 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4064 goto bad_param;
4065 memcpy( params, smb_base(inbuf) + psoff, num_params);
4067 if(data) {
4068 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4069 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4070 goto bad_param;
4071 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4072 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4073 goto bad_param;
4074 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4077 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4079 if(num_data_sofar < total_data || num_params_sofar < total_params) {
4080 /* We need to send an interim response then receive the rest
4081 of the parameter/data bytes */
4082 outsize = set_message(outbuf,0,0,True);
4083 srv_signing_trans_stop();
4084 if (!send_smb(smbd_server_fd(),outbuf))
4085 exit_server("reply_trans2: send_smb failed.");
4087 while (num_data_sofar < total_data ||
4088 num_params_sofar < total_params) {
4089 BOOL ret;
4090 unsigned int param_disp;
4091 unsigned int param_off;
4092 unsigned int data_disp;
4093 unsigned int data_off;
4095 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4098 * The sequence number for the trans reply is always
4099 * based on the last secondary received.
4102 srv_signing_trans_start(SVAL(inbuf,smb_mid));
4104 if ((ret &&
4105 (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4106 outsize = set_message(outbuf,0,0,True);
4107 if(ret)
4108 DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4109 else
4110 DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4111 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4112 goto bad_param;
4115 /* Revise total_params and total_data in case
4116 they have changed downwards */
4117 if (SVAL(inbuf, smb_tpscnt) < total_params)
4118 total_params = SVAL(inbuf, smb_tpscnt);
4119 if (SVAL(inbuf, smb_tdscnt) < total_data)
4120 total_data = SVAL(inbuf, smb_tdscnt);
4122 num_params = SVAL(inbuf,smb_spscnt);
4123 param_off = SVAL(inbuf, smb_spsoff);
4124 param_disp = SVAL(inbuf, smb_spsdisp);
4125 num_params_sofar += num_params;
4127 num_data = SVAL(inbuf, smb_sdscnt);
4128 data_off = SVAL(inbuf, smb_sdsoff);
4129 data_disp = SVAL(inbuf, smb_sdsdisp);
4130 num_data_sofar += num_data;
4132 if (num_params_sofar > total_params || num_data_sofar > total_data)
4133 goto bad_param;
4135 if (num_params) {
4136 if (param_disp + num_params >= total_params)
4137 goto bad_param;
4138 if ((param_disp + num_params < param_disp) ||
4139 (param_disp + num_params < num_params))
4140 goto bad_param;
4141 if (param_disp > total_params)
4142 goto bad_param;
4143 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4144 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4145 goto bad_param;
4146 if (params + param_disp < params)
4147 goto bad_param;
4149 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4151 if (num_data) {
4152 if (data_disp + num_data >= total_data)
4153 goto bad_param;
4154 if ((data_disp + num_data < data_disp) ||
4155 (data_disp + num_data < num_data))
4156 goto bad_param;
4157 if (data_disp > total_data)
4158 goto bad_param;
4159 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4160 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4161 goto bad_param;
4162 if (data + data_disp < data)
4163 goto bad_param;
4165 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4170 if (Protocol >= PROTOCOL_NT1) {
4171 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4174 /* Now we must call the relevant TRANS2 function */
4175 switch(tran_call) {
4176 case TRANSACT2_OPEN:
4177 START_PROFILE_NESTED(Trans2_open);
4178 outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4179 &params, total_params, &data, total_data);
4180 END_PROFILE_NESTED(Trans2_open);
4181 break;
4183 case TRANSACT2_FINDFIRST:
4184 START_PROFILE_NESTED(Trans2_findfirst);
4185 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4186 &params, total_params, &data, total_data);
4187 END_PROFILE_NESTED(Trans2_findfirst);
4188 break;
4190 case TRANSACT2_FINDNEXT:
4191 START_PROFILE_NESTED(Trans2_findnext);
4192 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4193 &params, total_params, &data, total_data);
4194 END_PROFILE_NESTED(Trans2_findnext);
4195 break;
4197 case TRANSACT2_QFSINFO:
4198 START_PROFILE_NESTED(Trans2_qfsinfo);
4199 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4200 &params, total_params, &data, total_data);
4201 END_PROFILE_NESTED(Trans2_qfsinfo);
4202 break;
4204 #ifdef HAVE_SYS_QUOTAS
4205 case TRANSACT2_SETFSINFO:
4206 START_PROFILE_NESTED(Trans2_setfsinfo);
4207 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4208 &params, total_params, &data, total_data);
4209 END_PROFILE_NESTED(Trans2_setfsinfo);
4210 break;
4211 #endif
4212 case TRANSACT2_QPATHINFO:
4213 case TRANSACT2_QFILEINFO:
4214 START_PROFILE_NESTED(Trans2_qpathinfo);
4215 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4216 &params, total_params, &data, total_data);
4217 END_PROFILE_NESTED(Trans2_qpathinfo);
4218 break;
4219 case TRANSACT2_SETPATHINFO:
4220 case TRANSACT2_SETFILEINFO:
4221 START_PROFILE_NESTED(Trans2_setpathinfo);
4222 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4223 &params, total_params, &data, total_data);
4224 END_PROFILE_NESTED(Trans2_setpathinfo);
4225 break;
4227 case TRANSACT2_FINDNOTIFYFIRST:
4228 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4229 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4230 &params, total_params, &data, total_data);
4231 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4232 break;
4234 case TRANSACT2_FINDNOTIFYNEXT:
4235 START_PROFILE_NESTED(Trans2_findnotifynext);
4236 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4237 &params, total_params, &data, total_data);
4238 END_PROFILE_NESTED(Trans2_findnotifynext);
4239 break;
4240 case TRANSACT2_MKDIR:
4241 START_PROFILE_NESTED(Trans2_mkdir);
4242 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4243 &params, total_params, &data, total_data);
4244 END_PROFILE_NESTED(Trans2_mkdir);
4245 break;
4247 case TRANSACT2_GET_DFS_REFERRAL:
4248 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4249 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4250 &params, total_params, &data, total_data);
4251 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4252 break;
4253 case TRANSACT2_IOCTL:
4254 START_PROFILE_NESTED(Trans2_ioctl);
4255 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4256 &params, total_params, &data, total_data);
4257 END_PROFILE_NESTED(Trans2_ioctl);
4258 break;
4259 default:
4260 /* Error in request */
4261 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4262 SAFE_FREE(params);
4263 SAFE_FREE(data);
4264 END_PROFILE(SMBtrans2);
4265 srv_signing_trans_stop();
4266 return ERROR_DOS(ERRSRV,ERRerror);
4269 /* As we do not know how many data packets will need to be
4270 returned here the various call_trans2xxxx calls
4271 must send their own. Thus a call_trans2xxx routine only
4272 returns a value other than -1 when it wants to send
4273 an error packet.
4276 srv_signing_trans_stop();
4278 SAFE_FREE(params);
4279 SAFE_FREE(data);
4280 END_PROFILE(SMBtrans2);
4281 return outsize; /* If a correct response was needed the
4282 call_trans2xxx calls have already sent
4283 it. If outsize != -1 then it is returning */
4285 bad_param:
4287 srv_signing_trans_stop();
4288 SAFE_FREE(params);
4289 SAFE_FREE(data);
4290 END_PROFILE(SMBtrans2);
4291 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);